68
高高高高高高高高高高 Android 高高高高高 Tel : 0411-8833-5533 Mail: www.pkbest.cn@gmail.com [email protected] Web : http://www.pkbest.cn

Android -汇博

Embed Size (px)

Citation preview

Page 1: Android -汇博

— 高级软件人才培训专家Android

讲师:

杨喜山

Tel : 0411-8833-5533Mail: [email protected] [email protected] : http://www.pkbest.cn

Page 2: Android -汇博

— 高级软件人才培训专家授课内容1.Android 简介2. 应用剖析3. 调试方法4 、 Android 框架 & 设计模式5.UI 主题 样式6. 数据存储7. 电话、短信8. 多媒体9. 网络通信10. 浏览器开发11. 天气预报 & GoogleMap & GPS12. 电源管理13.TextToSpeech14. 传感器15.OpenGL16. 图像处理17. 桌面组件18. 优化技术19. 项目实战20. 最佳实践

Page 3: Android -汇博

— 高级软件人才培训专家Android&3G第三代移动通信技术( 3rd-generation , 3G ) : 是指支持高速数据传输的蜂窝移动通讯技术。 3G 服务能够同时传送声音及数据信息,

速率一般在几百 kbps 以上。目前 3G 存在四种标准: CDMA2000 , WCDMA , TD-SCDMA , WiMAX 。

中国电信的 CDMA2000 日、韩和北美使用 中国联通的 WCDMA 世界上大部分 3G 网络都采用的是该标准 中国移动的 TD-SCDMA 具有自主知识产权 , 只有中国使用 ( 最近又提出 4G 技术 )

3G 网络能处理图像、音乐、视频等多种媒体形式,提供包括网页浏览、电话会议、电子商务等多种信息服务。第三代与前两代的主要区别是在传输声音和数据的速度上有很大的提升。

Android 一词的本义指“机器人”,同时也是 Google 于 2007 年 11 月 5 日宣布的基于Linux 平台的开源手机操作系统的名称,该平台由操作系统、中间件和应用软件组成,号称是首个为移动终端打造的真正开放和完整的移动软件。它采用了软件堆层(software stack ,又名软件叠层 ) 的架构,主要分为三部分:

底层:以 Linux 核心为基础,由 C 语言开发,只提供基本功能。 中间层:包括函数库 Library 和虚拟机 Virtual Machine ,由 C++ 开发。 应用软件:是最上层,包括通话程序,短信程序等,以 Java 编写。

Page 4: Android -汇博

— 高级软件人才培训专家Android 架构

Page 5: Android -汇博

— 高级软件人才培训专家Android 特性应用程序框架:支持组件的重用与替换 Dalvik 虚拟机:专为移动设备优化 集成的浏览器:基于开源的 WebKit 引擎 优化的图形库:包括定制的 2D 图形库, 3D 图形库基于 OpenGL ES 1.0 SQLite :用作结构化的数据存储 多媒体支持 :包括常见的音频、视频和静态图像格式 (如 MPEG4, H.264, MP3, AAC, AMR, JPG, PNG, GIF ) GSM 电话技术 :(依赖于硬件) Bluetooth EDGE 3G WiFi :(依赖于硬件) 照相机 GPS 指南针 加速度计( accelerometer ):(依赖于硬件) 丰富的开发环境:包括设备模拟器,调试工具,内存及性能分析图表和 Eclipse 集成开发环境插件

Page 6: Android -汇博

— 高级软件人才培训专家Android 程序库Android 包含一些 C/C++ 库,这些库能被 Android 系统中不同的组件使用。它们

通过 Android 应用程序框架为开发者提供服务。以下是一些核心库:系统 C 库 :一个从 BSD 继承来的标准 C 系统函数库( libc ), 它是专门为基

于 embedded linux 的设备定制的。 媒体库 :基于 PacketVideo OpenCORE;该库支持多种常用的音频、视频格式回

放和录制,同时支持静态图像文件。编码格式包括 MPEG4 、 H.264 、 MP3 、AAC 、 AMR 、 JPG 、 PNG 。

Surface Manager :对显示子系统的管理,并且为多个应用程序提供了 2D 和 3D图层的无缝融合。

LibWebCore :一个最新的 web 浏览器引擎,支持 Android 浏览器和一个可嵌入的 web 视图。

SGL :底层的 2D 图形引擎 3D libraries :基于 OpenGL ES 2.0 APIs 实现;该库可以使用硬件 3D 加速(如

果可用)或者使用高度优化的 3D 软加速。 FreeType :位图( bitmap )和矢量( vector )字体显示。 SQLite : 一个对于所有应用程序可用,功能强劲的轻型关系型数据库引擎。

Page 7: Android -汇博

— 高级软件人才培训专家Android 与其他系统比较智能手机软件平台有:Symbian: C++ & JavaRIM BlackBerry: JavaPalm: C & C++Brew: C++J2ME : java ( MIDP )WindowsMobile : C#(Compact Framework) C & C++Android : SDK & NDK java & CSymbian : C++iPhone : Objective-C

Page 8: Android -汇博

— 高级软件人才培训专家Android 前景IphoneGphone(google tv,voice,earth)Ophone乐 phone

Page 9: Android -汇博

— 高级软件人才培训专家Dalvik 虚拟机Dalvik 和标准 Java 虚拟机 (JVM) 首要差别: Dalvik 基于寄存器,而 JVM 基于栈。基于寄存器的虚拟机对于更大的程序来说,在它们编译的时候,花费的时间

更短。Dalvik 和 Java 运行环境的区别: Dalvik 经过优化,允许在有限的内存中同时运行多个虚拟机的实例,并且每一个 Dalvik 应用作为一个独立的 Linu

x 进程执行。独立的进程可以防止在虚拟机崩溃的时候所有程序都被关闭 .Dalvik 形势: Dalvik 的诞生也导致人们开始忧虑 Java 平台的第一次大规模的分道扬镳或许已经是进行时了——有人已经把 Dav

lik 和微软的 JVM 以及 Sun( 现 Oracle) 对微软的诉讼联系起来,等着看 Google 身上是否也会发生类似事情;另外一些人则指出, Google 并没有宣称 Dalvik 是一个 Java 实现,而微软却是这样做的。 Sun 也对可能带来的阵营分裂表达了忧虑情绪,并提出和 Google 合作来保证 Dalvik 和 JVM 之间的兼容性—— Google 对此的解释是, Dalvik 是对解决目前 JavaME 平台上分裂的一次尝试,也是为了提供一个拥有较少限制许可证的平台。甚至还有人怀疑这是否是 Sun 和 Google 两大阵营对 Java 之未来的一次大规模较量。

Class 文件 ------Java 编译后的目标文件 : 不像 J2se , java 编译成 class 就可以直接运行, android 平台上 class 文件不能直接在 android 上运行。由于 G

oogle 使用了自己的 Dalvik 来运行应用,所以这里的 class 也肯定不能在 Android Dalvik 的 java 环境中运行,android 的 class 文件实际上只是编译过程中的中间目标文件,需要链接成 dex 文件后才能在 dalvik 上运行。

Dex 文件 -----Android 平台上的可执行文件 Android 虚拟机 Dalvik 支持的字节码文件格式 Google 在新发布的 Android 平台上使用了自己的 Dalvik 虚拟机来

定义,这种虚拟机执行的并非 Java 字节码,而是另一种字节码: dex 格式的字节码。在编译 Java 代码之后,通过 Android 平台上的工具可以将 Java 字节码转换成 Dex 字节码。虽然 Google 称 Dalvik 是为了移动设备定做的,但是业界很多人认为这是为了规避向 sun 申请 Java license 。这个 Dalvik VM 针对手机程式 /CPU 做过最佳化,可以同时执行许多 VM 而不会占用太多 Resource 。

Page 10: Android -汇博

— 高级软件人才培训专家Android 菜单

Page 11: Android -汇博

— 高级软件人才培训专家开发环境下载: 1.JDK1.6 http://www.sun.com 建议不要使用 JRE 2.Eclipse3.5 http://www.eclipse.org 建议 for Java EE Developers 版本 3.Ansroid SDK3.2 ( + ADT-12.0.zip ) http://developer.android.com/index.html http://androidappdocs.appspot.com/index.html http://www.coolapk.com/docs/ http://www.ideasandroid.com/android/sdk/docs/offline.html安装: 1. 安装JDK( 设置JAVA_HOME) 2. 解压 eclipse 到指定目录 3. 解压 Android SDK到指定目录,更改环境变量 PATH=……; android-sdk-windows-HOME\tools\

