第3章chapter3 第一个Android程序本章主要介绍开发Android应用程序的基础知识和基本方法。通过本章内容的学习,读者可以掌握使用Android Studio开发Android应用程序的过程和方法,了解Android应用程序的目录结构和自动生成文件的作用。 本章学习目标: 掌握使用Android Studio开发Android应用程序的方法; 了解AndroidManifest.xml文件的用途; 了解Android的程序结构。 3.1Android Studio创建应用程序 本节介绍如何使用Android Studio集成开发环境建立第一个Android程序HelloAndroid。首先启动Android Studio,显示的集成开发环境如图3.1所示。 图3.1集成开发环境运用如下方法可以创建一个新的Android工程。单击Create New Project,跳转到选择模板页面。根据需要创建适用手机或平板电脑的Android工程,同时还提供创建适用于电视、可穿戴设备、车载应用、智能家居的Android工程。为了简化开发工作,选择Empty Activity建立一个空白的Activity即可,如图3.2所示。 图3.2选择页面模板 进入工程配置页面后,需要在Name栏中输入应用程序名称,在Package name栏中输入包名称,在Save location栏中选择项目路径,在Language单选框中选择Java。在Minimum SDK栏中选择能运行的最低版本的SDK,推荐使用API 16,它可以支持目前大部分的设备,如图3.3所示。 图3.3新建工程 包名称(Package Name)是包的命名空间,遵循Java包的命名方法。包名称由两个或多个标识符组成,中间用点隔开,例如edu.hrbeu.HelloAndroid。使用包主要为了避免命名冲突,因此可以使用反写电子邮箱地址的方式保证命名的唯一性。例如,笔者电子邮箱地址是wangxianghui@hrbeu.edu.cn,则可以将包名称命名为cn.edu.hrbeu.wangxianghui。为了保证代码的简洁,第一个Android程序的包名称使用ice.hrbeu.helloandroid。 SDK最低版本(Minimum SDK)是指Android程序能够运行的最低API等级,如果手机中的Android系统的API等级低于程序的SDK最低版本,则程序不能在该Android系统中运行。选择低版本的API可以提高程序的兼容性,但是为了兼容低版本API,在工程中就无法使用新版本API中加入的新功能。为此,一般选择使用API 16,可以在兼容绝大部分手机的情况下,使用一些流行的新功能。 ◆Android应用程序开发(第4版)第◆3章第一个Android程序API等级是Android系统中用来标识API框架版本的一个整数,用来识别Android程序的可运行性。如果Android程序标识的API等级高于Android系统所支持的API等级,程序则无法在该Android系统中运行。API等级与系统版本之间的对照关系可参考表3.1。续表表3.1API等级与系统版本对照表系 统 版 本API等级版 本 代 号支持设备类型Android 11.030R智能手机、 平板电脑、 智能家居Android 10.029Q智能手机、 平板电脑Android 9.028Pie(P)智能手机、 平板电脑Android 8.127Oreo(O)智能手机、 平板电脑Android 8.026Oreo(O)智能手机、 平板电脑Android 7.125Nouget(N)智能手机、 平板电脑Android 7.024Nouget(N)智能手机、 平板电脑Android 6.023Marshmallow(M)智能手机、 平板电脑Android 5.122Lollipop MR1(L)智能手机、 平板电脑Android 5.0.121Lollipop智能手机、 平板电脑Android 4.4W20KitKat Wear可穿戴设备Android 4.419KitKat智能手机、 平板电脑Android 4.318Jelly Bean智能手机、 平板电脑Android 4.217Jelly Bean智能手机、 平板电脑Android 4.116Jelly Bean智能手机、 平板电脑Android 4.0.34.0.415Ice Cream Sandwich智能手机、 平板电脑Android 4.014Ice Cream Sandwich智能手机、 平板电脑Android 3.213HONEYCOMB_MR2平板电脑Android 3.1.x12HONEYCOMB_MR1平板电脑Android 3.0.x11HONEYCOMB平板电脑Android 2.3.4 Android 2.3.310GINGERBREAD_MR1智能手机Android 2.3.2 Android 2.3.1 Android 2.39GINGERBREAD智能手机Android 2.2.x8FROYO智能手机Android 2.1.x7ECLAIR_MR1智能手机Android 2.0.16ECLAIR_0_1智能手机Android 2.05ECLAIR智能手机Android 1.64DONUT智能手机Android 1.53CUPCAKE智能手机Android 1.12BASE_1_1智能手机Android 1.01BASE智能手机最后单击Finish按钮,工程向导会根据用户所填写的Android工程信息,自动在后台创建Android工程所需要的基础文件和目录结构。当创建过程结束,用户可以看到如图3.4所示的内容。 图3.4HelloAndroid工程的文件和目录结构 用户无须在HelloAndroid工程中添加任何代码,即可运行HelloAndroid程序。但为了让Android程序能够正常运行,必须首先建立Android虚拟设备(Android Virtual Device,AVD)。 3.2建立Android虚拟设备 AVD是对Android模拟器进行自定义的配置清单,能够配置Android模拟器的硬件列表、模拟器的外观、支持的Android系统版本、支持的附件SDK库和存储设置等信息。在用户配置好AVD后,Android Studio就可以按照用户的要求启动特定版本和硬件特征的Android模拟器。配置AVD最简单的方式是选择Android Studio的Tools→AVD Manager命令启动AVD管理器,也可以单击工具栏中机器人与手机的图标打开AVD管理器。AVD管理器如图3.5所示。 图3.5AVD管理器 在AVD管理器中单击Create Virtual Device按钮,打开AVD创建界面,如图3.6所示。选择一个分辨率合适的设备,单击Next按钮。选择一个Android SDK版本,单击Download按钮下载该SDK版本,如图3.7所示。 图3.6AVD创建界面 图3.7下载Android SDK版本 在AVD Name输入框中输入AVD名称后,单击Finish按钮保存AVD的配置信息,如图3.8所示。然后在AVD管理器中单击启动按钮启动Android模拟器,如图3.9所示。 图3.8AVD配置界面 图3.9虚拟设备管理界面 图3.10创建运行配置模板向导 启动Android模拟器是一个缓慢的过程,程序调试完毕后,不必关闭Android模拟器,可以节约下次程序调试时启动模拟器的时间。 在运行、调试或测试Android程序代码之前,需要创建运行/调试配置信息。首先选择工具栏中Add Configuration下拉列表①,然后单击Run/Debug Configurations对话框左上方的“+”号按钮②,选择Android App模板创建运行配置,如图3.10所示。在Name输入框中输入配置模板名称,Module下拉栏选择需要运行调试的项目程序,其他选项保持默认设置,最后单击OK按钮保存配置,如图3.11所示。 图3.11运行配置模板创建界面 使用Android Studio运行Android程序非常简单,只要选择Run→Run app命令就可以运行Android程序。Android Studio会自动完成Android程序编译、打包和上传等过程,并将程序的运行结果显示在模拟器中。HelloAndroid程序的运行结果如图3.12所示。 图3.12HelloAndroid的运行结果 至此,已使用Android Studio创建了第一个Android程序,并得到程序的运行结果,对如何建立和运行Android程序已经有了基本的了解。后面的内容仍然以HelloAndroid为例,介绍Android Studio创建的Android的程序目录结构和文件用途。 3.3Android程序结构 在Android Studio中,一个程序项目有3种视图,分为Android视图、Project视图和Packages视图。 Android视图是通过类型来组织项目的资产文件。例如,AndroidManifest文件和XML文件在manifests文件中,所有的Java类都在java文件夹中,所有的资源文件都在res文件夹下,如图3.13所示。 图3.13Android视图 在默认的Android视图结构中,不能反映项目在磁盘上的实际物理组织。如果要查看项目的实际结构,就要切换到Project视图结构,如图3.14所示。 图3.14Project视图 Package视图与Project视图相比,最大的区别就是隐藏了相关的配置文件、属性文件和系统自身的目录,只显示当前的Module列表和Module下面的目录和文件,如图3.15所示。 图3.15Package视图 在建立HelloAndroid程序的过程中,Android Studio会自动建立一些目录和文件,如图3.16所示。这些目录和文件有其固定的作用,有的允许修改,有的则不能进行修改,了解这些文件和目录对Android程序开发有着非常重要的作用。 图3.16HelloAndroid工程的目录和文件 在Project视图下,Android Studio以工程名称HelloAndroid和External Libraries作为根目录,将所有自动生成的和非自动生成的文件都保存在这两个根目录下。Hello Android根目录下包含4个子目录.gradle、.idea、app和gradle,以及7个工程文件.gitignore、build.gradle、gradle.properties、gradlew、gradlew.bat、local.properties和settings.gradle。External Libraries根目录存放项目所依赖的所有类库。 .gradle目录和.idea目录是用来存放Android Studio自动编译工具生成的文件和开发工具产生的文件。 app目录是用来存放程序中的代码资源文件。其中,build目录在编译时生成,主要包含编译时自动生成的内容,在outputs目录下存放打包好的apk文件,libs目录存放第三方jar包,然后jar包会被自动添加到构建路径(如集成地图sdk,把jar包放到libs目录,可以在build.gradle文件中查看当前项目依赖)。 src目录是源代码目录。androidTest目录是用来编写android test测试用例的,可以对项目进行自动化测试;main目录下的java目录是存放Java代码的地方,res是存放资源的目录。Android程序所有的图像、颜色、风格、主题、界面布局和字符串等资源都保存在res目录下的几个子目录中。其中,drawable目录用来保存图像文件,layout目录用来保存与用户界面相关的布局文件,mipmaphdpi、mipmapmdpi、mipmapxhdpi、mipmapxxhdpi和mipmapxxxhdpi目录用来保存同一个程序中针对不同屏幕尺寸需要显示的不同大小的图标文件,引导页的图片也建议放在这里。values目录保存颜色、风格、主题和字符串等资源;AndroidManifest.xml是整个项目的配置文件,四大组件都需要在这里注册才能正常运行;test目录用来编写Unit Test测试用例的目录,是对项目进行自动化测试的另一种方式;.gitignore文件是为git源码管理的配置文件;build.gradle文件是Android项目的Gradle构建脚本文件,用于配置Android构建过程所需要的参数和引用依赖;proguardrules.pro用来指定项目代码的混淆规则,帮助代码打包成混淆过的安装包文件。 gradle目录下包含gradlewrapper的配置文件,使用gradlewrapper的方式不需要提前将gradle下载好,只需要根据本地的缓存情况决定是否需要联网下载gradle。Android Studio默认没有启动gradlewrapper的方式,如果需要打开,可以在Android Studio导航栏选择 File→Settings→Build,Execution,Deployment→Gradle命令进行配置更改。 .gitignore(外层)文件用于将指定的目录或文件排除在版本控制之外,作用和内层的.gitignore文件类似。 build.gradle(外层)文件是项目全局编译环境配置。 gradle.properties是全局的gradle配置文件。这里配置的属性将会影响到项目中所有的gradle编译脚本。 gradlew和gradlew.bat用来在命令行界面执行gradle命令,其中gradlew是在Linux或Mac系统中使用,gradlew.bat是在Windows系统中使用。 local.properties配置文件用来指定本机中Android SDK的路径,一般是自动生成,除非SDK位置发生变化,否则无须修改该文件的路径。 settings.gradle用于指定项目中所有引入的模块。由于项目中只有一个app模块,因此该文件中也就只引入了app这一个模块。通常情况下,模块的引入都是自动完成,需要手动修改这个文件的场景比较少。 AndroidManifest.xml是XML格式的Android程序声明文件,包含了Android系统运行Android程序前所必须掌握的重要信息。这些信息包括应用程序名称、图标、包名称、模块组成、授权和SDK最低版本等,而且每个Android程序必须在根目录下包含一个AndroidManifest.xml文件。XML是一种可扩展标记语言,本身独立于任何编程语言,能够对复杂的数据进行编码,且易于理解。Android工程中多处使用了XML文件,使应用程序开发更加具有弹性,且易于后期的维护和理解。 AndroidManifest.xml文件的代码如下。1<?xml version="1.0" encoding="utf-8"?> 2<manifest xmlns:android="http://schemas.android.com/apk/res/android" 3package="ice.hrbeu.helloandroid" 4android:versionCode="1" 5android:versionName="1.0"> 6<uses-sdk 7android:minSdkVersion="16" 8android:maxSdkVersion="30"/> 9<application 10android:allowBackup="true" 11android:icon="@mipmap/ic_launcher" 12android:label="@string/app_name" 13android:roundIcon="@mipmap/ic_launcher_round" 14android:supportsRtl="true" 15android:theme="@style/Theme.HelloAndroid"> 16<activity 17android:name=".MainActivity" 18android:label="@string/app_name"> 19<intent-filter> 20<action android:name="android.intent.action.MAIN" /> 21<category android:name="android.intent.category.LAUNCHER" /> 22</intent-filter> 23</activity> 24</application> 25</manifest>在AndroidManifest.xml文件中,根元素是manifest,其包含xmlns:android、package、android:versionCode和android:versionName 4个属性。其中,第2行属性xmlns:android定义Android的命名空间,值为http://schemas.android.com/apk/res/android;第3行属性package定义应用程序的包名称;第4行属性android:versionCode定义应用程序的版本号,是一个整数值,数值越大说明版本越新,但仅在程序内部使用,并不提供给应用程序使用者;第5行属性android:versionName定义应用程序的版本名称,是一个字符串,仅限于为用户提供一个版本标识。 manifest元素仅能包含一个application元素,application元素中能够声明Android程序中最重要的4个组成部分,包括Activity、Service、BroadcastReceiver和ContentProvider,所定义的属性将影响所有组成部分。第11行属性android:icon定义Android应用程序的图标,其中@mipmap/ic_launcher是一种资源引用方式,表示资源类型是图像,资源名称为ic_launcher,对应的资源文件为ic_launcher.png,目录是res/mipmaphdpi、res/mipmapmdpi、res/mipmapxhdpi、res/mipmapxxhdpi和res/mipmapxxxhdpi,这5个目录中的资源仍通过@mipmap进行调用;第12行属性android:label则定义了Android应用程序的标签名称。第14行属性android: supportSRtl用作地区适配,RTL即从右向左布局,为了支持阿拉伯语和波斯语,即阅读习惯从右向左的语言,在application标签里添加android: supportSRtl="true",从而改变布局。 activity元素是对Activity子类的声明,不在AndroidManifest.xml文件中声明的Activity将不能够在用户界面中显示。第17行属性android:name定义了实现Activity类的名称,可以是完整的类名称,如ice.hrbeu.helloandroid.MainActivity,也可以是简化后的类名称,如.MainActivity;第18行属性android:label则定义了Activity的标签名称,标签名称将在用户界面的Activity上部显示,@string/app_name同样属于资源引用,表示资源类型是字符串,资源名称为app_name,资源保存在res/values目录下的strings.xml文件中。 intentfilter中声明两个子元素action和category,在这里不详细讨论两个字元素的用途,但可以肯定的是,intentfilter使HelloAndroid程序在启动时,将.MainActivity这个Activity作为默认启动模块。 activity_main.xml文件是界面布局文件,可利用XML描述用户界面,界面布局的相关内容将在第5章中进行详细介绍。activity_main.xml代码的第7行说明在界面中使用TextView控件,TextView控件主要用来显示字符串文本。代码第10行说明TextView控件需要显示的字符串,非常明显,@string/hello_world是对资源的引用。通过strings.xml文件的第5行代码分析,在TextView控件中显示的字符串应是“Hello World, HelloAndroidActivity!”。如果读者修改strings.xml文件的第5行代码的内容,重新编译、运行后,模拟器中显示的结果也应随之更改。 activity_main.xml文件的代码如下。1<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" 2xmlns:tools="http://schemas.android.com/tools" 3android:layout_width="match_parent" 4android:layout_height="match_parent" 5tools:context="ice.hrbeu.helloandroid.MainActivity" > 6 7<TextView 8android:layout_width="wrap_content" 9android:layout_height="wrap_content" 10android:text="@string/hello_world" /> 11 12</RelativeLayout>strings.xml文件的代码如下。1<?xml version="1.0" encoding="utf-8"?> 2<resources> 3 4<string name="app_name">HelloAndroid</string> 5<string name="hello_world">Hello world!</string> 6<string name="action_settings">Settings</string> 7 8</resources>MainActivity.java是Android工程向导根据Activity名称创建的java文件,这个文件完全可以手工修改。为了在Android系统上显示图形界面,需要使用代码继承Activity类,并在onCreate()函数中声明需要显示的内容。 MainActivity.java文件的代码如下。1package ice.hrbeu.helloandroid; 2 3import android.app.Activity; 4import android.os.Bundle; 5import android.view.Menu; 6import android.view.MenuItem; 7 8public class MainActivity extends Activity { 9 10@Override 11protected void onCreate(Bundle savedInstanceState) { 12super.onCreate(savedInstanceState); 13setContentView(R.layout.activity_main); 14} 15 16@Override 17public boolean onCreateOptionsMenu(Menu menu) { 18// Inflate the menu; this adds items to the action bar if it is present. 19getMenuInflater().inflate(R.menu.main, menu); 20return true; 21} 22 23@Override 24public boolean onOptionsItemSelected(MenuItem item) { 25// Handle action bar item clicks here. The action bar will 26// automatically handle clicks on the Home/Up button, so long 27// as you specify a parent activity in AndroidManifest.xml. 28int id = item.getItemId(); 29if (id == R.id.action_settings) { 30return true; 31} 32return super.onOptionsItemSelected(item); 33} 34}第3行和第4行代码通过android.jar从Android SDK中引入了Activity和Bundle两个重要的包,用于子类继承和信息传递;第8行代码声明MainActivity类继承Activity类;第10行代码表明需要重写onCreate()函数;第11行代码的onCreate()会在Activity首次启动时被调用,为了便于理解,可以认为onCreate()是HelloAndroid程序的主入口函数;第12行代码调用父类的onCreate()函数,并将savedInstanceState传递给父类,savedInstanceState是Activity的状态信息;第13行代码声明了需要显示的用户界面,此界面是用XML描述的界面布局,保存在scr/layout/activity_main.xml资源文件中。 到这里分析了Android程序的目录结构和文件的用途,对AndroidManifest.xml文件、Java代码文件、资源引用等内容有了初步的了解。 习题 1. 简述AndroidManefiest.xml文件的用途。 2. 简述res目录下的各种资源类型。 3. 使用Android Studio建立名为MyAndroidStudio的工程,包名称为edu.hrbeu.MyAndroidStudio,程序运行时显示Hello MyAndroidStudio。