操作系统和所需(推荐)的工具都准备好之后,接下来我们重点关注的就是Android SDK了。开发者可在http://developer.android.com/sdk下载适合操作系统的SDK以及最新的安装说明。Android Studio自带SDK,但如果你喜欢独立的版本,可另行下载。 确保SDK始终是最新的,还要为我们开发的所有Android版本下载API。更新Android SDK最简单的方法是在提示符下运行如下更新命令: $ android update sdk --no-ui 在Android SDK文件夹内有一些子文件夹。从工具的角度看,只有platform-tools和tools文件夹是我们关心的。本书会介绍其中的一些工具并解释如何使用它们,从adb(Android Debug Bridge)开始。如果开发者经常在命令行中使用这些工具,建议把SDK的文件夹路径添加到PATH环境变量中。 开发者可在http:// developer.android.com/tools/help/index.html上找到大部分Android SDK工具的官方文档。 1.2.1 adb工具 adb位于platform-tools文件夹,开发者用它在设备上安装启动应用。在Android SDK的早期版本中,adb还在tools文件夹内。除了能在IDE中安装、启动、调试应用外,开发者还可手动用adb在Android设备上做一些底层的调试操作。在终端(Linux或者Mac OS X)或者命令提示符(Windows)键入adb help all,就会列出所有可用的命令。 一些常用的adb命令如下: adb devices,列出所有连接的Android设备和虚拟机; adb push <local> <remote>,将电脑上的文件复制到设备(通常存到SD卡); adb pull <remote> <local>,将设备上的文件复制到电脑。 1. adb和多设备 如果要在两台或者多台设备上同时开发和调试应用,比如多人游戏或者即时通信应用,需要将–s <serial number>作为adb的第一个参数来识别开发者想要的设备。adb devices命令会列出已连接设备的序列号。下面的示例可在特定设备上运行logcat命令: $ adb devices List of devices attached 0070015947d30e4b device 015d2856b8300a10 device $ adb -s 015d2856b8300a10 logcat 当有多台连接的设备或者模拟器时,在IDE中启动应用会弹出一个选择对话框。 2. 掌握logcat过滤 日志记录是Android应用程序开发的重要组成部分。虽然可以使用IDE强大的断点调试功能来跟踪执行流程以及检查不同变量的值和状态,但简单地从logcat中查看输出往往会更有效。Android的日志记录是由logcat函数处理的,它通常被集成在IDE中,不过也可通过adb命令启动。 因为Android把所有的系统以及应用程序日志消息都输出到了同一个流,所以很难找到特定应用的日志。幸好有一些简单的方法能过滤日志,如下面代码所示。 Android日志消息前面会有一个标签和优先级。通常,开发者可以像下面这样为应用程序的每一个类定义一个单独的日志标签: private static final String TAG = "MyActivity"; 接下来就可在类代码中用上面定义的标签来打印日志消息: Log.d(TAG, "Current value of moderation:" + moderation); 下面的命令只会打印以MyActivity为标签的日志消息: $ adb logcat MyActivity:* *:S logcat后面的参数代表需要应用的过滤条件,它们被格式化为<tag>:<priority>,其中星号(*)表示任何可能的值。一件很容易被遗忘的重要事情是,开发者需要添加特殊的过滤*:S来过滤掉所有的消息。结合自定义过滤器,开发者很容易就可以控制logcat只打印预期的消息。 如果使用过滤器查看logcat输出,建议加上AndroidRuntime:*参数,这样会显示Android系统相关的日志信息以及由平台引起的应用程序异常。 3. 用Wi-Fi连接adb 通常情况下,使用USB连接Android设备和电脑。但是,也可以用Wi-Fi通过标准的TCP/IP连接来连接Android设备。这在开发监听USB相关事件的应用程序时会特别有用(原因是USB连接会起到干扰作用),比如USB的连接/断开事件,或者只是由于开发者懒得在开发中使用USB线。 要想通过Wi-Fi连接adb,首先要像通常一样用USB线连接Android设备和电脑。同时,要确保电脑和设备连接的是同一个Wi-Fi。接下来还要取得设备的IP地址,打开Setting→Wi-Fi→Advanced(设置→Wi-Fi→高级)页面,列表底部会显示当前Wi-Fi的IP地址。 设置好以上步骤后,在终端运行如下命令: $ adb devices List of devices attached 0070015947d30e4b device $ adb tcpip 5555 $ adb connect 192.168.1.104 $ adb devices List of devices attached 192.168.1.104:5555 device 第一个命令只是验证设备已经处于调试模式。第二个命令会在TCP/IP模式下重启adb守护进程,然后监听5555端口(adb的默认端口)。第三个命令使用电脑上的adb服务连接设备的IP地址(使用默认的5555端口)。最后,第四个命令验证已通过TCP/IP成功地连接了电脑和设备。接下来可以拔掉USB线,像往常一样用IDE进行开发。 adb守护进程会一直保持TCP/IP模式,直到设备重新启动,或者运行了adb usb,该命令会重启USB守护进程。 不是所有的设备都支持Wi-Fi连接。同样,Wi-Fi连接下的通信性能会更糟,当需要部署更大的应用时可能会很麻烦。 4. 在Android设备上执行命令 由于Android系统基本上是一个定制的Linux发行版,开发者可像在电脑上操作Linux一样来操作它。运行一条特殊的adb命令可以在Android设备上启动标准的shell,然后就可以像其他Linux设备一样,执行命令行操作了。 $ adb shell 当在Android设备上运行shell时,am和pm命令会很有用,这两个命令和时间没关系。相反,开发者用它们跟应用程序(Application)和包管理器(Package Manager)交互,这在早期的开发以及测试环节会很有用。比如,在开发一个由外部Intent启动的Service时,可以用am命令手动发送该Intent。 在命令行中输入如下命令,便可用Intent启动一个Service: $ adb shell am startservice –a <intent action> 开发者可以添加额外的参数,甚至能指定一个特定的组件名称。除了能启动Service外,还可以启动Activity或者发送Intent广播。无参的adb shell am会列出所有可能的命令列表。如果在开发过程中需要测试一个Service,但是启动它的Activity还没有被创建,这时候该命令会非常有用。同样,该命令在模拟其他应用程序发送Intent时也很有帮助,比如ACTION_VIEW或者ACTION_SEND。 包管理器是Android上的一个核心组件,它用来管理设备上已安装的应用程序。可以像使用应用程序管理器(Application Manager)一样控制pm命令的使用。包管理器允许开发者查看、安装、卸载设备上已安装的应用程序(包),还能检查这些应用的特性以及权限。虽然在开发过程中pm命令不像am命令那么有用,但相对其他方法来说,pm命令更容易让开发者了解设备的相关细节。比如,下面的命令可列出所有已安装的包(也就是说,已安装的应用程序): $ adb shell pm list packages 除了上面提到的命令,开发者还需熟悉其他一些adb命令。如果还没有做到这一点,多花些时间研究一下这些命令。 可在http://developer.android.com/tools/help/adb.html上找到adb命令列表以及它们的用法。 1.2.2 用Monkey对应用UI做压力测试 大多数开发者认为测试是一项乏味且让人厌烦的工作,Android开发者可能也是这种感觉。优秀的开发者通过自动化测试来验证他们应用程序中的部分代码。也可通过代码检查工具找到常见的代码编写错误(1.5.2节将详述其中一种工具)。然而,正如你可能想到的,编写自动化测试以及执行静态代码分析并非十分简单。用户不会一直按照某种特定的行为去使用应用,他们可能在非预期的时刻点击了某个按钮或者意外点击了一个不合适的按钮,这都可能导致应用崩溃。基本上开发者需要的是像用户一样去使用应用,更确切地说,像猴子一样。 Android SDK附带了一个称为Application Exerciser Monkey的强大工具,简称为Monkey。它是一个命令行工具,能在设备上模拟触摸等随机用户事件以及系统事件。目的就是模拟用户的行为来对应用程序做压力测试。虽然Monkey不会为应用程序模拟一些经典的用例场景,但是在模拟应用程序如何处理一些非预期用户行为方面它会提供非常有用的反馈。 下面的命令对指定<package name>的应用程序执行Monkey,还可以用<event count>参数指定随机事件数量。 $ adb shell monkey –p <package name> <event count> Monkey默认在未处理异常出现时停止执行,并上报错误消息。这对检查代码中NullPointerExceptions等异常或者类似问题很有帮助。也可调整参数来改变Monkey的默认行为,比如当某种安全异常出现时停止运行。 用Monkeyrunner编写Monkey脚本 更高级的Monkey用法是使用Monkeyrunner API为应用程序编写Python脚本。这对在集成开发环境中执行Monkey工具和其他操作特别有用。它还能为按键提供输入,并且能用编程方式(同样使用Monkeyrunner API)捕获屏幕截图,以便和一组已知的正确屏幕截图比较。 对Android开发团队来说,使用Monkeyrunner具备很大的优势,因为几乎不费什么劲儿就能提供一个强大的回归测试解决方案。有时应用发布前只有一个测试员,这种情况下即便很小的代码改动都可能带来难以检测的意外结果。强烈建议在应用发布前使用Monkey工具,特别是用Monkeyrunner脚本进行回归测试。 可在http://developer.android.com/tools/help/monkeyrunner_concepts.html#APIClasses上查看Monkeyrunner API。 1.2.3 在Android上使用Gradle构建系统 随着Android Studio的发布,谷歌也推出了全新的模块化构建系统,以替代旧版本SDK中的Ant脚本。在Android Studio中创建新项目同时会创建所有的Gradle脚本。 Gradle是像Ivy和Maven一样的模块化构建系统。它结合了Ant的灵活以及Maven中的依赖管理。Gradle使用Groovy领域专用语言,开发者可以更清楚地描述配置项,不用再写复杂的XML构建脚本。 下面的代码是为新项目创建的默认build.gradel文件。第一个区块告诉gradle使用哪个仓库下载构建所用的插件以及依赖(这个依赖不同于后面即将介绍的项目依赖)。接下来的部分告诉gradle应用哪种插件,本例中使用的是Android插件,基于此即可开展后面的Android开发。再下面是项目的依赖,本例只使用了位于libs目录里的支持包。最后的区块以android开头,定义了项目的配置项。 buildscript { repositories { maven { url 'http://repo1.maven.org/maven2' } } dependencies { classpath 'com.android.tools.build:gradle:0.5+' } } apply plugin: 'android' dependencies { compile files('libs/android-support-v4.jar') } android { compileSdkVersion 18 buildToolsVersion "18.0.0" defaultConfig { minSdkVersion 18 targetSdkVersion 18 } } 可在http://tools.android.com/tech-docs/new-build-system/user-guide查看新的Gradle构建系统用户手册。 应用了新构建系统的Android项目的默认目录结构跟开发者之前熟悉的有点不同,不再使用扁平结构,而是有两个集合:源代码和测试代码。它们在如下的目录中: src/main/ src/instrumentTest/ Java源代码位于main/java目录,资源文件位于main/res目录。AndroidManifest.xml直接位于main目录(如图1-1所示)。 其他项目目录有assets(二进制资源)、aidl(Android IDL文件)、rs(RenderScript源文件)以及jni(本地C/C++代码)。 虽然可以直接在Android Studio IDE中构建运行项目,也可通过命令行与构建系统交互。Gradle定义了一系列任务。在项目根目录下输入如下命令即可列出所有可用的任务。 $ ./gradlew tasks 比如,如果从头开始构建应用程序,只需运行下面的命令。 $ ./gradlew clean build 该命令首先执行clean任务,接下来执行build任务。 图1-1 Android Studio IDE中的目录结构以及Gradle构建文件 从现有项目迁移到Gradle 由于大部分现有Android项目并没有使用Gradle构建系统,所以需要一个迁移向导。最简单的迁移方法是使用Android Studio创建新的Android项目,然后把原项目复制到新项目的子文件夹内。 接下来把Android Studio创建的build.gradle文件复制到已迁移项目的根目录下。 android { sourceSets { main { manifest.srcFile 'AndroidManifest.xml' java.srcDirs = ['src'] resources.srcDirs = ['src'] aidl.srcDirs = ['src'] renderscript.srcDirs = ['src'] res.srcDirs = ['res'] assets.srcDirs = ['assets'] } } } 像上面的例子一样编辑android部分,这应该对所有沿用老标准目录结构的Android项目都有效。如果你的项目结构有所不同,只需在前面的示例中改变路径即可。(注意:所有的路径都是相对的。) 1.2.4 用ProGuard优化和混淆代码 Android应用程序是Java代码、XML以及其他资源文件的编译结果。其中,Java代码被编译为称作dex的二进制格式,Android平台中的Dalvik虚拟机在执行代码时会从中读取内容。dex被设计成人类不可读的格式,可以使用工具把它反编译成人类可读的格式。 在某些情况下,反编译代码可能存在安全问题,比方说代码中包含密钥或者其他不应被轻易获取值的情况(如与授权服务器集成)。虽然很难实现完全防止反编译代码,但可以通过在发布前对代码进行混淆,让反编译变得更加困难。这样逆向工程会更加耗时,攻击者可能知难而退。 开发者使用集成在Android SDK中的ProGuard工具来对Android代码进行混淆。Gradle构建工具也支持该工具,所要做的是在build.gradle文件的android部分加入如下的代码。 buildTypes { release { runProguard true proguardFile getDefaultProguardFile('proguard-android.txt') } } 这将在应用程序的发布阶段打开ProGuard,正常的开发过程不会对代码进行混淆。 另一个混淆代码的原因是这样做能执行一些额外的优化,同时,删除无用的代码能压缩生成的二进制dex文件。这在引入一个大的第三方库时特别有用,因为它可以显著减小最终的文件大小和运行时的内存使用量。
Android编程实战——1.2 Android SDK进阶
书名: Android编程实战
作者: [阿根廷] 赫尔曼
出版社: 人民邮电出版社
原作名: Android Programming: Pushing the Limits
译者: 丁志虎 | 武海峰
出版年: 2014-6-1
页数: 348
定价: CNY 69.00
装帧: 平装
ISBN: 9787115357335