4. 安装Eclipse 插件 ADT( 在线安装方式 ) : a. 启动 Eclipse ,选择 Help -> Install New Software b. 在弹出窗体里,点击 Add… c. 在 Location 中输入 https://dl-ssl.google.com/android/eclipse/ 如果不可访问,输入 http://dl-ssl.google.com/android/eclipse/ d. 点击 OK -> Next -> Next -> Finish 。重启Eclipse 或也可直接下载 ADT-12.0.zip (文件安装方式): a. 启动 Eclipse ,选择 Help -> Install New Software b. 在弹出窗体里,点击 Add… ,然后选择 Archive… (选下载的 ADT-12.0.zip 文件) c. 选 Help -> Install New Software ,选择 android3.2 - jar:file:…

5. 安装 SDK( 需要网络 ) : 运行 android-sdk-windows-HOME/SDK Manager.exeSDK或者 Setup.exe ( 如果 https 不好用,就在 settings 设置为Force 强行 ) 建议选择所有的版本 (13,12,11,10,9,8,7,6,5,4,3,2,1) 。 Window -> Android SDK and AVD Manager -> 点击 New 创建 AVD

6. 创建 sdcard : 1. 在 android-sdk-windows-HOME/tools/ 目录下执行 mksdcard -l sdcard 256M e:/sd/pkbest.img (非常耗时 , 耐心等待 ) 2. 在 eclipse -> windows->Android AVD Manager ,弹出一个窗口,在 SDCard 后面的框中输入: e:\pkbest.img;即 SD 卡镜像文件 3. 上传文件: android-sdk-windows-HOME/platform-tools/adb push E:\music\hello.mp3 /sdcard/

Page 12: Android -汇博

— 高级软件人才培训专家Android 开发全过程创建 android 项目

Page 13: Android -汇博

— 高级软件人才培训专家运行 Android 程序创建 AVD(Android 模拟器 ) :

在工具栏中有一个手机图标 (Opens the Android SDK and AVD Manager) 。 选择 Virtual Devices ,点击 New按钮添加一个模拟器。 Target 选择 Android2.3 。其他的默认,单击 Create AVD 确认添加。

启动模拟器:选中我们添加的模拟器,单击右边的 Start... 按钮, 启动我们的模拟器。模拟器启动后, 在右键菜单 Run As Android Application 。

执行 Android 程序: 在模拟器中,打开抽屉,找到自己的应用程序。点击运行

Page 14: Android -汇博

— 高级软件人才培训专家目录结构

Page 15: Android -汇博

— 高级软件人才培训专家AndroidManifest.xml 轮廓<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" package="cn.pkbest.mobile" android:versionCode="1" android:versionName="1.0"> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".PKbestActivity" android:label="@string/app_name"> <intent-filter> <action android:name= "android.intent.action.MAIN" /> 入口 <category android:name= "android.intent.category.LAUNCHER" /> 在桌面列表中显示 <data /> </intent-filter> </activity>

<service /> <receiver /> <provider /> </application> <uses-sdk android:minSdkVersion="8" /> </manifest>

Page 16: Android -汇博

— 高级软件人才培训专家xml 文件

正前方提示:布局文件名字可以自己指定 strings.xml 常量如下:

Page 17: Android -汇博

— 高级软件人才培训专家资源 & 国际化 (I18N)Internationalization( 国际化 ) 简称 i18n, 因为在 i 和 n 之间还有 18 个字符。 Localization( 本地化 ) ,简称 L10n 。一般说明一个地区的语言时,用语言 _r 地区的形式,如 zh_CN, zh_TW. 本人认为对于不同国籍、文化信仰、办公习惯和生活方式,国际化可分为数据国际化、 UI 国际化、逻辑国际化。 一个很好的国际化软件是需要从这三个方面做到适应不同国籍人群的需要。

像 struts 一样, Android 也提供了一套数据国际化的经济处理方案:转化大量的资源信息,使 Android 资源保存与代码无关。可使用 Resources 类访问应用程序的资源;与应用程序相关联的资源可以通过 Context.getResources() 得到。 android 没有专门的 API 来提供国际化,而是通过对不同 resource 的命名来达到国际化,同时这种命名方法还可用于对硬件的区分,如不同的新视屏用不同的图片。

在代码中使用资源: R.resource_type.resource_name 的方式来使用,如 setTitle(R.string.title);在 xml 中直接引用: <TextView android:id ="@+id/hello_view" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="@string/hello" /> 我们以不同的 local 和 region 来做一次国际化,首先 values 表示默认的字符串,也即当 Resource 找不到匹配的资源时,默认使用 values

文件夹下的资源,其余 drawable 等资源也是同样的。 文件夹的命名必须都是小写字符。可以有限定词来修饰。res/anim XML 文件编译为桢序列动画或者自动动画对象。res/drawable .png , .jpg 文件被编译为 Drawable 资源子类型:使用 Resources.getDrawable(id) 可以获得资源类型位图文。res/layout 资源编译为屏幕布局器。参见“布局器”一章 res/valuesXML 文件可以被编译为多种资源。注意:不像其他 res 下的目录,

这个目录可以包含多个资源描述文件。 XML 文件元素类型控制着这些资源被 R 类放置在何处。这些文件可以自定义名字。这里有一些约定俗成的文件。

res/values/arrays.xml 定义数组。 colors.xml 定义可绘制对象的颜色和字符串的颜色。使用 Resources.getDrawable() 和 Resources.getColor() 都可以获得这些资源。

按照以下序列排列: #RGB , #ARGB , #RRGGBB , #AARRGGBB 。 dimens.xml 定义尺度。使用 Resources.getDimension() 可以获得这些资源 strings.xml 定义字符串(使用 Resources.getString() 或者更适合的 Resources.getText() 方法获得这些资源。 Resources.getText()

方法将保留所有用于描述用户界面样式的描述符,保持复杂文本的原貌。 styles.xml 定义样式对象res/xml 自定义的 XML 文件。这些文件将在运行时编译近应用程序,并且使用 Resources.getXML() 方法可以在运行时获取。res/raw 自定义的原生资源,将被直接拷贝入设备。这些文件将不被压缩近您的应用程序。使用带有 ID 参数的 Resources.getRawResource() 方法可以获得这些资源,比如R.raw.somefilename 。

Page 18: Android -汇博

— 高级软件人才培训专家I18N

如: values-zh-rCN/strings.xml ( 用语言 _r 地区的形式 ) values/strings.xml 文件夹名是变化的,文件名不变

res/drawable 在之前的版本中,只有一个 drawable ,而 2.1 版本以后有 drawable-mdpi 、 drawable-ldpi 、 drawable-hdpi

三个,这三个主要是为了支持多分辨率。 1.drawable-hdpi 里面存放高分辨率的图片 , 如 WVGA (480x800),FWVGA (480x854) 2.drawable-mdpi 里面存放中等分辨率的图片 , 如HVGA (320x480) 3.drawable-ldpi 里面存放低分辨率的图片 , 如 QVGA (240x320)系统会根据机器的分辨率来分别到这几个文件夹里面去找对应的图片。在开发程序时为了兼容不同平台不同屏幕,建

议各自文件夹根据需求均存放不同版本图片

Page 19: Android -汇博

— 高级软件人才培训专家限定词限定词 值 1. 语言 两字节 ISO 639-1 低位的语言编码,比如: en, fr, es 2. 区域 两字节 ISO 3166-1-alpha-2 带有小写 "r" 前缀的大写地区编码。如: rUS, rFR, rES 3. 屏幕方向 port, land, square 4. 屏幕像素密度 92dpi, 108dpi, etc. 5. 触摸屏类型 notouch, stylus, finger 6. 用户是否可以使用键盘 keysexposed, keyshidden 7. 默认的文字输入方法 nokeys, qwerty, 12key 8. 默认的非触摸导航方法 notouch, dpad, trackball, wheel 9. 屏幕尺寸 320x240, 640x480, etc. 较大的尺寸必须首先声明。

