
1.5 Android应用程序架构
现在,读者应该已经学会如何新建一个Android项目以及开发Android项目的流程了,即在XML文件中定义用户界面,然后打开Java源代码编写业务实现。但是,读者也许现在对上面的Java源文件的代码还不是很理解,例如“findViewById(R.id.showTextView);”代码中的R.id.showTextView参数是从何而来等等,对Android应用程序的项目结构也存在疑惑。
实际上,这些问题的答案并不太难,接下来对如图1.22所示的Android项目应用结构做一个简单介绍。
src目录只是一个普通的、存放Java源文件的目录,这里不做详细介绍,下面介绍的是除src以外的其他目录结构。
1.5.1 自动生成的gen目录
gen目录中存放所有由Android开发工具自动生成的文件。该目录中最重要的就是R.java文件。这个文件是由Android开发工具AAPT工具根据应用中的资源文件自动产生的。Android开发工具会自动根据你放入res目录的XML界面文件、图标与常量,同步更新修改R.java文件。正因为R.java文件是由开发工具自动生成的,所以应避免手工修改R.java。R.java在应用中起到了资源字典的作用,它包含了界面、图标、常量等各种资源的id,通过R.java,应用可以很方便地找到对应资源。另外编译器也会检查R.java列表中的资源是否被使用到,没有被使用到的资源不会编译进软件中,这样可以减少应用在手机中占用的空间。打开gen/cn/edu/hstc/firstapp目录下的R.java文件,可以看到如下代码。

从上面的源代码文件可以看到:
在R类中,针对各种资源生成了对应的内部类。例如界面布局资源对应layout内部类;字符串资源对应string内部类;标识符资源对应id内部类。
每个内部类中以一个public static final int类型的Field来对应每个具体的资源项。例如前面在activity_main.xml文件中设置了Button控件的id属性为confirmButton以及设置了EditText控件的id属性为showEditText,因此R.id类中就定义了这两个Field;由于我们有一个名为activity_main.xml的布局文件,所以在R.layout类中就有了activity_main的Field。
1.5.2 资源目录res
Android应用的res目录中存放了包括XML界面文件、图片资源、字符串资源、颜色资源、尺寸资源等在内的Android应用所用的全部资源。
通过展开Android项目的结构目录中的res目录,可以看到layout、values、drawable等资源文件夹,这些文件夹对不同的资源进行了分类,这样可以方便地让AAPT工具来扫描这些资源,并在R.java文件中为它们生成对应的内部类。下面对各个资源文件夹做一个简单的介绍。
res/drawable:专门存放png、jpg等图片文件。在Java代码中使用getResources().getDrawable(resourceId)获取该目录下的资源。
res/layout:专门存放XML界面文件,XML界面文件和HTML文件一样,主要用于显示用户操作界面。
res/values:专门存放应用使用到的各种类型数据。不同类型的数据存放在不同的文件中,如下:
① strings.xml——定义字符串和数组,在Activity类中使用getResources().getString (resourceId)或getResources().getText(resourceId)来取得字符串资源。它的作用和struts中的国际化资源文件一样。一份strings.xml文件的内容如下:

在Java代码中使用getResources().getString(R.string.app_name)或getResources().getText(R.string.app_name)来获取key为app_name的值。
在XML中使用@string/app_name来获取key为app_name的值。
② arrays.xml:定义数组。一份arrays.xml文件的内容如下:

③ colors.xml:定义颜色和颜色字串数值,可以在Activity中使用getResources().getDrawable(resourceId)以及getResources().getColor(resourceId)取得这些资源。一份colors.xml文件的内容如下:

④ dimens.xml:定义尺寸数据,在Activity中使用getResources().getDimension (resourceId)取得这些资源。一份dimens.xml文件的内容如下:

⑤ style.xml:定义样式。一份styles.xml文件的内容如下:

res/anim:存放定义动画的XML文件。
res/xml:在Activity中使用getResources().getXML()读取该目录下的XML资源文件。
res/raw:该目录用于存放应用使用到的原始文件,如音效文件等。编译软件时,这些数据不会被编译,它们被直接加入到程序安装包里。为了在程序中使用这些资源,可以调用getResources().openRawResource(resourcesId)来获取资源。
Android除了提供res目录存放资源文件外,assets目录也可以存放资源文件,而且assets目录下的资源文件不会在R.java中自动生成ID,所以读取assets目录下的文件必须指定文件的路径,如:file:///android_asset/xxx.3gp。
1.5.3 项目清单文件:AndroidManifest.xml
AndroidManifest.xml清单文件是每个Android项目都必需的,它是整个Android应用的全局描述文件。这个文件列出了应用程序所提供的功能,以后开发好的各种组件需要在该文件中进行配置,如果应用使用到了系统内置的应用(如电话服务、互联网服务、短信服务、GPS服务等等),还需在该文件中声明使用权限。
AndroidManifest.xml清单文件说明了该应用的名称、所使用图标以及包含的组件等,一份AndroidManifest.xml文件的内容如下:

由以上文件内容可以看出,AndroidManifest.xml清单文件通常包含如下信息:
应用程序的包名,该包名将会作为该应用的唯一标识。
应用程序所包含的组件,如Activity、Service、BroadcastReceiver和ContentProvider等。
应用程序兼容的最低版本。
应用程序使用系统所需的权限声明。
其他程序访问该程序所需的权限声明。
随着不断地进行开发,可能需要对AndroidManifest.xml清单文件进行适当的修改。
1.5.4 声明应用程序使用权限
上面提到,如果应用使用到了系统内置的应用(如电话服务、互联网服务、短信服务、GPS服务等),还需在该文件中声明使用权限;一个应用也可能被其他应用调用,因此也需要声明调用自身所需要的权限。
1.声明该应用自身所拥有的权限
通过为<manifest…/>元素添加<uses-perrnission…/>子元素即可为自身声明权限。
例如,在<manifest…/>元素中添加如下代码:
<!--声明该应用本身即有打电话的权限-->
<uses-permission android:name="android.permission.CALL_PH0Ne"/>
2.声明调用该应用自身所需的权限
通过为应用的各组件元素,如<activity…/>元素添加<uses-permission…/>子元素即可声明调用该程序所需的权限。
例如,在<activity…/>元素中添加如下代码:
<!--声明该应用本身即有打电话的权限-->
<uses-permission android:name="android.permission.SEND_SM S"/>
下面给出一些Android系统常用权限,这些权限都可以通过Android官方文档查看到。
开机自动允许——android.permission.RECEIVE_BOOT_COMPLETED,允许程序开机自动运行。
电量统计——android.permission.BATTERY_STATS,获取电池电量统计信息。
使用蓝牙——android.permission.BLUETOOTH,允许程序连接配对过的蓝牙设备。
蓝牙管理——android.permission.BLUETOOTH_ADMIN,允许程序发现和配对新的蓝牙设备。
收到短信时广播——android.permission.BROADCAST_SMS,当收到短信时触发一个广播。
拨打电话——android.permission.CALL_PHONE,允许程序从非系统拨号器里输入电话号码。
拍照权限——android.permission.CAMERA,允许访问摄像头进行拍照。
安装应用程序——android.permission.INSTALL_PACKAGES,允许程序安装应用。
修改声音设置——android.permission.MODIFY_AUDIO_SETTINGS,修改声音设置信息。
修改电话状态——android.permission.MODIFY_PHONE_STATE,修改电话状态,如飞行模式,但不包含替换系统拨号器界面。
读取日程提醒——android.permission.READ_CALENDAR,允许程序读取用户的日程信息。
读取联系人——android.permission.READ_CONTACTS,允许应用访问联系人通讯录信息。
屏幕截图——android.permission.READ_FRAME_BUFFER,读取帧缓存用于屏幕截图。
读取短信内容——android.permission.READ_SMS,读取短信内容。
接收彩信——android.permission.RECEIVE_MMS,接收彩信。
接收短信——android.permission.RECEIVE_SMS,接收短信。
录音——android.permission.RECORD_AUDIO,录制声音通过手机或耳机的麦克。
发送短信——android.permission.SEND_SMS,发送短信。
设置闹铃提醒——com.android.alarm.permission.SET_ALARM,设置闹铃提醒。
设置系统时间——android.permission.SET_TIME,设置系统时间。
使用振动——android.permission.VIBRATE,允许振动。
写入联系人——android.permission.WRITE_CONTACTS,写入联系人,但不可读取。
写入外部存储——android.permission.WRITE_EXTERNAL_STORAGE,允许程序写入外部存储即SD卡上写文件。
编写短信——android.permission.WRITE_SMS,允许编写短信。
访问网络——android.permission.INTERNET,允许访问网络。
修改文件系统——android.permission.MOUNT_UNMOUNT_FILESYSTEMS,允许创建修改或删除文件。