Android经典应用程序开发
上QQ阅读APP看本书,新人免费读10天
设备和账号都新为新人

1.3 Android应用程序的结构

1.3.1 Android应用程序的代码组成

Android应用程序包含了工程文件、代码和各种资源,主要由Java语言编写,每一个应用程序将被编译成Android的一个Java应用程序包(*.apk)。

一般情况下,Android应用程序由以下4种组件构成:

活动(Activity);

服务(Service);

广播接收器(BroadcastReceiver);

内容提供者(ContentProvider)。

一个Android应用程序是一个包(Package),包中可能包含一个或者多个Android组件(component)。

提示:Android应用程序包当中也有一个应用程序的概念,称之为application。相比4种组件,这个概念在Android中对程序的运行时影响不大。

Android应用程序一般包含在一个单一的文件夹中,即每一个Android应用程序是一个独立的工程,包含了以下文件。

Android.mk:工程编译文件,作用类似于Makefile,在SDK开发中不需要;

AndroidManifest.xml:工程描述文件,在其中定义了各种组件;

src目录:Java源代码,按照Java包的方式来组织目录结构,包括各个Java类的源代码;

res目录:资源文件,包含XML文件、图片、原始数据文件等,其中表示界面的布局(Layout)文件比较重要;

assets目录:资产文件,将原样复制到目标的应用程序包当中。

1.3.2 Android应用示例

SkeletonApp是Android中一个应用程序的骨架,这个程序包含了两个按钮和菜单,两个按钮分别用于清除编辑文本框中的内容,菜单的功能和两个按钮是相同的,菜单是Android中的标准UI元素。SkeletonApp程序的运行结果如图1-35所示。

图1-35 SkeletonApp程序的运行结果(左:启动界面;右:使用菜单)

1.源代码工程结构

SkeletonApp工程的源文件的结构(没有包含相对独立的用于测试的代码)按照目录树的方式如下所示:

        SkeletonApp/
        |-- Android.mk                         工程管理文件
        |-- AndroidManifest.xml                工程描述文件
        |-- res                                [资源文件目录]
        |   |-- drawable
        |   |   `-- violet.jpg                     图片文件
        |   |-- layout
        |   |   `-- skeleton_activity.xml            [布局文件目录]
        |   `-- values
        |      |-- colors.xml                    颜色资源文件
        |      |-- strings.xml                    字符串资源文件
        |      `-- styles.xml                    样式资源文件
        |-- src                                [Java源代码目录]
          `-- com
              `-- example
                  `-- android
                      `-- skeletonapp
                          `-- SkeletonActivity.java

Java源代码SkeletonActivity.java中构建了菜单、按钮的动作等功能,其中最核心部分如下所示:

        package com.example.android.skeletonapp;            // 定义应用程序的包名
        public class SkeletonActivity extends Activity {
              // ......省略部分内容
            @Override
            public void onCreate(Bundle savedInstanceState) {
              super.onCreate(savedInstanceState);
              setContentView(R.layout.skeleton_activity);  // 设置其中的布局文件
              // ......省略部分内容
            }
        }

在SkeletonApp中,资源目录res中的values目录中除了strings.xml文件,还包含了colors.xml和styles.xml文件,这两种文件也是Android中的标准资源文件。

colors.xml文件的内容如下所示:

        <?xml version="1.0" encoding="utf-8"?>
        <resources>
            <!— 可以通过Resources.getColor()得到。-->
            <color name="red">#f00</color>
            <!--可以通过Resources.getDrawable()得到 -->
            <drawable name="semi_black">#80000000</drawable>
        </resources>

styles.xml文件用于定义程序中的不同样式,其中的内容如下所示:

        <?xml version="1.0" encoding="utf-8"?>
        <resources>
            <style name="ActionButton">
              <item name="android:layout_width">wrap_content</item>
              <item name="android:layout_height">wrap_content</item>
              <item name="android:textAppearance">
                              @style/TextAppearance.ActionButton</item>
            </style>
            <style name="TextAppearance" parent="android:TextAppearance">
            </style>
            <style name="TextAppearance.ActionButton">
              <item name="android:textStyle">italic</item>
            </style>
        </resources>

资源目录res还包含了drawable目录,表示可以绘制的内容,这里的violet.jpg是一个JPEG格式的文件。

在res/layout目录中的布局文件skeleton_activity.xml中的部分内容引用了以上资源,内容如下所示:

        <LinearLayout android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_gravity="center_vertical"
            android:gravity="center_horizontal"  android:orientation="horizontal"
            android:background="@drawable/semi_black">
            <Button android:id="@+id/back"   style="@style/ActionButton"
                    android:text="@string/back" />
            <ImageView android:id="@+id/image"
                      android:layout_width="wrap_content"
                      android:layout_height="wrap_content"
                      android:paddingLeft="4dip"   android_paddingRight="4dip"
                      android:src="@drawable/violet" />
            <Button android:id="@+id/clear" style="@style/ActionButton"
                    android:text="@string/clear" android:textColor="@color/red" />
        </LinearLayout>

布局文件中引用了上面的资源,颜色可以作为字体的颜色,style/ActionButton作为按钮的样式,drawable/semi_black表示了背景的内容,drawable/violet表示引用violet.jpg图片作为图像的内容。例如根据上面styles.xml文件中的定义,两个按钮上的字体为斜体,第二个按钮的字体颜色为红色。

2.SDK环境中的编译结构

以上的SkeletonApp应用程序包在SDK环境中经过编译之后将生成一些额外的文件。除去源代码中已经具有的文件以下,自动生成的内容的目录结构如下所示:

        SkeletonApp
        |-- bin                                     [目标文件目录]
        |   |-- classes.dex
        |   |-- com                                 [根据目录生成字节码]
        |   |   `-- example
        |   |      `-- android
        |   |          `-- skeletonapp
        |   |             |-- R$attr.class          [R*.class为资源对应字节码]
        |   |             |-- R.class
        |   |             |-- R$color.class
        |   |             |-- R$drawable.class
        |   |             |-- R$id.class
        |   |             |-- R$layout.class
        |   |             |-- R$string.class
        |   |             |-- R$style.class
        |   |             |-- SkeletonActivity$1.class    [主要Java源文件的字节码]
        |   |             |-- SkeletonActivity$2.class
        |   |             `-- SkeletonActivity.class
        |   |-- resources.ap_
        |   `-- SkeletonApp.apk
        |-- default.properties                           [属性文件]
        |-- gen                                           [自动生成Java文件的目录]
            `-- com
              `-- example
                  `-- android
                      `-- skeletonapp
                          `-- R.java

在SDK环境中,自动生成的文件包括以下几项内容。

default.properties:工程的设置信息;

gen目录:包含资源文件和AIDL文件生成的源代码文件,其中资源文件生成的源代码文件为R.java;

bin目录:为根据类名生成的各个Java标准字节码文件(*.class),classes.dex文件为经过转化的运行于Android系统的特定字节码。XXX.apk为最终生成的APK包,不同工程根据名字所生成的包名不同,例如SkeletonApp.apk。

3.APK包的结构

Android中程序的编译结构基本类似,SkeletonApp工程生成的应用程序包SkeletonApp.apk,本质上是一个无压缩率的ZIP包。经过解压缩后,可以看到其中包含了下面的一些内容:

        SkeletonApp.apk/
        |-- AndroidManifest.xml              经过aapt处理的工程描述文件
        |-- META-INF
        |   |-- CERT.RSA
        |   |-- CERT.SF
        |   `-- MANIFEST.MF
        |-- classes.dex                      Dalvik的字节码文件
        |-- res
        |   |-- drawable
        |   |   `-- violet.jpg               保持原状的图片文件
        |   `-- layout
        |       `-- skeleton_activity.xml    经过aapt处理的布局文件
        `-- resources.arsc