此列表不包括设备定制的参数,比如信号、商标等。所有应用程序应该知道的信息都需要按照上面的列表信息编码。这里有一些命名的通用原则:1. 值之间用连接号连接2. 值是大小写敏感的,比如:一个指定的 drawable 目录必须命名为 drawable-port ,而不是 drawable-PORT 。3. 每种限定词只能有一种选择,您不能命名目录为 drawable-rEN-rFR/ 。4. 可以添加多种限定词,但是每个限定词必须在在上面列表中。比如: drawable-en-rUS-land 表明其用于直板的美

式英语设别上。5. 带有限定词的目录不能被嵌套,比如: res/drawable/drawable-en 是不允许的。6. 资源引用在语法中表示为未加修饰的表达式,比如 PKbestApp/res/drawable-port-92dpi/pkbestimage.png ,

在 XML 中表示为: @drawable/pkbestimage ,在代码中表示为: R.drawable.pkbestimage 。

正前方提示:限定词只对特定目录有作用

Page 20: Android -汇博

— 高级软件人才培训专家调试工具 & 方法DDMS : Dalvik Debug Monitor service ,提供很多功能:截屏、模拟广播信息、模拟电话呼叫、接发 SMS 、虚拟地理坐标、进程、线程查

看、堆信息及 gc 等。 LogCat :用来将消息写入模拟器上的日志文件中的类。可以在 DDMS 上查看实时消息。 Log.v 输出颜色为黑色的,任何消息都会输出,这里的 v 代表 verbose 啰嗦的意思,平时使用就是 Log.v("",""); Log.d 输出颜色是蓝色的,仅输出 debug 调试的意思,但他会输出上层的信息,过滤起来可以通过 DDMS 的 Logcat 标签来选择 . Log.i 输出颜色为绿色,一般提示性的消息 information ,它不会输出 Log.v 和 Log.d 的信息,但会显示 i 、 w 和 e 的信息 Log.w 输出颜色为橙色,可以看作为warning 警告,一般需要我们注意优化 Android 代码,同时选择它后还会输出 Log.e 的信息。 Log.e 输出颜色为红色,可以想到 error 错误,这里仅显示红色的错误信息,这些错误就需要认真的分析,查看栈的信息了。 Log.v() verbose :适合开发过程中 Log.d() debug :适合开发过程中 Log.i() information :最终版本 Log.w() warning :最终版本 Log.e() error :最终版本 Devices :可以查看到当前运行的 Emulator 和其内运行的应用 Emulator control: 即仿真器的硬件设置项

Debug 单步调试:设置断点,进行单步调试。启动 Run -> Debug History 即可切入 debug 模式运行。正前方提示:断点调试必须有源代码。

adb : 调试桥 (adb) 是多种用途的工具,该工具可以帮助你你管理设备或模拟器的状态。 Adb shell 是一个简单的 shell 环境。 android-sdk-windows-HOME/platform-tools/adb android-sdk-windows-HOME/tools/adb adb shell ( 进入 shell) mksdcard -l sdcard 1024M e:/sdcard.iso ( 创建 SD 卡 ) adb push <local> <remote> adb push E:\music\hello.mp3 /sdcard/ ( 将文件上传至 SD 卡,下载用 pull) 常用 shell 命令: 正前方提示:如果遇到Read-only file system 请仔细核查虚拟机是否安装了 sdcard ls cd mkdir music rm pkbest.mp3 rmdir alarms

Page 21: Android -汇博

— 高级软件人才培训专家应用打包与安装Apk 是 Android 安装包的扩展名,一个 Android 安装包包含了与某个 Android 应用程序相关的所有文件。 apk 文

件将 AndroidManifest.xml 文件、应用程序代码 (.dex 文件 ) 、资源文件和其他文件打成一个压缩包。一个工程只能打进一个 .apk 文件。通常会安装到 /data/app/xxx.apk

1. 导出 Android 应用 : 在工程上右键 -->Export-->Android-->Export Android Application ,将工程导出为 APK 包。2. 将 APK 包放入到 SDCard 目录中 : 在 FileExplorer 面板的右上角有一个导入手机图标,将上面生成的 APK 包导入到 SDCard 目录中。 或直接使用命令安装: adb install pkbest.apk 命令即可执行安装 3. 编写安装 APK 包的 Android 程序 : 1. 在 AndoirdManifest.xml 添加权限: <!-- 安装程序权限 --> <uses-permission android:name="android.permission.INSTALL_PACKAGES"/> 2. 通过 Android 提供的功能,安装 APK : Intent intent = new Intent(); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.setAction(android.content.Intent.ACTION_VIEW); Uri data = Uri.fromFile(new File(Environment.getExternalStorageDirectory(), filename)); intent.setDataAndType(data, "application/vnd.android.package-archive"); startActivity(intent);

4. 向模拟器中安装 apk 文件 adb install c:/pkbest.apk 卸载(只能手动删除): adb shell cd data/app rm app.apk

Page 22: Android -汇博

— 高级软件人才培训专家Linux 命令ADB(Android Debug Bridge) 是一个通用调试工具,借助这个工具,可以管理设备或手机模拟器的状态。ADB常用操作: 复制文件:可向一个设备或从一个设备中复制文件;复制一个文件或目录到设备或模拟器上: adb push adb push test.txt /tmp/test.txt 一般放小的文件挺顺利 ( < 1 M ) 从设备或模拟器上复制一个文件或目录如: adb pull adb pull /android/lib/libwebcore.os 搜索 / 等待模拟器、设备实例,取得当前运行的模拟器、设备的实例列表及每个实例的状态 | 等待正在运行的设备 adb devices adb wait-for-device 查看Bug 报告: adb bugreport 记录无线通讯日志: adb bugreport 无线通讯记录日志非常多,在运行时没必要记录,可以通过命令设置记录: adb shell logcat -b radio 获取设备 ID 和序列号: adb get-product adb get-serialno 访问数据库 SQLite3 adb shell sqlite3创建文件夹: mkdir pkbest

Page 23: Android -汇博

— 高级软件人才培训专家模拟器参数

Page 24: Android -汇博

— 高级软件人才培训专家模拟器参数

Page 25: Android -汇博

— 高级软件人才培训专家eclipse 快捷键Alt+/ 显示 api 列表 :Ctrl+Shift+L+L( 可以弹出设置窗口 或 Window->Preferences->General->Keys)Content Assist 改成别的组合键 (alt+ 非 /)word completion 改成 alt+/

CTRL+SHIFT+X 将选中字母变为大写CTRL+SHIFT+Y 将选中字母变为小写

如果 api 列表还不出现,不妨可以删除workspace 目录里的设置信息

Page 26: Android -汇博

— 高级软件人才培训专家拨打电话调用面板拨打:模拟器上号码使用端口号Intent it = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:041188335533"));startActivity(it);直接拨打:没有面板, API 方式Intent it = new Intent(Intent.ACTION_CALL, Uri.parse("tel:041188335533"));startActivity(it);// 正前方提示:可以使用: PhoneNumberUtils.isGlobalPhoneNumber(phoneNumber) 来判断电话号码的有效性

需要权限:<uses-permission android:name="android.permission.CALL_PHONE"/> 与 <application> 节点同级

启动模拟器 : 我们可以启动两个模拟器。使用一个模拟器给另一个模拟器拨打。启动模拟器后,主界面显示信号强度的旁边会有一个 3G 的字样,这说明模拟器已经能接收到信号了。如果我们的机器不能联网,那么将自己的 IP地址、网关和 DNS 服务器都设置为相同的值,比如都设置为 192.168.0.100 。如果我们的机器是在局域网下,但没有联网,那么将自己的网关和 DNS 设置为路由的 IP 即可,一般情况下路由的 IP 是 192.168.0.1 。

拨打电话 : 可以看到模拟器窗口的标题栏上有 5554 和 556 的字样。这是模拟器监听的端口即 --127.0.0.1:5554 。

使用 ADT 插件呼叫模拟器 : 如机器太慢,无法启动两个模拟器,我们可以只启动一个模拟器。然后在菜单windows->show view->other->Android->Emulator Control 打开 Emulator Control 面板。

Page 27: Android -汇博

— 高级软件人才培训专家发送短信 SMS调用界面发送:Uri uri = Uri.parse("smsto:041188335533"); Intent it = new Intent(Intent.ACTION_SENDTO, uri);String message = "来正前方学习,每次都有新感觉! from www.PKbest.CN";it.putExtra("sms_body", message);startActivity(it);finish();

