• 第一部分:开发前的准备-第九章 开发入门


    第9章 开发入门

    本章从5个方面来讲解一个做出好应用需要注意哪些地方,它们包括

    1. 管理虚拟设备

    2. 项目管理

    3. 编译与执行

    4. 调试

    5. 图形处理神器draw9-patch

    在开始讲解这5个方面之前,首先让我们看一下Android程序程序的开发流程

    (1)Setup(设置)

    在这个阶段,你安装SDK,并设置好开发环境。然后我们可以创建Android虚拟设备(AVDS)或者直接用真机连接Eclipise,不管是虚拟机还是真机都能安装我们的应用程序。

    (2)Development(开发)

    在这个阶段,我们需要建立和开发我们的android工程,其中包含所有源代码和资源等。

    (3)Debugging and Testing(调试和测试)

    在这个阶段,我们需要建立一个debuggable .apk专用来调试,并可以使用此APK在模拟器和真机上安装和运行。

    关于调试和测试的更多细节我们后面会讲解

    (4)Publishing(出版)

    这个阶段,我们需要发布我们的APK。出版发行是单独一个部分,在第三大篇会讲述,此章不会讲解

    具体内容我们可以通过图9-1来了解一下:

     

    图9-1 Android程序程序的开发流程

    9.1 管理虚拟设备

    一个AVD(Android虚拟设备)是一个以实际设备为参考的模拟器。创建AVD最简单的方法就是使用图形化的AVD Manager工具。你可以从Eclipse中点击Window > AVD Manager。在Windows下你也可以在<sdk>/tools/目录下直接双击android.bat。

    一个AVD是由以下部分的组成的:

    (1)硬件配置文件:定义虚拟设备的硬件功能。例如,你可以定义设备是否有一个摄像头,它是否使用一个物理QWERTY键盘或拨号盘,它有多少内存,等等。

    (2)一个系统镜像的映射: 你能定义什么样的android系统版本运行在此AVD上。你能选择一个标准的android平台版本或SDK中附加组件封装的系统镜像。

    (3)其他选项: 你能指定AVD的皮肤,尺寸,外观等,并还能指定模拟的SD卡供AVD使用。

    (4)在你开发的电脑上有一个专用的存储区域: 设备的用户数据和模拟的SD卡都存储在这个区域

    你能创建许多AVDs来测试你的应用程序,保证他们能在不同设备上都能很好的工作。请注意AVD的分辨率,密度,系统版本都可能会影响应用程序的效果。所以你可以创建多个AVD来测试。

    当你为你的AVD选择一个系统镜像时(android系统版本),请记住下面一些要点::

    (1)APILevel的target是非常重要的,因为你的应程序将无法执行低于API Level的应用,但我们可以在manifest中指定minSdkVersion属性,例如我们的创建模拟器的时候选择是2.2版本,minSdkVersion可以低于或者等于8,但绝不能高于8不然就无法安装此应用。

    (2)为了保证兼容性,我们可以尽量使用比较低的系统版本来开发应用,这样能支持更多的设备。

    (3)如果我们的应用在声明manifest中声明一个uses-library节点,那么这个App仅能当成一个扩展的库赖运行在一个系统镜像上。如果你想在模拟器上运行一个需求库文件的应用程序。通常情况下,你必须创建使用附加组件的AVD的平台(例如,Google APIs的附加组件包含Google Maps库)。

    9.1.1使用AVD Manager管理AVDs

    AVD Manager其实很容易管理AVD,它有一个图形界面 ,你只要稍微设置下就能满足你的要求了。你可以对AVD执行新建,编辑,删除等操作。如图9-2所示:

     

    图9-2 AVD Manager截图

    9.1.2创建一个AVD

    我们可以创建许多AVDs,这样我们能在每个API Levels下测试我们的应用。创建一个AVD:

    1. 启动AVD Manage:

    (1)在Eclipse中: 选择Window > AVD Manager,或者在Eclipse 工具栏点击  AVD Manager 图标。

    (2)在其他IDE中:windows下请找到SDK文件存放的位置,然后再tool目录下执行 android.bat。

    2. 新建一个AVD

    在虚拟设备的面板,你会看到的现有AVDs列表。单击“new”创建一个新的AVD。会出现如下对话框,如图9-3所示:

     

    图9-3 AVD Manager中点击“new”创建一个新AVD的截图

    3. 填写AVD的一些细节

    给它一个名字, 平台target, SD卡大小,一个皮肤(skin) 。你还可以在Hardware部分选择“new”来添加指定的硬件选项。下面会有一张表来详细讲述硬件细节

    4. 最后点击Create AVD。完成

    你的AVD已经准备好了,你可以继续新建其他AVD或者返回上一层选择一个已创建好的AVD点击“Start”来启动一个模拟器。启动后的模拟器截图如图9-4所示:

     

    图9-4 模拟器启动后的截图

    9.1.3硬件选项

    下面表格9-1中的内容是AVD的模拟硬件选项:

    特征

    描述

    属性

    Device ram size

    设备上物理的RAM总量,单位为MB(1000KB),默认为96

    hw.ramSize

    Touch-screen support

    设备上是否有触摸屏。默认为"yes" 

    hw.touchScreen

    Trackball support

    设备上是否有轨迹球。默认为"yes"

    hw.trackBall

    Keyboard support

    设备上是否有一个QWERTY 键盘。 默认为"yes"

    hw.keyboard

    DPad support

    设备上是否有DPad键。默认为"yes"

    hw.dPad

    GSM modem support

    设备是否有GSM模式。默认为"yes"

    hw.gsmModem

    Camera support

    设备上是否有一个摄像头。默认为"no"

    hw.camera

    Maximum horizontal camera pixels

    摄像头的最小水平像素值。默认为"640"

    hw.camera.maxHorizontalPixels

    Maximum vertical camera pixels

    摄像头的最小垂直像素值。默认为"480"

    hw.camera.maxVerticalPixels

    GPS support

    设备上是否有GPS。默认为"yes"

    hw.gps

    Battery support

    设备上是否有电池。默认为"yes"

    hw.battery

    Accelerometer

    设备上是否有加速计。默认为"yes"

    hw.accelerometer

    Audio recording support

    设备上是否能录音。默认为"yes"

    hw.audioInput

    Audio playback support

    设备上是否能播放音频。默认为"yes"

    hw.audioOutput

    SD Card support

    设备是否支持插入/移除虚拟的SD卡。默认为"yes"

    hw.sdCard

    Cache partition support

    设备上是否使用高速缓存分区。默认为"yes"

    disk.cachePartition

    Cache partition size

    设备上默认的高速缓存分区大小为 66MB

    disk.cachePartition.size

    Abstracted LCD density

    AVD屏幕的密度大小。默认为“160”

    hw.lcd.density

    表格9-1 AVD的模拟硬件选项

    9.2 项目管理

    项目(Projects)中存储了代码和资源文件。请尽量使用Eclipse和ADT来创建项目。下面三种项目类型在结构上是相同的,但功能上不同。

    1. Android Projects

    Android 项目包含源代码,资源文件和其他文件(如manifest)。这是编译后最终以.apk文件格式安装到设备上的主要项目类型。

    2. Test Projects

    这些项目包含代码在设备上来测试你的应用程序。

    3. Library Projects

    这些项目包含共享的android源代码和资源,你可以从其他android项目中引用他们。当你要重用的时候这是非常有用的。库项目不能安装到设备上,但在其他android项目引用并编译时能pull到.apk文件中。

    下面我们分别看下每个项目中文件夹的含义。

    9.2.1 Android Projects

    下面这些文件夹在Eclipse下会自动帮你生成一些但不会全部都生成,如果你需要的话,可以自行创建:

    src/

    存放源代码的地方

    bin/

    编译后的输出目录。这里你可以找到.apk文件和其他编译后的资源

    jni/

    包含使用Android NDK的本地代码。这里只要稍微了解下,系统级程序员需要了解NDK,以后在讲

    gen/

    包含R.java文件,这个文件是由ADT自动生成的,请不要随意修改它

    assets/

    你能在这里放入原始的asset 文件。例如一些文档,这里的文件会保留原来的文件名被编译到.apk文件中,并且你还能使用文件系统的URL机制来读取文件,例如使用AssetManager类来读取一个字节流。

    res/

    包含应用程序的资源,如drawable文件, layout文件, string值. 更多详细内容第二篇讲解

    anim/

    这里可以放入动画XML文件

    color/

    这里可以放入颜色XML文件

    drawable/

    这里可以放入位图(PNG,JPEG,GIF)还有9-Patch图片文件,并且也能放置XML文件用来描述Drawable形状和Drawable对象的多种状态切换

    layout/

    这里可以放入布局XML文件

    menu/

    这里可以放入定义菜单的XML文件

    raw/

    这里和assets/差不多都是放入原始的asset文件。但访问的方式与assets/不同。这里必须用R文件来引用,例如如果需要在这里放入一个bg.ogg音频文件,那么请这样调用R.id.bg 。一般来说这里都是放多媒体文件

    values/

    这里可以放入许多种类的XML文件。不同于其他res/目录下的资源。这个文件夹下的XML文件不能由文件名直接引用。但XML文件中的节点可以控制R文件定义的名字。

    xml/

    一些用来配置App组件的其他XML文件。

    libs/

    包含似有的一些库文件。

    AndroidManifest.xml

    用来描述App的性质和它的每一个组件的一种控制型文件。 例如需求的API Levels ,描述四大组件的特征,权限等。我们必须熟悉它的功能以后对我们开发android应用有很大的帮助

    project.properties(早期的ADT生成的是default. properties)

    这个文件包含项目的设置,如编译target。他属于项目的一个部分。

    local.properties

    根据你本地的计算机的系统生成的一个属性文件。如果你使用Eclipse,这个文件不会被使用。

    ant.properties

    构建系统的自定义属性。Ant,是一个将软件编译、测试、部署等步骤联系在一起加以自动化的一个工具,大多用于Java环境中的软件开发。由Apache软件基金会所提供。例如Ant文件构建就是我们常所知道的src,lib,class这样的目录结构,Eclipse就是这种目录结构。如果你使用Eclipse,这个文件不会被使用。

    build.xml

    为你的项目构建Ant文件。仅仅适用于为Ant构建的项目。目前来说AndroidManifest.xml后面的内容大家先可以忽略不计,我们用的很少。接下来我们使用Eclipise创建一个Android Project。步骤如下:

    1. 选择File > New > Project.

    2. 选择Android > Android Project, 然后点击 Next.

    3. 为项目选择和填入相应的内容:

    (1)输入Project Name。这个名字就是创建项目的文件夹名字。

    (2)选择“Create new project in workspace。”

    (3)选择Target。这里主要就是选择我们的应用是基于哪个系统版本开发的。

    注意: Target这里是可以修改的,我们可以在任何时候修改它:在项目右键选择Properties,然后选择Android,在选择你需要切换的系统版本

    (4)接下来需要填入一些字段:应用程序名,包名,主Activity名和最小SDK版本

    4. 点击Finish.

    9.2.2 Library Projects

    Android库项目你可以理解为java中的jar包,只是它没有被编译还是源码方面我们修改,最终目的都是为了重用代码和资源。多个应用可以引用同一个库项目,任何一个应用也能引用多个库项目(注意: 你需要使用SDK Tools r14或更高的版本来使用新的库项目特性,关于关于SDK Tools的信息请查阅http://developer.android.com/sdk/tools-notes.html)。如果你有多个Android项目,并且它们都有共同的源代码和资源,你就可以将它们移动到一个库项目,这样跨应用程序和版本会更容易维护。下面是一些常见的使用库项目的情况:

    (1)如果您正在使用相同的组件开发多个相关的应用程序,那么你可以搬出每个应用项目中冗余的组件。然后使用库项目创建单一个的,可重复使用的一套组件。

    (2)如果你正在创建一个应用程序,存在免费和付费两种版本。那么请毫不犹豫的使用库项目吧。

    库项目在结构上和android项目没有很大的差别,几乎是一样的。不同的地方就是单纯的库项目是不能运行于Android设备上的。也不能导出成一个独立的jar包。但请不要怀疑它的功能,它的确是有用的。当你的应用程序依赖与一个库项目的时候,SDK工具会吧库项目编译成一个临时的jar文件让主项目使用。并且当你的资源ID和库文件定义一样的话,SDK工具会优先使用你主项目的资源,库文件的一些内容就不会编译到.apk中,这种强大的灵活性读者应该尽量掌握它。不仅如此,还可以给每个库文件指定相对的优先级。例如你的App中同时使用几个库项目,但有2个库项目有相同的资源ID,那么它会使用优先级高的那个库项目,而放弃低级别的。库项目可以引用其他库项目,并能以正常的方式导入外部库文件(如JAR包)。

    关于这一点目前目前国内很多Android版的SDK就是这么样的,例如各大开放平台中Android版的微博的SDK都使用了库文件,,笔者强力推荐大家多使用这种库项目来管理。这种高度灵活性与可复用性会让你觉得写N个有相同功能或相同组件的应用程序其实是非常简单的!

    9.2.2.1 使用库项目开发注意事项

    当你开发库项目和依赖库项目的应用程序时,请考虑以下几点:

    1. 资源冲突

    当资源相同后合并的项目,会去掉优先级低的相同资源。请最好做到心中有数。

    2. 使用前缀,以避免资源冲突

    共同的资源ID,为了避免资源冲突,可以考虑使用一个前缀或其他一致的命名方案。

    3. 您不能导出一个库项目到一个JAR文件

    一个库不能被当成一个二进制文件(如一个JAR文件)处理。也许未来的SDK工具会提供这个功能。

    4. 一个库项目能包括一个Jar库

    你能包含一个jar库来开发库项目。但是你必须手动指定jar的路径

    5. 一个库项目可以依赖于外部jar库

    例如Google APIs 就是一个外部库,虽然可以使用,但请注意在manifest 文件使用<uses-library> 节点中声明它。

    6. 库项目不能包含raw assets

    因为raw assets有两种模式,这里仅指的是asset/目录下的raw asset文件。因为SDK工具不支持在一个库项目中使用asset/目录下raw asset文件。就是说我们不能吧raw asset文件放入assets/目录下,但是我们可以放到res/raw/目录下。

    7. 库项目系统版本必须低于或等于Android项目系统版本

    例如你的库项目为2.1你的android项目为1.6那么这将无法编译。

    8. 库包名没有限制

    库包名和主项目包名不一定是要相同的。

    9. 每个库项目会创建它自己的R.class

    每个库都有自己的R文件,你可以通过使用库包名来引用R文件。永远记住R文件是自动生成与变化的,请不要修改

    10. 库项目的存储位置

    对于存储位置没有具体的要求,重要的是你的主项目能通过相对链接引用到库项目就OK。

    9.2.2.2 设置一个库项目

    库项目是标准的android项目,你能像创建android项目那样创建它。然后稍微需要几个步骤就能吧它设置成一个库项目:

    1. 在项目上右键选择 Properties

    2. 在Properties 窗口, 选择 "Android" ,然后再下方的“Is Library”上打个勾即可

    3. 点击OK

    那么现在这个项目被标记为库项目了。其实你可以在库项目和android项目中切换,只要吧那个勾去掉即可。操作结果如图9-5所示:

     

    图9-5 标记一个android项目为库项目

    9.2.2.3 引用一个库项目

    如果你正在开发一个应用程序,并需要引用共享的库项目,那么接下来我们需要几个步骤来设置一下即可:

    1. 在项目上右键选择Properties

    2. 在Properties 窗口, 选择 "Android" ,然后点击Add。

    3. 然后再库列表,选择我们需要的库,点击OK

    4. 回到Properties 窗口继续点击OK.

    如果你引用多个库项目,可以使用"Up"来提高库的优先级。引用后的截图如图9-6所示:

     

    图9-6 项目中引用一个库项目后的截图

    9.2.3 Test Projects

    测试项目使用专门的一套框架(第二大篇讲解)。这套专门的测试框架是基于JUnit测试框架扩展的,测试项目的文件结构和android项目一样。下面我们简单的讲解一下测试方面的内容

    src/

    包括你需要测试的源文件。测试项目不需要Activity .java 文件, 但可以包含一个。

    gen/

    包含R.java文件,这个文件是由ADT自动生成的,请不要随意修改它。

    assets/

    你能在这里放入原始的asset 文件

    res/

    和android项目中的一样。

    AndroidManifest.xml

    和android项目中的一样。但需要注意的是测试项目需要指定一个 <instrumentation> 节点来让App项目链接测试项目。

    project.properties,local.properties,ant.properties,build.xml

    和android项目中的一样。

    启动android应用程序的测试环境,你必须首先使用需要测试的代码来创建一个单独的项目。并且新建的测试项目与android项目的目录结构是一样的。与android项目的一个小区别就是测试项目需要在manifest 文件中声明一个<instrumentation>节点,但是使用Eclipse的读者完全不用担心,Eclipse中的ADT会自动创建这个节点。接下来我们来使用Eclipse创建一个测试项目。步骤如下

    1. 在Eclipse, 选择File > New > Other。

    2. 展开Android下的列表, 选择 Android Test Project, 然后点击 Next. 

    3. 输入Test Project Name。

    4. 使用默认的工作空间,这里一般直接略过,如果你想指定在其他地方,可以自己指定。

    5. 在Test Target 面板, 设置一个已经存在的 Android Project, 点击Browse, 然后选择你需要测试的application。

    6. 剩下的工作和创建android项目一样。当你点击完成后,manifest文件中会自动生成<instrumentation>节点

     9.2.3.1 创建一个测试包

    如果你创建了一个测试项目,你需要一个测试包。这个包不是必须要求有一个Activity,如果你想的话还是可以定义一个。测试包不需要Android GUI(图形化用户界面),当你在Eclipse使用ADT执行测试包时,结果会出现在JUnit界面中。为了创建一个测试包,使用android.test启动一个Android的测试用例类。这些类是继承自TestCase类。下面添加一个测试用例类到你的项目中,步骤如下:

    1. 在Project Explorer 选项卡,打开你的测试项目,然后打开src文件夹,点击测试包。如图9-7所示:

     

    图9-7 展开src后点击测试包的截图

    2. 选中src下面的java包。新建一个Test类(名字根据自己需求改)

    3. 继承 AndroidTestCase 类,如图9-8所示:

     

    图9-8 我们的Test类需要继承android.test.AndroidTestCase类

    4. 然后给Test创建一个无参的构造函数并使用super()调用父类的构造函数,这是JUnit要求的。

    我们可能需要重写 setUp() 和tearDown() 方法来控制我们的测试环境:

    (1)setUp():这个方法在任何测试方法之前被调用。使用这个方法来建立测试环境(这个测试夹具能使用setUp()来用action ACTION_MAIN来实例一个新的Intent。你能使用这个intent在测试下启动Activity。

    (2)tearDown(): 这个方法在所有测试方法之后调用。使用它来垃圾回收和重置测试夹具。

     9.2.3.2 执行测试

    在Eclipse上选中测试的项目,鼠标右键选择Run As... > Android JUnit Test即可运行测试项目。执行成功和失败的截图,分别为图9-9和图9-10.

     

    图9-9 测试执行成功后的截图

     

    图9-10 测试执行失败后的截图

    9.3 编译与执行

    9.3.1使用真机设备

    其实大部分开发者都喜欢用真机来测试我们的应用,最好的一个优点就是它快。模拟器的速度实在是慢的不行,不管你的电脑配置多高都是比较慢的,尤其是你APK越来越大以后。就跟蜗牛一样了,并且有些功能模拟器上实在是不好测试或者测试不了。但我们依旧不能放弃模拟器,因为为了测试兼容性,作为个人开发者来说不可能买很多不同的手机来测试吧,就算是公司也只会买几个比较典型配置的机子。所以笔者的建议是关于测试功能请使用真机,关于测试兼容性请打开你的各种模拟器吧。使用真机来调试和测试我们的应用程序和模拟器上要做的差不多,但首先还是有些不同的地方需要我们做:

    1. 在Manifest文件中声明应用为“debuggable”

    使用Eclipse时,你可以跳过这一步,因为直接从Eclipse IDE中运行你的应用程序会自动启用调试。

    在AndroidManifest.xml文件中,添加 android:debuggable="true"到 <application>节点中。

    注意: 这个android:debuggable="true"目前来说我们可以无视掉,因为绝大多数都是用Eclipse开发。万一你设置了这个属性,请一定记得在发布时去掉它

    2. 在我们的真机上打开“USB 调试模式”

    设备上点击 设置(Settings )->应用程序(Applications )->开发(Development)->USB调试(USB debugging)。

    3. 设置我们的系统来探测我们的设备。

    (1)如果在Windows上开发,你需要为adb工具安装一个usb驱动。关于这一点我们现在无需深入了解,一般来说装个豌豆夹就OK了。

    (2)如果在Mac OS X系统上开发,就可以直接跳过这个步骤

    (3)如果在Ubuntu Linux上开发,比较麻烦,请尽量不要在Linux上开发android。如必要请参考http://developer.android.com/guide/developing/device.htm

    请注意Android中的adb工具是来验证你设备的,如果成功了你就能看见你的设备了。所以在Eclipse中插入真机会经常出现与adb相关的一些提示。

    如果你使用Eclipse, 可以同时运行模拟器和真机,并且会弹出一个Device Chooser对话框让你选择

    9.3.2编译,执行

    在编译过程中,你的android项目被编译成一个.apk文件,你可以把它想成一个被压缩后的文件。他包含二进制的信息。例如.dex(源码打包后的文件), 二进制的AndroidManifest.xml,还有资源打包文件等。当然我们使用Eclipse这些都会在我们项目的bin目录下自动生成一个.apk文件。其实在模拟器或者真机上运动我们的程序时,是有两种模式的,一种是debug 模式,一种release模式。在我们开发和测试App时,我们通常要签署我们的应用程序指定在debug模式下。当然我们上面说过Eclipse默认已经帮我们做好了,但他是怎么做的呢?那就是使用debug key。当我们需要发布时,我们必须签署我们的APP为release模式并使用private key关于这方面的更多内容我们将在出版章节讲解。下图9-11描述了在编译与运行的应用程序所涉及的流程:

     

    图9-11 编译与运行APP所涉及的流程

    其实图9-11帮我们省略了很多细节,Eclipse已经帮我们做了很多事情。下面我们在看一下生成过程中的详细细节,如图9-12所示:

     

    图9-12 编译与运行APP所涉及的详细流程与工具

    最后我们来看一下一个典型的Android编译打包过程,这些工具都做了些什么事情:

    1.Android Asset Packaging Tool (aapt)需要你应用程序中的资源文件, 如AndroidManifest.xml 文件和其他XML文件,当你编译完它们的后一个 R.java 也产生了,所以你可以从Java代码中引用它们

    2. aidl tool转换任意.aidl文件接口为java接口。(aidl:Android Interface Definition Language,即Android接口描述语言。用来远程过程调用)

    3. 所有的Java代码,包括R.java文件。aidl文件,由Java编译器编译出来为.class文件。

    4. dex tool 转换.class文件到Dalvik 字节码。任何第三方的库和.class文件也会被转换成.dex文件,最终一起打包成.apk文件。

    5. 所有非编译的资源(如图像),编译资源,和dex文件发送到apkbuilder工具处理,然后被打包成一个。apk文件。

    6. 一旦.apk被生成,它必须被签署为debug 或release  key,才能安装到设备上。

    7. 最后, 如果应用程序被签署为release模式,你必须使用zipalign 工具校准.apk文件。当App运行在一个设备上时,校准后的.apk文件会减少内存的使用。

    最后再一次提醒大家,在真机上测试时,请不要忘记打开调试模式,因为有时候依然会由于关机或取电池什么的,系统默认又设置成关闭调试的状态。

    9.4 调试

    Android SDK 提供大部分的工具来调试你的应用程序。例如Eclipise中自带JDWP-compliant (JDWP百科:http://baike.baidu.com/view/4056494.htm)调试器允许你单步调试。一个典型的android调试环境是由以下几个部分组成的:

    1.adb(Android Debug Bridge)

    adb是作为一个设备和开发系统的中间角色。它提供多种设备管理功能,包括移动和同步文件到模拟器,在设备或模拟器上执行一个UNIX shell ,为连接模拟器和设备提供通讯。

    2.Dalvik Debug Monitor Server

    DDMS是一个图形化的程序通过adb来和你的设备通讯。DDMS能截图,收集线程和推栈信息,模拟来电和短信等其他一些功能。

    3.真机或虚拟设备

    你的应用程序必须运行在一个设备或AVD中,这样才能调试它。

    4.JDWP debugger

    Dalvik虚拟机支持运行JDWP协议,以允许调试器附加到虚拟机。每一个应用程序在虚拟机中执行并暴露一个唯一的端口,这个端口可以通过DDMS附加一个调试器。如果你要调试多个应用程序,连接到每个端口可能会冗长,所以DDMS提供了端口转发的功能可以转发一个特定的虚拟机的调试端口到8700。 目前大部分IDE都包含JDWP 调试器,当然Eclipse中也有。

    9.4.1调试环境

    图9-13展示了各种调试工具如何在一个典型的调试环境一起工作。

     

    图9-13 调试工具的相互协作

    9.4.2工具

    接下来我们要认识一些工具,并具体介绍一些工具。Android SDK中包含多种工具帮助我们开发android移动平台的应用程序。这些工具被分为两组:SDK工具和平台工具。SDK工具是独立于平台的,它不依赖于平台。而平台工具则是依赖于平台的,根据平台版本的不同功能上会有新特性。

    1. SDK工具

    (1)android

    让你管理的AVDS,项目和SDK的安装的组件。

    (2)Dalvik Debug Monitor Server (ddms)

    让你调试Android应用程序。

    (3)dmtracedump

    从跟踪日志文件中生成的图形调用堆栈图。这个工具属于调试的范畴

    (4)Draw 9-patch

    创建android专属的 NinePatch 图形,这个工具非常好用,所见即所得。我们后面详细讲解此工具。

    (5)Android模拟器

    你可以用它来设计,调试和测试您的应用程序。

    (6)Hierarchy Viewer

    让你调试和优化Android应用程序的用户界面。属于调试范畴

    (7)hprof-conv

    J2SE中提供了一个简单的命令行工具来对java程序的cpu和heap进行 profiling,这个工具叫做HPROF。而android SDK中的这个工具是用来转换HPROF 文件,生成一个标准的格式让我们浏览。

    (8)layoutopt

    让你快速分析应用程序的布局,以优化效率。属于调试范畴

    (9)mksdcard

    帮助您创建一个磁盘镜像,您可以使用模拟器,模拟外部存储卡(如SD卡)。

    (10)Monkey

    运行你的模拟器或设备,并产生伪随机流的用户事件,比如点击,触摸或手势,以及一些系统级事件。你可以使用Monkey工具来做压力测试。

    (11)monkeyrunner

    提供一个API编写程序,用来控制Android代码以外的Android设备或模拟器。

    (12)ProGuard

    缩小, 优化, 混淆你的代码。

    (13)sqlite3

    允许你通过Android应用程序访问 SQLite 数据文件。

    (14)traceview

    提供一个图形化的查看器,用来查看你执行Logs时保存的内容。

    (15)zipalign

    优化.apk文件。当apk被签名后都会调用此工具用来校准.apk文件。

    2. 平台工具

    平台工具通常是每次你安装一个新的SDK平台后更新。每个平台工具的更新都会兼容旧平台。通常情况下,我们只使用一个工具那就是Android Debug Bridge (adb)。这是一款多用途的工具。我们在之前的文章中已经多次提到过它了。其他平台工具,如aidl,aapt,dexdump和dx通常被称为Android Development Tools (ADT)。我们很少直接使用它们,而是通过Eclipse中的ADT插件自动调用它们。

    下面我们来介绍调试方法和个别工具

    9.4.3使用DDMS

    首先在Eclipse中选择Window > Open Perspective > Other... > DDMS。来打开DDMS界面

    1. DDMS与调试器如何交互

    在Android上,每一个应用程序运行在它自己的进程中,并运行在它自己的虚拟机(VM)。每个虚拟机暴露一个唯一的端口用来连接调试器。当DDMS启动时,它就会连接到adb。当一个设备被连接时,一个虚拟机在设备上启动或停止时它会通知DDMS,在DDMS和adb之间创建一个虚拟机的监控服务。一旦虚拟机运行,DDMS会通过adb检索虚拟机的进程ID(pid),并通过设备上的adb守护进程打开一个连接到虚拟机的调试器。现在DDMS就能和虚拟机对话了。

    DDMS会给每个设备上的VM分配调试端口。通常情况下,DDMS为第一次VM调试分配8600端口,下一次为8601,等等。当一个调试器连接其中的一个端口,所有的通信将被转发到相关的VM调试。一个调试器只能附加一个端口,但DDMS能处理多个调试器。可以理解为一个管理器,但这只是DDMS其中一个功能而已。默认情况下,DDMS也会监听另一个调试端口8700。下面的图9-14显示了在Eclipse中的DDMS的界面。

     

     图9-14 DDMS的截图

    2. DDMS使用方法

    (1)查看一个进程中的堆内存使用

    DDMS的允许你查看一个进程使用了多少堆内存。这个信息可以查询跟踪应用程序在一定时间点的执行过程中堆内存的使用情况。使用步骤如下:

    ◆在 Devices 选项卡,选择一个你想要查看的进程。

    ◆点击Update Heap按钮打开堆信息,按钮位置如图9-15所示:

     

     图9-15 Update Heap按钮的位置

    ◆在右边的 Heap 选项卡, 点击Cause GC 来调用垃圾回收,收集堆数据。当操作完成后,你会看到一组对象类型和为每个类型已分配的内存。读者也可以再次点击 Cause GC 来刷新这个数据。

    ◆点击列表中的一个对象类型,你会看到一个条形图用来显示对象在指定的内存大小分配的数量,单位为字节。

    (2)跟踪对象的内存分配

    DDMS的提供了一个功能来跟踪类和线程分配的对象所占用的内存。允许你实时跟踪在您的应用程序分配的对象,当您执行某些动作时。这个信息可以评估你的程序的性能。使用步骤如下:

    ◆在 Devices 选项卡,选择一个你想要查看的进程 。

    ◆在 Allocation Tracker 选项卡,点击 Start Tracking 按钮来启动跟踪。此刻,你在此应用上做的任何事情将被跟踪 。

    ◆点击Get Allocations 会看到一个对象列表,这个列表是当你点击Start Tracking 后分配的对象。你也可以再次点击Get Allocations 追加新对象到列表中

    ◆要停止跟踪或者清空数据,请点击 Stop Tracking 按钮.

    ◆点击列表中一行,你会看到更多信息,例如这个分配对象的方法和行数。

    (3)查看使用模拟器和真机上的文件系统

    这个功能是非常有用的,我们可以查看,添加,删除某些文件,例如添加一个文件到SD卡中,在模拟器上使用DDMS添加是非常方便的。

    ◆在 Devices 选项卡,选择一个模拟器或真机,然后选择一个文件夹。

    ◆从设备上复制文件出来,请在 File Explorer中点击Pull file。

    ◆吧文件复制到设备中去,点击Push file。

    (4)检查线程信息

    使用步骤如下:

    ◆在 Devices 选项卡, 选择一个你想要查看的进程。

    ◆点击Update Threads 按钮。按钮位置如图9-16所示:

    图9-16 Update Threads按钮的位置

    ◆在 Threads 选项卡, 您可以查看选定进程的线程信息。

    (5)启动方法分析

    方法分析能在某一个角度给我们提供方法测量,例如调用次数,执行时间点,执行方法所花费的时间。你如果想要更精确的控制,分析被收集的数据,使用Debug.startMethodTracing() 和Debug.stopMethodTracing()方法。

    在你开始方法分析之前,请注意以下的限制情况:

    ◆Android 1.5 设备部支持

    ◆Android 2.1 和低于2.1的设备必须当前有SD卡并且你的应用必须有写入SD卡的权限。

    ◆Android 2.2 和高于2.2的设备不需要SD卡。trace log文件会直接用Traceview显示。

    以下是启动方法分析的步骤:

    ◆在 Devices 选项卡, 选择一个你想要查看的进程 。

    ◆点击Start Method Profiling按钮。按钮位置如图9-17所示:

     

    图9-17 Start Method Profiling按钮的位置

    ◆启动方法分析并互动。

    ◆点击Stop Method Profiling按钮。DDMS停止分析并打开Traceview。

    (6)模拟器控制

    在设备选项卡的下面,有一个模拟器控制(Emulator Control)选项卡这个里面有很多关于模拟实际手机的功能,例如模拟一个来电,模拟发送一个短信,切换网络制式等。DDMS为我们更好的开发android应用提供了很方便的功能。

    9.4.4 读取和写入Logs

    Android日志系统提供了一个收集和查看系统调试输出机制。 Logcat这个工具会转储系统消息的日志,其中包括推栈信息,抛出的错误信息,以及你自己定义的Log信息,这些都是实时输出的,就好像原始的System.out.print()。下面让我们看一下Android API中的Log类。

    Log是一个日志类,你可以在代码中利用这个类来输入信息到LogCat中。 它有以下几种输出方法:

    v(String, String) (verbose详细全部的信息)

    d(String, String) (debug调试信息)

    i(String, String) (information信息,通知)

    w(String, String) (warning警告)

    e(String, String) (error错误)

    例如:

    Log.i("MyActivity", "MyClass.getView() — get item number " + position);

    下图9-18是LogCat的截图,它是通过Log类的调用而显示出来的

     

    图9-18 LogCat的截图

    9.4.5 调试和分析用户界面

    有时你应用程序的布局会使你的应用程序变慢。Android SDK提供Hierarchy Viewer和layoutopt这两个工具来帮助调试你的布局问题。

    1.使用Hierarchy Viewer来调试与优化用户界面

    运行Hierarchy Viewer并选择一个窗口,步骤如下:

    ◆连接你的设备或启动一个模拟器。

    为了安全Hierarchy Viewer只能连接到使用开发版本的Android系统上的设备。目前发现真机连不了,如果有知道方法的同学请告知,root和debug模式我已经试过了。

    ◆安装执行你的应用程序,确保它的用户界面是可见的。

    ◆从我们本地电脑中的<sdk>/tools/目录下,直接双击启动hierarchyviewer。这里我发现android1.6的模拟器,启动了并没刷新hierarchyviewer界面,使用2.2就刷新了,如果出现类似问题的朋友请切换其他系统版本试下。请记住在Debug模式下是不能启动此工具的。

    ◆选中列表中的Activity。现在可以看看它的视图层次了。

    下面是一张关于启动Hierarchy Viewer后正确显示的截图,如图9-19所示:

     

    图9-19 Hierarchy Viewer的截图

    当我们点击Load View Hierarchy后会进入另外一个界面,这个界面有4个面板:

    Tree View: 左边的这个面板显示一个Tree View,这是Activity 对象的层次结构图,使用Tree View能检查单个的View对象,并能看到这个对象与周围View的关系。

    底部滑块可以放大的这个面板,或者使用鼠标滚轮放大。并且还能拖动当前View对象生成一张.psd的层次图。

    下面还有一个过滤输入栏,可以输入类名或者ID来过滤你想要查看的View。

    你还可以在左上角点击 Save As PNG 来保存成一张结构图,在团队合作过程中这是非常有用的Save As PNG旁边还有一个Capture Layers我们点击它,其实就和刚才上面拖动当前View一样会弹出一个框,保存为.psd文件格式。这种层次图可以让你编辑,隐藏某些层来安排其他人员工作。

    Tree Overview右上方的一个窗口,用来预览整个树视图,当你在Tree View点击一个View对象时,这里会给那个View矩形上色。

    Properties View右边中间的右侧面板中显示“Properties” View,它会显示选定的视图对象的属性列表,你可以在这里检查这个View的属性

    Layout View右边下方的面板,用来以实际布局的方式来浏览UI。

    当前Activity的UI改变了,这里是不会自动更新的,你需要再次点击 Load View Hierarchy按钮来刷新。下面是View Hierarchy 窗口的截图。如图9-20所示

     

    图9-20 Hierarchy Viewer窗口的截图

    这个工具网络上也有比较多的文章来介绍使用方法,我们这里只需要了解一下就行了,因为在使用此工具的时候还有许多问题,比如不显示指示图标,n/a的情况,不支持真机只支持模拟器的情况。如图9-21所示

     

     图9-21 Hierarchy Viewer窗口出现问题情况的截图

    2.使用layoutopt优化布局

    layoutopt工具让我们分析定义布局的XML文件,并在View Hierarchy找到效率低的地方。用法如下:

     

    它会给你一些英语提示,教你该怎么做,但是请注意,它并不是全能的,在有些地方它依然会出现错误,请不要完全依赖它。

    9.4.6 使用Traceview

    Traceview是一个图形化的浏览工具,当你输出log信息时,它将执行这个log文件并显示出来。Traceview能帮助你调用你的应用程序并分析它的性能。并且我们在讲DDMS使用方法的时候提到过“启动方法分析”,这里就是对他的扩展。

    9.4.6.1 Traceview 布局

    当你有一个trace log文件后 (由自己添加的tracing code 或由DDMS生成),你能使用Traceview载入log文件并吧里面的内容显示到窗口中,这个窗口由两个面板组成:

    ◆timeline panel -- 用于描述每个方法启动和停止时的时间片。

    ◆profile panel -- 提供一个摘要,用于记录一个方法中发生了些什么事情。

    1. Timeline Panel

    下图9-22显示了timeline 面板。每个线程在执行的时候会根据时间的增加来记录一个片段。每一个方法都有一种颜色。并且下面的细线用来显示方法被调用的进度。

     

     图9-22 timeline面板界面

    2. Profile Panel

    下图9-23显示的分析面板,关于在一个方法中的时间片内做了一个总结。该表格显示 inclusive(包含性分析)和 exclusive(独有性分析) 的时间(以及占总时间的百分比)。Exclusive 时间是在这个方法中花费的时间。Inclusive时间是Exclusive时间加上子函数调用此方法所花费的时间。Calls+Rec表示对函数的调用次数(包括递归调用),例如14+0表示调用次数14次,递归0次。

     

    图9-23 profile面板界面

    9.4.6.2 Traceview文件格式

    Tracing 创建了两部分: 一个数据文件,用来防止trace数据, 另一个是一个key文件,用来以二进制标识符来映射线程和方法名。然后当tracing 完成时,这两部分合并成一个.trace文件

    9.4.6.3 创建Trace文件

    要使用Traceview必须生成log文件.有两种方法生成 trace logs:

    ◆使用Debug类调用Debug.startMethodTracing()和Debug.stopMethodTracing()方法。

    ◆使用我们上面讲到的DDMS ,但这种不太精确也不好控制。

    当然在生成 trace logs之前有些限制是我们必须了解的(下面一部分是我们在DDMS中讲过的内容,不知道你是否还有印象呢):

    ◆如果使用Debug 类, 你的设备或模拟器必须有SD 卡并且有写入SD卡的权限。

    ◆如果使用DDMS,Android 1.5不支持。1.6-2.1需要SD卡并且有写入SD卡的权限。2.2和2.2以上可以不需要SD卡直接会显示

    一般来说我是建议大家使用Debug类来分析trace log。因为Debug.startMethodTracing()和Debug.stopMethodTracing()可以很好的控制我们想要查看的地方,并且也不需要关心系统版本的影响。一般在Activiy的onCreate()中使用Debug.startMethodTracing()在onDestroy()或onStop()中使用Debug.stopMethodTracing()。Traceview的使用方法如图9-24所示,我这里已经把SD中的文件拷到电脑中来,并且把tl.trace文件拷贝到了tools目录下,再使用命令行工具调用traceview。

     

    图9-24 Traceview的使用方法

    9.5 图片处理神器draw9patch

    不知道大家是否对.9.png有点印象,好像哪见过,但不太明白是怎么回事?由于android分辨率和设备非常多。关于这一点android定义了一种机制,可以使用一个工具来处理图片的缩放问题,当然美工和设计师可能不会去看android程序开发的文档。作为一名程序员,我们了解这样一种机制后,应该告诉整个团队有这样一种工具能帮我们处理好的图片缩放问题。这样可以大量减少图片放大后出现的问题,对于整个应用产品的提升都是有帮助的。我特别单独写一章用来介绍此工具的使用方法和.9.png原理,是因为它实在是很重要,请大家记住它的重要性并能实际运用到自己的项目中。

    9.5.1 draw9patch和NinePatch

    首先我们要明白draw9patch是什么。以windows系统为例draw9patch是一个工具软件,它是存在于我们的<sdk> ools目录下的一个draw9patch.bat的文件。而NinePatch是android系统中的一种图形,它的文件扩展名为.9.png,对应的类为NinePatchDrawable。这个图形是一个可伸缩的位图图像,Android会自动调整这个图片以适应例如一个按钮的背景或文本框的背景。一个NinePatch drawable是一个标准的PNG图像,并包括一个像素的边框,它必须被保存为.9.png才能被很好的使用。下面我们将使用draw9patch工具来动手创建.9.png的图片并可以在此工具中观察到操作效果。

    1. 首先打开我们的draw9patch,这里我在网上找到了一张图。载入图片后界面如图9-25所示:

     

    图9-25 使用draw9patch工具载入图片后的截图

    2. 放大图片,并把鼠标放到边缘上会出现一个小方块,点一下左键会变黑。如图9-26所示:

     

    图9-26 使用draw9patch工具载入图片后边缘1个像素的截图

    3. 接下来我们要讲解一下,鼠标点击这些小方块有什么用。首先它分为两部分。左边和上方是一组 ,右边和下面是一组。以下是官方的说明图示如图9-27所示:

     

    图9-26 左上一组控制伸缩,右下一组控制边距

    我们看到方用鼠标点击左边和上方会有一个交集,这个区域是允许你放大的区域,意思就是说这个区域外的部分都不会被拉伸,就好像一个面粉团,你一直在中间搓,中间就越来越大,然后往旁边扩散,但变化最大的是中间我们搓的区域。实际上旁边变化很小(这里变化很小就忽略不计等于没变化),这里左边和上方的交集就是我们中间搓的地方,而旁边那些面粉团隆起的小山丘是不会改变的。那右边和下方的交集是什么意思呢?我们继续用面粉团举例,假设你要用面粉团包裹一个大肉馅,这个肉馅的区域你要制指定一下,这样才能保证你的皮有多厚。如果带到程序中,假设这张图的下半部分是用在一个文本框中做背景的,右边和下方的交集就是文本框内容的显示区域。这种功能类似于再代码中加上layout_margin或pandding这种间距的概念,但比加代码更优雅。下面我们来看工具具体是怎么处理(部分内容来源于网络)

    左边和上方处理拉伸区域的对比图:

     

     

     

              

    右边和下方处理内容区域的边距:

     

    我们定义了一个很小的内容区域,其他的地方则自动充当边框,从而使内边距显的很大,实际显示效果如下:

     

    9.6 本章小节

    本章我们介绍了开发之前一些重要的理论为我们进入第二大篇打下了良好的基础,包括管理虚拟设备,项目管理,编译执行,调试,以及重要的draw9patch。我们可以根据自己的实际情况筛选一些知识,也许后期学完了一段时间后在来看这些会有不同的体会。接下来我们可以进入令人兴奋的第二大篇实战篇了!

    本文来自jy02432443,QQ78117253。转载请保留出处,并保留追究法律责任的权利

  • 相关阅读:
    hdfs 复制路径下所有文件
    吐槽scala
    scala
    spark 你要喧宾夺主么?好好干。
    信赖域算法
    scala shuffle
    自动梯度求解 反向传播算法的另外一种视角
    spark 2.0 Vector toBreeze
    自己玩的git
    js判断浏览器
  • 原文地址:https://www.cnblogs.com/tianjian/p/3430156.html
Copyright © 2020-2023  润新知