在这里drawable中的图片文件保持原状,layout中的布局文件经过aapt处理成为压缩的文本文件。

1.3.3 应用程序生成运行过程

1.应用程序包生成的过程

在编译Android应用程序的过程中,Java源代码使用Sun JDK将Java源程序编译成Java字节码文件(多个后缀名为.class的文件),这一步骤和标准的Java一致,然后通过Android自带的工具软件dex把所有的字节码文件转成DEX文件(单一文件classes.dex)。

AndroidManifest.xml文件经过Android打包工具(aapt)处理后形成二进制格式AndroidManifest.xml文件,实质的内容与以前相同。

各个资源文件也经过aapt处理,其中布局等文本文件处理成二进制文件,图片等文件保持不变。

最后将这三个部分组合成一个应用程序包(*.apk)。AndroidManifest.xml描述文件、Java源文件、资源文件是Android应用程序的三个部分;在编译之前的工程中是这三个部分,在编译之后APK包依然是由这三个部分组成的。

Android应用程序的编译过程如图1-36所示。

图1-36 Android应用程序的编译过程

如图1-36所示,Android源文件经过了标准的Java编译器的编译,又经过了dx工具的处理,标准的Java字节码作为整个Android编译的中间过程,最终生成的DEX文件(classes.dex)是一个单一文件,将工程中所有的Java源代码文件对应的字节码集成在一起。资源文件和AndroidManifest.xml文件通过aapt工具进行处理。

除此之外,assets目录及所有内容,将会原样保存,放入到目标APK包中,作为预编译的内容存在。在程序中,可以直接访问其中的文件。

2.应用程序包安装运行的过程

在运行时,APK包将首先进行“安装”,也就是将其中的DEX文件进行优化,优化后的文件被保存到缓存区域,生成格式为DEY的优化文件,然后Dalvik虚拟机将运行这些DEY文件。如果应用程序包文件不发生变化,DEY文件不会被重新生成;在应用程序包发生更新的情况下,将重新由DEX生成DEY。

Android和标准Java的JAR包中字节码的不同之处在于,标准Java每个源文件对应字节码文件一个Class文件,而Android将所有Java字节码生成一个DEX文件。