直接发送: API 方式没有界面SmsManager sms = SmsManager.getDefault(); // 正前方提示:运营商允许每次发送的字节有限,需要分割成多条发。message=" 一件外衣钱学会 3G ,值!现在是 javaEE+Android 的春天!你还等什么?来正前方学习,每次都有新感

觉! ";List<String> messList = sms.divideMessage(message); for (String mess : messList) { sms.sendTextMessage("041188335533", null, mess , null, null);}sendTextMessage(destinationAddress, scAddress, text, sentIntent, deliveryIntent) : destinationAddress: 接收方的手机号码 scAddress: 发送方的手机号码 text: 信息内容 sentIntent: 发送是否成功的回执 deliveryIntent: 接收是否成功的回执

权限:<uses-permission android:name="android.permission.SEND_SMS"/>正前方提示:目前在模拟器中对短信中文支持不够理想,发送短信会有乱码,依赖真机测试 .

Page 28: Android -汇博

— 高级软件人才培训专家Android 应用解析Android 应用程序由 4个模块构成,但并不是必须的,可根据需求进行组合。

Activity :最基本的模块,称之为“活动”;控制视图、监听系统事件、启动其他的 Activity 、 Service 等。一个应用有很多个 Activity ,一个 Activity 控制一个屏幕(一个屏幕很有可能由多个Activity 组成);很容易实现一个屏幕到一个新的屏幕,完成新的活动。打开一个新的屏幕,前一个屏幕将会暂存在历史栈中,用户可以返回到历史栈中前一个屏幕,不用时还可以删除。简单理解 Activity 为一个 action 类( MVC )。 Activity 类必须在 AndroidManifest.xml 中注册方可使用。

ContentProvider :是提供与其他应用程序共享存取数据的标准方法的类。应用程序可以查询、修改、添加、删除数据。

Service :后台运行的“服务”程序 ,可交互。跟 Activity 的级别差不多,但他不能自己运行,需要通过某一个 Activity 或者其他 Context 对象来调用, Context.startService() 和 Context.bindService() 。通常用来播放媒体文件或检测设备状态等无需界面的任务。

BroadcastReceiver :能让你的应用对外部的事件做出响应;不能显示 UI ,它只能通过NotificationManager 来通知用户事情发生了。既可在 xml 中注册,也可在代码中用 Context.registerReceiver() 注册。各种应用还可以通过使用 Context.sendBroadcast() 将它们自己的 intent broadcasts 广播给其它应用程序。

Page 29: Android -汇博

— 高级软件人才培训专家IntentAndroid 基本的设计理念是鼓励减少组件间的耦合,因此 Android 提供了 Intent ( 意图 ) , Intent 提供了一种通用

的消息系统,它允许在你的应用程序与其它的应用程序间传递 Intent 来执行动作和产生事件。使用 Intent 可以激活 Android 应用的三个核心组件:活动、服务和广播接收器。 Intent 可以划分成显式意图和隐式意图:

对于明确指出了目标组件名称的 Intent ,我们称之为“显式 Intent” 。对于没有明确指出目标组件名称的 Intent ,则称之为“隐式 Intent” 。 Android 系统使用 IntentFilter 来寻找与隐式 Intent 相关的对象。

显式 Intent: 直接用组件的名称定义目标组件,这种方式很直接。但是由于开发人员往往并不清楚别的应用程序的组件名称,因此,显式 Intent 更 多用于在应用程序内部传递消息。比如在某应用程序内,一个 Activity 启动一个 Service 。

Intent intent = new Intent(PKbestActivity.this, NewActivity.class); startActivity(intent);// 发送 Intent ,启动 NewActivity, // 意图里默认类别相当于 :android.intent.category.DEFAULT // 对于显示 Intent , Android 不需要去做解析,因为目标组件已经很明确

应用场景: 应用内部使用显式意图,代码清晰可见。

Page 30: Android -汇博

— 高级软件人才培训专家隐式 Intent隐式 Intent: 恰恰相反,它不会用组件名称定义需要激活的目标组件,它更广泛地用于在不同应用程序之间传递消息。

Android 系统会根据隐式意图中设置的动作 (action) 、类别 (category) 、数据( URI 和数据类型)找到最合适的组件来处理这个意图。 如:

Uri uri = Uri.parse("smsto:04118835533"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); // 通过 action 和 URI 找到最适合的组件 String message = "来正前方学习,每次都有新感觉! from www.PKbest.CN"; it.putExtra("sms_body", message); startActivity(it);

<activity android:name=".PKbestActivity" android:label="@string/main_activity"> <intent-filter> <action android:name="cn.pkbest.mobile.PKbestActivity"/> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> Android 需要解析的是那些间接 Intent ,通过解析,将 Intent 映射给可以处理此 Intent 的 Activity 、 IntentRec

eiver 或 Service 在 intent 过滤器中还可以添加多个 action 和 category ,还可以添加 data 。

应用场景: 应用外部只能使用隐式意图,功能封装。

Page 31: Android -汇博

— 高级软件人才培训专家屏幕切换Android 其实跟网页开发差不多,屏幕切换就好像一个页面跳转到另一个页面。1.屏幕切换( AB ):需要调用 startActivity()来完成 Intent intent = new Intent(); intent.setClass(A.this, B.class); startActivity(intent); A.this.finish();// 关闭 A 的 Activity2.携带数据切换:需要调用 startSubActivity()实现跳转 (AB) , setData(ContentURI) :将封装的数据带过去 (AB) 。 setResult() :将参数带回来 (ABA), 即传递B 后, A 可以得到 B返回的数据, 同时触发 A 的 onActivityResult()。 A.Java Intent intent = new Intent(); intent.setClass(A.this, B.class); Bundle b = new Bundle(); b.putString("first", "firstValue"); intent.putExtras(b); intent.setData(Uri.parse("www.PKbest.CN")); int requestCode = 88335533; //88335533 为自定义的整数 . 此时就不要关掉 A ,因为要有得知返回的状态 this.startActivityForResult(intent,requestCode); //正前方提示:不要关闭 A protected void onActivityResult(int requestCode, int resultCode, Intent data) {// 正前方提示:获取 B返回的信息 } B.java 获取来自 A 的数据 Intent intentFromA = B.this.getIntent(); Bundle bundleFromA = intentFromA.getExtras(); String firstValue = bundleFromA .getString("first"); Bundle toABundle = new Bundle(); toABundle.putString("second", "return string value to a"); intentFromA.putExtras(toABundle); // 正前方提示:返回给 A int REQUEST_CODE = 8833; B.this.setResult(REQUEST_CODE, intentFromA ); // 正前方提示:返回给 A B.this.finish();

Page 32: Android -汇博

— 高级软件人才培训专家Activity生命周期

Page 33: Android -汇博

— 高级软件人才培训专家Activity生命周期Activity 有三个状态: 当它在屏幕前台时(位于当前任务堆栈的顶部),它是激活或运行状态。它就是响应用户操作的 Activity 。 当它失去焦点但仍然对用户可见时,它处于暂停状态。即在它之上有另外一个 Activity 。这个 Activity 也许是透明的,或者没有完全覆盖

全屏,所以被暂停的 Activity 仍对用户可见。暂停的 Activity 仍然是存活状态(它保留着所有的状态和成员信息并保持和窗口管理器的连接),但系统处于极低内存时仍然可以杀死这个 Activity 。

完全被另一个 Activity 覆盖时则处于停止状态。它仍然保留所有的状态和成员信息。然而对用户是不可见的,所以它的窗口将被隐藏,如果其它地方需要内存,则系统经常会杀死这个 Activity 。

当 Activity 从一种状态转变到另一种状态时,会调用以下保护方法来通知这种变化: void onCreate(Bundle savedInstanceState) void onStart() void onRestart() void onResume() void onPause() void onStop() void onDestroy()这七个事件定义了 Activity 的完整生命周期。实现这些事件方法可以帮助我们监视其中的三个嵌套生命周期循环: 1.Activity 的完整生命周期自第一次调用 onCreate() 开始,直至调用 onDestroy() 为止。 Activity 在 onCreate() 中设置所有“全局”状态以完成初始化,而在 onDestroy() 中释放所有系统资源。例如,如果 Activity 有一个线程

在后台运行从网络上下载数据,它会在 onCreate() 创建线程,而在 onDestroy()销毁线程。

2.Activity 的可视生命周期自 onStart() 调用开始直到相应的 onStop() 调用结束。 在此期间,用户可以在屏幕上看到 Activity ,尽管它也许并不是位于前台或者也不与用户进行交互。在这两个方法之间,我们可以保留用

来向用户显示这个 Activity 所需的资源。例如,当用户不再看见我们显示的内容时,我们可以在 onStart() 中注册一个BroadcastReceiver 来监控会影响 UI 的变化,而在 onStop() 中来注消。 onStart() 和 onStop() 方法可以随着应用程序是否为用户可见而被多次调用。

3.Activity 的前台生命周期自 onResume() 调用起,至相应的 onPause() 调用为止。 在此期间, Activity 位于前台最上面并与用户进行交互。 Activity 会经常在暂停和恢复之间进行状态转换——例如当设备转入休眠状态或

者有新的 Activity 启动时,将调用 onPause() 方法。当 Activity 获得结果或者接收到新的 Intent 时会调用 onResume() 方法。

Page 34: Android -汇博

— 高级软件人才培训专家Android设计模式Android 是个完全的 Application framework ,处处可见反向控制。主要有两种实现机制:Template Method 模式 : 使用继承 (Inheritance)Observer(也称 Listener) 模式:Android 的源码很多都是 singleton 模式。

Page 35: Android -汇博

— 高级软件人才培训专家事件处理1.Android 基于 Listener 实现事件处理的,通过View 的 setOnXXXListener() 来添加事件的监听器 Listener 。 OnClickListener OnCreateContextMenuListener OnKeyListener OnFocusChangeListener OnTouchListener OnLongClickListener

2.Listener 是以 Interface 的方式来提供,包含一个或多个 abstract 方法,需要实现这些方法来完成相应事件的操作。在特定的事件被 dispatch 到该 view 时,通过 callback() 给予响应 。

3.Android 下, Activity 的相应按键和触屏两种事件: boolean onKeyDown(int keyCode, KeyEvent event) // 键按下 boolean onKeyLongPress(int keyCode, KeyEvent event) //长按键 boolean onKeyMultiple(int keyCode, int repeatCount, KeyEvent event) // 重复按键 boolean onKeyUp(int keyCode, KeyEvent event) // 按键释放 boolean onTouchEvent(MotionEvent event) // 触屏事件 //Touch Screen Click举例 public class PKbestEventActivity extends Activity implements OnTouchListener { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); TextView tv = (TextView) findViewById(R.id.tv); tv.setOnTouchListener(this); } public boolean onTouch(View v, MotionEvent event) { Toast.makeText(this, "Touch", Toast.LENGTH_SHORT).show(); // 正前方提示: Toast 是一个提示,几秒钟后自动消失 return false; } }

Page 36: Android -汇博

— 高级软件人才培训专家UIAndroid 生成屏幕有三种方式: XML配置、 IDE 界面接口、硬代码生成。在一个 Android 应用中,用户界面是有 Vi

ew 和 ViewGroup 对象构成。View :任何一个 View 的对象都继承 android.view.View类。它表示屏幕特定的矩形布局和内容属性的数据结构。可

以处理测距、布局、绘图、焦点变换、滚动条、案件、手势等。 View为 Widget 服务,是一组用于绘制交互屏幕元素的完全实现子类。 Widget 处理自己的测距和绘图,可快速用它们构建 UI 。可用的 Widget 包括 Text 、 EditText 、 Button 、 RadioButton 、 Checkbox 、 ScrollView 等。

ViewGroup : android.view.ViewGroup 类。是一个特殊的 View对象,装载和管理一组下层的 View 和 ViewGroup ;ViewGroup 可以为 UI增加结构,并将复杂的屏幕构建成独立实体。 ViewGroup 为 Layout 服务, Layout 可为一组 View构建。

右图表示一个 Activity 界面,可以包含很多 ViewGroup 和 View ,这样的组合可以开发更完美、更复杂的界面。当 Activity 被激活并得到焦点时,通过 setContentView() 方法传递给 根节点对象,系统会通知并请求根节点测距并绘制树,根节点 就会请求它的子节点对象的 draw() 去完成此事。依次下去。如果叶子节点为 ViewGroup ,则会测量它的有效空间、布 局,并调用每个子对象 draw() 去绘制。子对象可以获取父对象的大小和 位置,但父对象对每个子对象的大小和位置有最终的决定权。

View View

View View View

ViewGroup

ViewGroup

View 和 ViewGroup混合布局的 Activity 界面

Page 37: Android -汇博

— 高级软件人才培训专家LayoutAbsoluteLayout :绝对布局。是一个按照绝对坐标定义的布局,由于使用绝对坐标去定

位控件,因此要实现自适应界面时,应尽少使用 AbsoluteLayout 。 AbsoluteLayout 里面的控件都以 layout_x 、 layout_y 来定义其位置。

FrameLayout :帧布局。所有的控件都被放到布局的左上角,并一层覆盖一层。 LinearLayout : 线布局。按照水平或者垂直排列。RelativeLayout : 相对布局。按照相对位置排列的布局。 TableLayout : 表布局。TabWidget : 切换卡。

Page 38: Android -汇博

— 高级软件人才培训专家FrameLayoutFrameLayout 是最简单的一个布局对象。它被定制为你屏幕上的一个空白备用区域,之后你可以在

其中填充一个单一对象 — 比如,一张你要发布的图片。所有的子元素将会固定在屏幕的左上角;你不能为 FrameLayout 中的一个子元素指定一个位置。后一个子元素将会直接在前一个子元素之上进行覆盖填充,把它们部份或全部挡住(除非后一个子元素是透明的)。 FrameLayout 的大小是最大的子元素的大小。

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" > <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text= "正前方最新课程访问 www.PKbest.CN" />

</FrameLayout>

Page 39: Android -汇博

— 高级软件人才培训专家LinearLayout<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" horizontal android:layout_width="fill_parent" android:layout_height="fill_parent"> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text= " 正前方开启地震提示 " /> <Button android:layout_width="fill_parent" android:layout_height="wrap_content" android:text= " 最新课程访问www.PKbest.CN" /> </LinearLayout>

DisplayMetrics screen = new DisplayMetrics();this.getWindowManager().getDefaultDisplay().getMetrics(screen);// 获取屏幕的大小LinearLayout layout = new LinearLayout(this); // LayoutParams params = new LayoutParams(screen.widthPixels,screen.heightPixels); // layout.setLayoutParams(params);layout.setOrientation(LinearLayout.VERTICAL); Button a = new Button(this);a.setText("正前方开启地震提示 ");Button b = new Button(this);b.setText(" 最新课程访问www.PKbest.CN");LayoutParams buttonParams = new LayoutParams(screen.widthPixels,50);LayoutParams buttonParams1 = new LayoutParams(screen.widthPixels,50);layout.addView(a,buttonParams);layout.addView(b,buttonParams1); this.setContentView(layout);

Page 40: Android -汇博

— 高级软件人才培训专家RelativeLayout<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" android:padding="10px" >

<TextView android:id="@+id/label" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text=" 输入正前方课程名称 :" /> <EditText android:id="@+id/entry" android:layout_width="fill_parent" android:layout_height="wrap_content" android:layout_below="@id/label" />

<Button android:id="@+id/go" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/entry" android:layout_alignParentRight="true" android:layout_marginLeft="10px" android:text="GO" /> <Button android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_toLeftOf="@id/go" android:layout_alignTop="@id/go" android:text="Cancel" /> </RelativeLayout>

Page 41: Android -汇博

— 高级软件人才培训专家AbsoluteLayout<AbsoluteLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/mArtivleViewLayout" android:layout_width="fill_parent" android:layout_height="fill_parent" androidrientation="vertical">

<LinearLayout android:layout_y="350px" android:layout_width="fill_parent" android:id="@+id/TooLBarLayout" android:layout_x="0px" android:layout_height="44px" android:gravity="center" >

<ImageView android:id="@+id/pkbest" android:layout_height="wrap_content" android:layout_width="wrap_content" android:src="@drawable/pkbest"> </ImageView> </LinearLayout> </AbsoluteLayout>

AbsoluteLayout 可以让子元素指定准确的 x/y 坐标值,并显示在屏幕上。 (0, 0) 为左上角,当向下或向右移动时,坐标值将变大。 AbsoluteLayout 没有页边框,允许元素之间互相重叠 (尽管不推荐 ) 。我们通常不推荐使用 AbsoluteLayout ,除非你有正当理由要使用它,因为它使界面代码太过刚性,以至于在不同的设备上可能不能很好地工作。

Page 42: Android -汇博

— 高级软件人才培训专家TableLayout<TableLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:stretchColumns="1"> <TableRow> <TextView android:text=" 正前方 java 系列课程 " android:padding="3dip" /> </TableRow> <TableRow> <TextView android:text="Android2.2课程 " android:padding="3dip" /> <TextView android:text="Struts2.1课程 " android:padding="3dip" /> </TableRow> <TableRow> <TextView android:text="Spring2.5课程 " android:padding="3dip" /> <TextView android:text="Hibernate3.3课程 " android:padding="3dip" /> </TableRow> </TableLayout>TableLayout layout = new TableLayout(this); TableRow row0 = new TableRow(this);TextView text0 = new TextView(this);text0.setText(" 正前方 java 系列课程 :");row0.addView(text0);layout.addView(row0);

TableRow row1 = new TableRow(this);TextView text1 = new TextView(this);text1.setText("Android2.2课程 ");row1.addView(text1);TextView text11 = new TextView(this);text11.setText("Struts2.1课程 ");row1.addView(text11);layout.addView(row1); this.setContentView(layout);

Page 43: Android -汇博

— 高级软件人才培训专家TabWidget<TabHost xmlns:android="http://schemas.android.com/apk/res/android" android:id="@android:id/tabhost" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TabWidget android:id="@android:id/tabs" android:layout_width="fill_parent" android:layout_height="wrap_content" /> <!-- TabHost必须与 FrameLayout 搭配使用 --> <FrameLayout android:id="@android:id/tabcontent" android:layout_width="fill_parent" android:layout_height="fill_parent"> <TextView android:id="@+id/android" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text=" 正前方最新 Android 课程 请到 www.PKbest.CN 查询 " /> <TextView android:id="@+id/spring" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text=" 正前方最新 Spring 课程 请到 www.PKbest.CN 查询 " /> <TextView android:id="@+id/struts" android:layout_width="fill_parent" android:layout_height="fill_parent" android:text=" 正前方最新 Struts 课程 请到 www.PKbest.CN 查询 " /> </FrameLayout> </LinearLayout></TabHost>

Page 44: Android -汇博

— 高级软件人才培训专家TabActivitypublic class PKbestActivity extends TabActivity { // 正前方提示:使用 TabHost 必须与 TabActivity 一起使用 private TabHost tabHost = null; // 声明 TabHost 对象 public void onCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState); setContentView(R.layout.pkbest); tabHost = getTabHost(); // 取得 TabHost 对象 // 为 TabHost 添加标签 //1. 新建 newTabSpec(newTabSpec) 2. 设置其标签和图标 (setIndicator) 3. 设置内容 (setContent) tabHost.addTab(tabHost.newTabSpec("tab_test1") .setIndicator("Android课程 ",getResources().getDrawable(R.drawable.icon)) .setContent(R.id.android)); tabHost.addTab(tabHost.newTabSpec("tab_test2") .setIndicator("Spring课程 ",getResources().getDrawable(R.drawable.icon)) .setContent(R.id.spring)); tabHost.addTab(tabHost.newTabSpec("tab_test3") .setIndicator("Struts课程 ",getResources().getDrawable(R.drawable.icon)) .setContent(R.id.struts)); tabHost.setBackgroundColor(Color.argb(150, 22, 70, 150));// 设置 TabHost 的背景颜色 //tabHost.setBackgroundResource(R.drawable.pkbest);// 设置 TabHost 的背景图片资源 tabHost.setCurrentTab(0);// 设置当前显示哪一个标签 // 标签切换事件处理, setOnTabChangedListener tabHost.setOnTabChangedListener(new OnTabChangeListener() { public void onTabChanged(String tabId) { // 已经选中此 tab 页 } }); }}

Page 45: Android -汇博

— 高级软件人才培训专家UI控件ListView :列表在 android.widget 包下,有这些View。均为可视的图形 UI 部件。EditText :编辑框 ( 多行 )RadionButton :单项选择按钮 ( 用 RadionGroup 分组管理、事件监听等 )CheckBox :多项选择Spinner :下拉框ExpandableListView :可折叠列表AutoCompleteTextView :自动提示DatePicker :日期 (DatePickerDialog)TimePciker :时间 (TimePickerDialog)Menu :菜单 ( 三种菜单类型,分别为 options menu , context menu , sub menu Dialog :对话框ImageView :图片ImageButton :图片按钮Gallery :拖动效果ImageSwitcher :切换图片GridView :网格ScrollView :卷轴视图ProgressBar :进度条SeekBar :拖动条VideoView :视频视图Notification :状态提示 (NotificationManager: 管理状态栏信息 )PopupWindow :弹出窗体RatingBar :评分条WebView :webkit内核浏览器TableView :自定义 View :SurfaceView :

Page 46: Android -汇博

— 高级软件人才培训专家Spinner使用 XML 布局 +arrays.xml 数据res/values/arrays.xml<?xml version="1.0" encoding="utf-8"?><resources> <string-array name="cities"> <item> 大连 -- 正前方总部 </item> <item> 北京 </item> <item> 上海 </item> </string-array></resources>

<?xml version="1.0" encoding="utf-8"?><LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <Spinner android:id="@+id/citiesSpinner" android:layout_width="wrap_content" android:layout_height="wrap_content" android:entries="@+array/cities" /> </LinearLayout>

Page 47: Android -汇博

— 高级软件人才培训专家Spinner使用 Adapterpublic class PKbestSpinner extends Activity { public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.spiner); List<String> list = new ArrayList<String>(); list.add(" 大连 -- 正前方总部 "); list.add(" 北京 "); list.add(" 上海 "); Spinner citiesSpinner = (Spinner)this.findViewById(R.id.citiesSpinner); ArrayAdapter adapter = new ArrayAdapter<String>(this, android.R.layout.simple_spinner_item, list); // 为适配器设置下拉列表下拉时的菜单样式。 adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); // 将适配器添加到下拉列表上 citiesSpinner.setAdapter(adapter); } }

Page 48: Android -汇博

— 高级软件人才培训专家Menu选项菜单 Options Menu :这是一个活动的主菜单。按 MENU 键来显示,在屏幕最下面最多显示 6

个菜单选项( icon menu ,不可以有 checkable ),如果多于 6 个的其他的会以“ more”icon menu 来调出包含两组菜单项:

图标菜单 Icon Menu :这个是当用户按下菜单键时最初出现屏幕下方的 item 集合。它支持最多 6个菜单项。只有这些菜单支持图标而且这些菜单并不支持 checkboxes 或者 radio buttons 。

扩展菜单 Expanded Menu :这是通过按“更多”菜单显现出来的一个竖向的项目列表。它仅当图标菜单过多时存在而且是由 6 个以及其它选项菜单组成。

上下文菜单 Context Menu :这是一个浮动菜单列表,通常在你长时间按在一个视图上时出现(比如一个列表项)

子菜单 Submenu :这是一个浮动菜单列表,通过在选项菜单或上下文菜单显露出来。不支持嵌套子菜单。

Page 49: Android -汇博

— 高级软件人才培训专家OptionsMenuXML 布局方式: OptionsMenu 需重写 Activity 的 onCreateOptionsMenu() 、 onOptionsItemSelected() <menu> 、 <group> 和 <item> 。 item 和 group 必须是菜单的子元素,而 <item>元素还可以是 <group> 的子元素,并且另外一个菜单元素

可以是一个 <item> 的子元素(来创建一个子菜单<menu> )。任何文件的根元素必须是一个 <menu>元素。

<menu xmlns:android="http://schemas.android.com/apk/res/android"> <item android:id="@+id/newItem" android:title="new"> <menu> <item android:id="@+id/androidItem" android:title="android project" /> </menu> </item> <item android:id="@+id/exitItem" android:title="exit" /></menu>public boolean onCreateOptionsMenu(Menu menu){ this.getMenuInflater().inflate(R.menu.menu, menu); // 正前方提示:设置界面为 res/menu/menu.xml return true;}public boolean onOptionsItemSelected(MenuItem item){ int id = item.getItemId(); switch(id){ case R.id.newItem: Toast.makeText(this, "new item selected!", Toast.LENGTH_SHORT).show(); break; case R.id.exitItem: Toast.makeText(this, "exit menu", Toast.LENGTH_SHORT).show(); DisplayUIActivity.this.finish(); break; } return true;}

Page 50: Android -汇博

— 高级软件人才培训专家OptionsMenu硬编码方式: OptionsMenu 需重写 Activity 的 onCreateOptionsMenu() 、 onOptionsItemSelected()public boolean onCreateOptionsMenu(Menu menu){ SubMenu fileMenu = menu.addSubMenu(0,0,0,"new"); SubMenu editMenu = menu.addSubMenu(0,1,1,"exit"); fileMenu.add(0,2,0,"android project"); menu.addSubMenu("search"); menu.addSubMenu("refactor"); menu.addSubMenu("navigate"); menu.addSubMenu("project"); return true;}public boolean onOptionsItemSelected(MenuItem item){ int id = item.getItemId(); switch(id){ case 0: Toast.makeText(this, "new item selected!", Toast.LENGTH_SHORT).show(); break; case 1: Toast.makeText(this, "exit menu", Toast.LENGTH_SHORT).show(); DisplayUIActivity.this.finish(); break; } return true;}

Page 51: Android -汇博

— 高级软件人才培训专家ContextMenupublic void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); TextView view = new TextView(this); view.setText("www.PKbest.CN"); // 正前方提示:任何 View均可有 ContextMenu 。需要长按 2秒 this.registerForContextMenu(view); // 正前方提示:需用此方法注册 this.setContentView(view);}@Overridepublic void onCreateContextMenu(ContextMenu menu, View v, ContextMenuInfo menuInfo) { super.onCreateContextMenu(menu, v, menuInfo); menu.add(0,0,0, "new"); // 正前方提示:与添加 OptionsMenu 一样 menu.add(0,1,1,"exit");}@Overridepublic boolean onContextItemSelected(MenuItem item) { switch (item.getItemId()) { case 0: Toast.makeText(this, "new item selected!", Toast.LENGTH_SHORT).show(); return true; case 1: Toast.makeText(this, "exit menu", Toast.LENGTH_SHORT).show(); return true; default: return super.onContextItemSelected(item); } }

Page 52: Android -汇博

— 高级软件人才培训专家Dialog

2 个按钮对话框 xml 布局的对话框 进度对话框前两个都通过 AlertDialog.Builder 创建获得。进度对话框通过 ProgressDialog 创建获得。

Page 53: Android -汇博

— 高级软件人才培训专家DialogBuilder builder = new AlertDialog.Builder(DisplayUIActivity.this);builder.setTitle("正前方提示 ");// 设置标题builder.setMessage("需要您重新登录! ");// 设置内容// 正前方提示:得到自定义对话框。去掉即为带有 2 个按钮的对话框LayoutInflater factory = LayoutInflater.from(DisplayUIActivity.this);final View dialogView = factory.inflate(R.layout.ui_dialog, null); builder.setView(dialogView);// 设置自定义对话框的样式 builder.setPositiveButton(" 确定 ", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton){ }});builder.setNeutralButton("退出 ", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int whichButton){ }});Dialog dialog = builder.create();// 创建 dialog.show();// 显示对话框

// 进度对话框 : 有圆形和长方形两种。也可以通过 setButton()增加按钮。final ProgressDialog dialog = ProgressDialog.show(DisplayUIActivity.this,"请稍等 ...", "正在处理 ...", true);Thread thread = new Thread(){ public void run(){ try { sleep(3000); }finally{ dialog.dismiss();// 正前方提示:取消对话框 } }};thread.start();dialog.show();

Page 54: Android -汇博

— 高级软件人才培训专家ImageView&ImageButton<ImageView android:id="@+id/pkbestImageView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/pkbest" />ImageView pkbestImageView = (ImageView)this.findViewById(R.id.pkbestImageView);// 正前方提示:等价于 XML 配置 android:src="@drawable/pkbest"pkbestImageView.setImageResource(R.drawable.pkbest); //pkbestImageView.setAlpha(alpha);// 设置 Alpha 值

<ImageButton android:id="@+id/pkbestImageButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/pkbest" />ImageButton button = (ImageButton)this.findViewById(R.id.pkbestImageButton);button.setImageDrawable(this.getResources().getDrawable(R.drawable.pkbest));// 正前方提示:设置图片 button.setOnClickListener(new OnClickListener(){ @Override public void onClick(View v) { Toast.makeText(DisplayUIActivity.this, "clicked me", Toast.LENGTH_SHORT).show(); } );

Page 55: Android -汇博

— 高级软件人才培训专家Gallery<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/main" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent">

<ImageButton android:id="@+id/pkbestImageButton" android:layout_width="fill_parent" android:layout_height="wrap_content" android:src="@drawable/pkbest" /> <Gallery android:id="@+id/pkbestGallery" android:layout_width="fill_parent" android:layout_height="wrap_content" /> </LinearLayout>

Page 56: Android -汇博

— 高级软件人才培训专家Gallery1.通过 BaseAdapter 装载图片库 2.监听 Gallery 的 setOnItemClickListener事件,得知要显示的图片 3.通过 ImageView呈现指定的图片Gallery gallery = (Gallery)this.findViewById(R.id.pkbestGallery); gallery.setAdapter(new PKbestImageAdapter(this));//gallery.setBackgroundResource(R.drawable.pkbest); // 正前方提示:设置背景图片gallery.setOnItemClickListener(new OnItemClickListener(){ public void onItemClick(AdapterView<?> parent, View view, int position,long id) { Toast.makeText(DisplayUIActivity.this, "显示第 "+(position + 1)+" 张图片 ", Toast.LENGTH_SHORT).show(); } });class PKbestImageAdapter extends BaseAdapter{ private Integer[] imageIDs= { R.drawable.pkbest, R.drawable.icon }; private Context context = null; public PKbestImageAdapter(Context context){ this.context = context; } public int getCount() { return imageIDs.length; } public Object getItem(int position) { return position; } public long getItemId(int position) { return position; } public View getView(int position, View convertView, ViewGroup parent) { ImageView image = null; if (convertView == null) { image = new ImageView(context); // 正前方提示:给 ImageView 设置资源 image.setLayoutParams(new Gallery.LayoutParams(120, 120)); // 正前方提示:设置布局 图片 120*120 显示 image.setScaleType(ImageView.ScaleType.FIT_CENTER); // 正前方提示:设置显示比例类型 }else{ image = (ImageView) convertView; } image.setImageResource(imageIDs[position]); return image; }}

Page 57: Android -汇博

— 高级软件人才培训专家ImageSwitcher1.设置 ViewFactory 为数据源,通过 makeView()显示图片 2.通过 setImageResource() 指定图片资源public class ImageSwitcherActivity extends Activity implements OnClickListener,ViewFactory{ private ImageSwitcher imgSwiter = null; private final static int ID = 100; private final static int PREV_BUTTON_ID = 200; private int index = 0; private Integer[] imageArray = { R.drawable.pkbest, R.drawable.icon, R.drawable.ok }; protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); LinearLayout line = new LinearLayout(this);// 正前方提示:创建线性布局 imgSwiter = new ImageSwitcher(this); line.addView(imgSwiter); // 正前方提示:将 imgSwiter 视图添加到线性布局 imgSwiter.setId(ID); imgSwiter.setFactory(this); // 正前方提示:设置 imgSwiter 对象数据源 imgSwiter.setImageResource(this.imageArray[index]); this.setContentView(line); Button prev = new Button(this); prev.setId(PREV_BUTTON_ID); prev.setText("prev"); prev.setOnClickListener(this); LayoutParams param = new LayoutParams(100,100); line.addView(prev,param); } public void onClick(View v) { switch(v.getId()){ case PREV_BUTTON_ID: index --; if(index < 0) index = 0; imgSwiter.setImageResource(this.imageArray[index]); } } public View makeView() { return new ImageView(this);// 正前方提示:图片都是通过 ImageView来显示的 } }

Page 58: Android -汇博

— 高级软件人才培训专家GridView1.XML 布局文件 2. 使用 BaseAdapter (与前的基本上一样)作为数据源 (只是将 Gallery.LayoutParams 换

成 GridView.LayoutParams)<?xml version="1.0" encoding="utf-8"?><GridView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pkbestGridView" android:layout_width="fill_parent" android:layout_height="fill_parent" android:numColumns="auto_fit" 列数自适应 android:verticalSpacing="10dp" android:horizontalSpacing="10dp" android:columnWidth="90dp" android:stretchMode="columnWidth" 缩放模式 (stretchMode="columnWidth" - 缩放与列宽大小同步 ) android:gravity="center"/> View 组件的对齐方式 (居中显示 )

this.setContentView(R.layout.gridview);GridView gridview = (GridView)this.findViewById(R.id.pkbestGridView);gridview.setAdapter(new PKbestImageAdapter(this));// gridview.setBackgroundResource(R.drawable.pkbest);gridview.setOnItemClickListener(new OnItemClickListener(){ public void onItemClick(AdapterView<?> parent, View view, int position,long id) { Toast.makeText(DisplayUIActivity.this, " 您选择第 "+(position+1)+"号图片 ", Toast.LENGTH_SHORT).show(); } });

Page 59: Android -汇博

— 高级软件人才培训专家ScrollView卷轴视图是指内容很多时,一屏显示不完,需要通过滚动来显示。 1.通过 XML配置 ScrollView 布局。 2.硬编码动态添加 View部件。<ScrollView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/pkbestScrollView" android:layout_width="fill_parent" android:layout_height="wrap_content" android:scrollbars="none"> <LinearLayout android:id="@+id/layout" android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="wrap_content"> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="正前方 www.PKbest.CN 0"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="正前方 www.PKbest.CN 1"/> <TextView android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="正前方 www.PKbest.CN 2"/> …………………………………………………………… </LinearLayout></ScrollView>

Page 60: Android -汇博

— 高级软件人才培训专家发送 Email使用系统自带Email 程序,需要配置 email 信息:需要网络支持 ( 网络连接后在启动模拟器 )Email 账号: [email protected] [email protected] 密码 : ############ 外发 Pop3: pop.gmail.com 端口: 995 外发 Pop3: pop3.163.com 端口: 110 接收 Imap : imap.gmail.com 端口: 993 接收 SMTP : smtp.163.com 端口: 25//只发送文本邮件Uri uri = Uri.parse("mailto:[email protected]"); Intent it = new Intent(Intent.ACTION_SENDTO, uri); // 正前方提示:不能设置 it.setType("text/plain");it.putExtra(Intent.EXTRA_TEXT, "The email body content"); it.putExtra(Intent.EXTRA_SUBJECT, "The email subject"); startActivity(it);

//带有 cc 和 bc 的发送方式Intent it = new Intent(Intent.ACTION_SEND);String[] to = {"[email protected]" };String[] cc = {"[email protected]"}; String[] bc = {"[email protected]"}; it.putExtra(Intent.EXTRA_EMAIL, to); it.putExtra(Intent.EXTRA_CC, cc); it.putExtra(Intent.EXTRA_BCC, bc); it.putExtra(Intent.EXTRA_TEXT, "The email body text"); it.putExtra(Intent.EXTRA_SUBJECT, "The email subject"); it.setType("text/plain"); // 正前方提示:需要设置 it.setType(); startActivity(it);//startActivity(Intent.createChooser(it, "Choose Email Client"));// 调用选客户端的界面

Page 61: Android -汇博

— 高级软件人才培训专家带附件的 EmailIntent it = new Intent(Intent.ACTION_SEND); it.putExtra(Intent.EXTRA_TEXT, "The email body content"); it.putExtra(Intent.EXTRA_SUBJECT, "The email subject text"); it.putExtra(Intent.EXTRA_STREAM,uri); //"file:///sdcard/mysong.mp3" sendIntent.setType(mimeType); // "audio/mp3" startActivity(Intent.createChooser(it, "Choose Email Client"));

以上说明 :1. mimeType: 图片 ---- "image/*" 音频 ---- "audio/*" 视频 ---- "video/*"2. uri: 如果是直接读取到文件路径并发送 , 则为 Uri.fromFile(new File(filePath)); 如果是从数据库中查循出来的 uri, 则直接传入即可 .

Page 62: Android -汇博

— 高级软件人才培训专家监听短信Android 设备接收到的 SMS 是 pdu 形式的 (protocol description unit) 。 android.telephony.SmsMessage 这个类可以储存 SMS 的相关信息,

我们也可以从接收到的 pdu 中创建新的 SmsMessage 实例。public class SmsReceiver extends BroadcastReceiver { public void onReceive(Context context, Intent intent) { Bundle bundle = intent.getExtras(); Object messages[] = (Object[]) bundle.get("pdus");

// 正前方提示:是 android.telephony.SmsMessage( 支持 GSM & CDMA) ,不是 android.telephony.gsm.SmsMessage SmsMessage smsMessage[] = new SmsMessage[messages.length]; for (int i = 0; i < messages.length; i++) { smsMessage[i] = SmsMessage.createFromPdu((byte[]) messages[i]); String telCode = smsMessage[i].getOriginatingAddress(); // 发送者号码 String msgBody = smsMessage[i].getMessageBody().toString(); // 短信内容 } }}订阅方式:<receiver android:name=".tel.SmsReceiver"> <intent-filter> <action android:name="android.provider.Telephony.SMS_RECEIVED" /> </intent-filter> </receiver> 或者:IntentFilter filter = new IntentFilter("android.provider.Telephony.SMS_RECEIVED");SmsReceiver receiver = new SmsReceiver();registerReceiver(receiver, filter);

<!-- 接收 SMS 权限 --><uses-permission android:name="android.permission.RECEIVE_SMS"/>

Page 63: Android -汇博

— 高级软件人才培训专家监听电话监听电话状态需要: 1. 获取 TelephonyManager service ,添加自己的监听器 2. 自己的监听器要继承 PhoneStateListener ,重写 onCallStateChanged() 方法

// 正前方提示获:取电话的 service ,应在 android.intent.action.MAIN activity 中获取TelephonyManager tm = (TelephonyManager)this.getSystemService(Context.TELEPHONY_SERVICE); tm.listen(new PKbestPhoneListener(), PhoneStateListener.LISTEN_CALL_STATE); // 注册电话通信 listener

class PKbestPhoneListener extends PhoneStateListener{ @Override public void onCallStateChanged(int state, String incomingNumber) { switch(state){ case TelephonyManager.CALL_STATE_IDLE: // 无任何状态,电话挂点后仍是空闲状态 break; case TelephonyManager.CALL_STATE_OFFHOOK: // 接听电话 break; case TelephonyManager.CALL_STATE_RINGING: // 来电 break; } super.onCallStateChanged(state, incomingNumber); } }<!-- 监听电话权限 --><uses-permission android:name ="android.permission.READ_PHONE_STATE"/>

Page 64: Android -汇博

— 高级软件人才培训专家MediaPlayer

Page 65: Android -汇博

— 高级软件人才培训专家播放音乐获得 MediaPlayer 对象: (注意三者的在 start 之前调用略有不同) 1. 如果是 res 下资源文件(即与程序一起打包文件) player = MediaPlayer.create(this,R.raw.pkbest); player.start(); 2. 网络文件,使用: Uri uri = Uri.parse("http://www.PKbest.CN/media/sexy.mp3"); player = MediaPlayer.create(this,uri); player.prepare(); player.start(); 3.sdcard 文件 MediaPlayer player = new MediaPlayer(); player.setDataSource("/sdcard/sexy.mp3"); player.prepare(); player.start(); // 播放音乐MediaPlayer player = new MediaPlayer();player.reset(); // 正前方提示:设置 idle 状态player.setDataSource("/sdcard/sexy.mp3"); // 正前方提示: sdcard 下文件使用 setDataSource 方法player.prepare();player.start();player.setLooping(true);// 停止播放if(player.isPlaying()){ player.stop();}

Page 66: Android -汇博

— 高级软件人才培训专家参考资源http://androidappdocs.appspot.com/http://www.linuxgraphics.cn/gui/http://www.coolapk.com/docs/

Page 67: Android -汇博

— 高级软件人才培训专家Thanks

本人能力有限,有不足之处,请多指教!

thanks

杨喜山 2011-08-27

Page 68: Android -汇博

— 高级软件人才培训专家广告正前方最近活动: 手机 课 程: Android3.2 、 iPhone4 javaEE课程: struts2.1 、 spring2.5 、 hibernate3.3 、 oracle 、 JS web 技术 : pkbest.js 类库 网络技术 : http协议攻破、网络数据抓取、 B/S 软件外挂 框架产品 :数据库持久化产品、无需配置的 MVC 框架、智能类库 定制产品 :根据用户的需求,提供合理简便的解决方案、产品