第一章 初识Android开发

开发Android应用程序
1.Android项目结构分析

-
.gradle和.idea
这两个目录无须关心,这是Android Studio自动生成的文件,开发者不要手动更改这些文件。 -
.app
项目中的代码和资源等内容几乎都是放在这个目录下的,在实际编写代码时也都是在这个目录下进行的,随后将会单独对这个目录进行详细讲解。 -
build
此目录也不必关心,里面主要放置一些编译时生成的文件,开发者也不要手动去更改该目录下的文件。 -
.gradle
这个目录下包含了gradle wrapper的配置文件,使用gradle wrapper的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。若需要打开,可以通过Android Studio导航栏->File->Settings,如下图所示。

-
.gitignore
此文件用来指定的目录和文件排除在版本控制之外,关于版本控制会在之后的目录中介绍。 -
build.gradle
这是项目全局的gradle构建脚本,一般此文件中的内容是不需要修改的。稍后详细分析gradle脚本中的内容。 -
gradle.rpoperties
这个文件是全局的gradle配置文件,在这里配置的属性将会影响到全局的项目中所有的gradle编译脚本。 -
.gradlew和gradlew.bat
这两个文件是用来在命令行界面中执行gradle命令的,其中gradlew是在Linux或Mac系统中使用的,gradlew.bat是在Windows系统中使用的。 -
MyFirstAPP.iml
.iml文件是所有IntelliJ IDEA项目中都会自动生成的一个文件(Android Studio是基于IntelliJ IDEA开发的),开发者也不用修改这个文件职工的任何内容。 -
local.properties
这个文件用于指定本机中的Android SDK路径,通常内容都是自动生成的,并不需要修改。除非用户计算机上的SDK位置发生变化,这是将这个文件中的路径改成新的路径即可。 -
.settings.gradle
这个文件用于指定项目中所引用的模块。由于MyFirstApp项目中只有一个app模块,因此该文件就引入了app这一模块。通常情况下模块的引入都是自动完成的,需要手动修改这个文件的场景较少,但是要知道这个文件的作用,避免以后开发中遇到此种情况。
至此,整个项目的外层目录介绍完毕。除了app目录之外,绝大多数的文件和目录都是自动生成的,开发者并不需要修改。而app目录才是之后开发的重点目录,将它展开如下图所示。

下面对app目录进行详细分析
-
build
这个目录和外层build目录类似,都包含一些编译时自动生成的文件,不过它里面的内容更加复杂一些,不需要关心它。 -
libs
如果项目中使用了第三方jar包,就需要把第三方jar包放在libs目录下,放在这个目录下的jar包都会被自动添加到构建路径中去。 -
androidTest
此处用来编写Android Test测试用例,可以对项目进行一些自动化测试。 -
java
毫无疑问.java目录是用来放置java代码的地方,展开该目录,可以看到之前自动创建的MainActivity文件。 -
res
res中包含多个目录,如drawable,layout,values和mipmap等,分别用于存放项目工程中使用的图片、布局文件、字符串文件和存放自动缩放图片的目录。其中values目录中包含很多XML描述我呢间,包括字符串定义、颜色定义、样式定义和长度定义等。 -
AndroidMainifest.xml
这是整个Android项目的配置文件,项目中使用到的四大组件都需要在这目录下进行注册。另外,还可以在这个文件中给项目应用添加权限声明。这个文件会经常用到,稍后的内容中会详细讲解。 -
test
此处是用来编写Unit Test测试用例的,是对项目进行自动化测试的另一种方式。 -
gitignore
与外层的.gitignore文件作用相似,是将app模块中的指定文件或目录排除在版本控制之外。 -
app.iml
IntelliJ IDEA 项目自动生成的文件,开发者不需要修改此文件内容。 -
proguard-rules.pro
这个文件用于指定项目代码的混淆规则,当代码开发完成后打成安装包文件。如果不希望代码被别人破解,通常会将代码进行混淆,从而让破解者难以阅读。
2.程序文件分析
1.Android程序的组成结构
package com.example.myapplication;//包声明语句
//导入包
import androidx.appcompat.app.AppCompatActivity;
import android.os.Bundle;
//定义MainActivity类继承AppCompatActivity
public class MainActivity extends AppCompatActivity{
@Override//重写onCreate方法
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);//调用父类的onCreate方法
setContentView(R.layout.activity_main);//显示布局文件的内容
}
}
MainActivity继承自AppCompatActivity,这是一种向下兼容的Activity,可以将Activity在各个版本增加的特性和功能最低兼容到系统Android2.1。而读者必须知道,开发中所有自定义的Activity都必须继承自Activity或者Activity的子类才能拥有Activity的特性,此代码中AppCompatActivity是Activity的子类。往下看可以看到有一个onCreate方法,这个方法是Activity创建时必须执行的方法,而在此方法中并没有看到Hello World字样,那么在模拟器中看到的Hello World来自哪里呢?
其实Android程序的设计讲究逻辑层与视图层分离,在Activity中一般不直接编写界面,而是在布局文件layout中编写,那在Activity中怎么与layout相联系呢?通过setConnectView()方法。在上面代码中可以看到,setConnectView引入一个叫作activity_main的layout文件,那么可以猜测,Hello World字样一定来自这个布局文件。按住Ctrl+鼠标左键可以直接打开该布局文件。AndroidStudio有许多快捷键供开发者使用,在后续的开发练习中可以多多练习使用快捷键,这样可以大大提高开发效率。
2.项目配置文件AndroidMainfest.xml
AndroidMainifest.xml清单文件是每个应用程序都需要的系统配置文件,它是整个Android应用的全局描述文件。清单文件详细说明了应用的图标,名称以及包含的各种组件等,它位于应用程序根目录下。
AndroidMainfest.xml文件代码如下:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.MyApplication"
tools:targetApi="31">
//应用程序的Activity
<activity
android:name=".MainActivity"
android:exported="true">
//指定该Activity为程序的入口
<intent-filter>
<action android:name="android.intent.action.MAIN" />
//指定启动应用时运行该Activity
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
AndroidMainifest.xml文件代码说明如下表所示。

3.资源的管理与引用
在Android程序中我们经常把图片、文字、样式、布局颜色等信息放在外部的资源文件中,这些文件也是程序的一部分,会被编译到APP中。在Android程序中,资源文件一般存放在res目录下,例如我们前面在程序中使用的布局文件。下面我们将对res目录下的资源进行介绍。
1.字符串资源文件
在界面中出现的文字都可以使用字符串资源存储到文件中,例如程序需要的文本提示信息,控件上显示的文本或标题等。为了开发过程中更加方便快捷地使用字符串,Android系统提供了强大的字符串资源,我们可以在res/values目录下的string.xml文件中定义字符串。定义字符串的代码如下:
<resources>
<string name="app_name">APP名字<string>
</resources>
/*上述代码中,<string></string>标签定义的就是字符串资源,其中name属性指定字符串的资源名称,两个标签中间的就是字符串中的内容。需要注意的是,string,xml文件中只能有一个根元素,但是根元素中间可以包含多个<string></string>标签。
*/
在程序中调用字符串资源的方式有两种,一种是通过Java代码来调用该字符串资源,另一种是在XML布局文件中引用字符串资源。具体使用方式如下:
1.通过Java代码调用字符串资源
在Activity的onCreate()方法
getResources().getString(R.string.app_name);
2.在XML布局文件中引用字符串资源
在XML布局文件中通过@string引用字符串资源,例如在XML布局文件中调用名为app_name的字符串资源,代码如下:
@string/app_name
2.颜色资源
在Android程序中,可以在res/values/文件夹的color.xml文件中定义颜色。
在XML中定义颜色值时,颜色使用RGB值和Alpha通道指定。我们可以在接受十六进制颜色值的任何地方使用颜色资源,例如保存在/res/values/colors.xml的XML文件中的代码如下:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="opaque_red">#f00</color>
<color name="translucent_red">#80ff0000</color>
</resources>
当XML中需要可绘制资源时,也可以使用颜色资源(例如,android:drawable=“@color/opaque_red”)。资源的引用有2种方式:
(1)在Java中,R.color.color_name:
Resources res=getResources();
int color=res.getColor(R.color.opaque_red);
(2)在XML中,@[package:]color/color_name:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_parent"
android:textColor="@color/translucent_red"
android:text="Hello"/>
3.可绘制对象资源
可绘制对象资源是图形的一般概念,是指可在屏幕上绘制的图形,以及可使用getDrawable(int)等API检索,或应用到拥有android:drawable和android:icon等属性的其他XML资源的图形。可绘制对象包含以下多种类型,如位图文件,九宫格文件,图层列表等。这里我们主要以位图文件为例。
Android 支持三种格式的位图文件:.png(首选)、.jpg(可接受)、.gif(不建议)。使用时将任一位图文件保存到res/drawable目录中时,Android都会为其创建Drawable资源。使用时将应用图标资源存放在mipmap文件夹中,界面中使用的图片资源存放在drawable文件夹中。
根据屏幕密度的不同,Android系统自动匹配对应文件夹中的资源。res中mipmap和drawable文件夹中的屏幕密度匹配规则如表1.2所示。
程序中使用文件名作为资源ID直接引用位图文件,也可以在XML中创建别名作为资源ID。
当图像保存为res/drawable/myimage.png后,在布局XML文件中使用如下代码会将该图像应用至视图:
<ImageView
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:src="@drawable/myimage"/>
在Java应用程序中,使用如下代码获取图像资源:
Resources res=getResources();
Drawable drawable=ResourcesCompat.getDrawable(res,R.drawable.myimage,null);
4.样式与主题资源
Android中的样式和主题,都用于为界面元素定义显示风格,他们的定义方式比较类似,下面分别介绍。
1.样式资源
样式是指为View或窗口指定外观和格式的属性集合。样式可以指定高度,填充,字体,颜色,字号,背景色等许多属性。样式是在与指定布局的XML不同的XML资源中进行定义的。Android中的样式和CSS样式作用相似,都用于为界面元素定义显示风格,它是一个包含一个或者多个View控件属性的集合。样式只能作用于单个View,如EditText、TextView,使用样式可以将多个控件具有的重复属性统一抽取出来进行编写,避免书写大量重复代码,例如可以将如下代码进行重构:
<TextView
android:layout_width="fill_parent"
android:layout_height="wrap_parent"
android:textColor="#00FF00"
android:text="@string/hello"/>
将布局XML中所有与样式有关的属性都移除,并置于一个名叫CodeFont的样式的样式定义内,然后通过style属性加以应用。重构后的结构如下:
<TextView
style="@style/CodeFont"
android:text="@string/hello"/>
下面我们详细说明如何定义样式资源。
(1)定义样式资源
在项目的res/values目录中创建一个设置样式XML文件。默认有一个styles.xml样式资源文件保存在res/values/文件夹内。
1)定义样式资源
在项目的res/values目录中创建一个设置样式XML文件。默认有一个styles.xml样式资源文件保存在res/values/文件夹内。
该XML文件的根节点必须是<resources>。我们创建的每个样式都向该文件添加一个<style>元素,该元素带有对样式进行唯一标识的name属性(该属性为必需属性)。然后为该样式的每个属性添加一个<item>元素,该元素带有声明样式属性以及属性值的name(该属性为必需属性)。根据样式属性,<item>的值可以是关键字字符串、十六进制颜色值,对另一资源类型的引用或其他值。以下是一个包含单个样式的示例文件:
<?xml version="1.0" encoding="utf-8"?>
<resources>
<style name="CodeFont"parent="@android:style/TextAppearance.Medium">
<item name="android:layout_width">fill_parent</item>
<item name="android:layout_height">wrap_parent</item>
<item name="android:textColor">#00FF00</item>
<item name="android:typeface">monospace</item>
</style
>
</resources>
在上述代码中<resources>元素的每个子项都会在编译时转换成一个应用资源对象,该对象可由<style>元素的name属性中的值引用。可从XML布局以@style/CodeFont形式引用该示例样式(如上文所示)。<style>元素中的parent属性是可选属性,它指定应作为此样式所继承属性来源的另一样式的资源ID。
2)使用样式
在布局文件的View控件中使用style属性调用定义的样式,如下面代码:
<TextView
style=“@style/CodeFont”
android:text="@string/hello"/>
2.主题资源
主题也是包含一个或者多个View控件属性的集合,但它的作用范围不同。主题通过AndroidMainifest.xml中的<application>和<activity>节点用在整个应用或者某个Activity,它的影响是全局性的。如果一个应用中使用了主题,同时应用下的View也使用了样式,那么当主题和样式中的属性发生冲突时,样式的优先级高于主题。
在Android系统中,自带的样式和主题都可以直接拿来用,例如设置主题可以通过android:theme=“android:style/...”在弹出的对话框中选择。
1)定义主题
程序要使用定制主题,必须先定义主题,在res/values目录下的styles.xml文件中定义主题样式,如下:
<style name="AppTheme"parent="Theme.AppCompat.Light.DarkActionBar">
<!--Customize your theme here.-->
<item name="colorPrimary">@color/colorPrimary</item>
<item name="colorPrimaryDark">@color/colorPrimaryDark</item>
<item name="colorAccent">@color/colorAccent</item>
上述代码中,<style></style>标签用于定义主题,<style>标签中的name属性用于指定主题的名称,parent属性永固指定Android系统提供的父主题。<style></style>中包含的<item></item>标签用于设置主题的样式。
2)使用主题
在Android程序中调用styles.xml文件中的主题,可以在AndroidMainifest.xml
中引用,如:
<application
...
android:theme="@style/AppTheme">
</application>
通过Java代码引用,代码如下
setTheme(R.style.AppTheme)
5.布局资源
通过前面的学习可以看到,在程序的res目录下有一个layout文件夹,该文件夹中存放的是程序中的所有布局资源文件,这些布局资源通常用于搭建App中的各个界面。
当创建一个Activity时,可以选择同时创建它的布局文件,这时会在res/layout文件夹中生成一个XML布局文件,也可以单独在res/layout文件夹中创建新的布局资源文件。
布局资源文件创建好后,可以通过Java程序使用,或者在另外一个布局文件中引用,具体如下:
1.通过Java代码调用布局资源文件
在Activity中,找打onCreate()方法,在该方法中通过调用setContentView()方法来加载Activity对应的布局资源文件,代码如下:
setContentView(R.layout.activity_main);
2.在XML布局文件中引用其他布局文件
在XML布局文件中可以通过<include>标签引入其他的布局资源文件,例如在XML布局文件中调用activity_login.xml文件,代码如下:
<include layout="@layout/activity_logo">
6.应用程序主题制作
随着移动互联网的快速发展,已经有越来越多互联网企业在Android平台上部署客户端,为了提升用户体验,客户端布局非常合理而且美观。Android应用程序开发中涉及的样式设计是提升用户体验的关键之一。
Android中的样式分为两个方面:
(1)主题(Theme)是针对窗体级别的,改变窗体的样式。
(2)样式(Style)是针对窗体元素级别的,改变指定控件或者布局的样式。
主题和样式的区别主要体现在如下两个方面:
(1)主题不能作用于单个的View控件,主题对整个应用中所有的Activity起作用,或者对指定的Activity起作用。
(2)主题定义的格式只能改变窗口的外观。
主题是用来设置界面UI风格的,因此可以通过主题来设置整个应用或者某个Activity的界面风格。Android系统为程序开发者提供了大量主题供其选择使用。
开发者可以在应用程序中创建自定义的主题样式。Android源代码中的themes.xml和style.xml(位于/frameworks/base/core/res/res/values/)包含了很多系统定义好的style,开发者可以在里面挑选合适的,然后再继承修改。
4.程序的日志
程序日志是记录程序中硬件、软件、系统问题的反馈信息,同时还可以监视程序中发生的执行状态和变化。用户可以通过它来检查错误发生的原因和痕迹。日志类型包括系统日志、应用程序日志和安全日志。日志通常有五种输出类型级别,详细描述如下:
- Debug级别:调试信息提示。
- Info级别:比较重要的信息提示。
- Warn级别:可能存在的潜在问题的提示。
- Error级别:系统发生异常的提示。
- Verbose级别:打印最详细的日志。
Android Logcat日志查看工具中输出,Logcat是Android SDK中的命令,它用于查看和过滤缓冲区中的日志信息。Logcat日志查看工具如下图所示。
Android日志信息由android.util.Log类提供,Log类输出的日志级别包括Debug、Info、Warn、Error和Verbose模式。
日志的输出语法格式如下:
Log.d|i|w|e|v;
其中,第一个参数代表消息源,第二个参数代表日志内容。
日志的使用示例如下:
(1)编写Activity类,在onCreate()方法中添加代码。代码如下:
Log.v("测试_v",“verbose模式,打印最详细的日志”);
Log.d("测试_d",“debug级别的日志”);
Log.i("测试_i",“info级别的日志”);
Log.w("测试_w",“warn级别的日志”);
Log.e("测试_e",“error级别的日志”);
(2)运行程序。日志输出内容,如下图所示。
日志的输出可以作为简单的调试功能使用,如查看变量的赋值情况和当前的运行位置。对于日志级别的使用,一般选择Debug和Info即可。

5.程序调试
程序调试,是程序投入实际运行前,手动或使用编译程序等方法进行测试,修正语法错误和逻辑错误的过程。调试可以不断地对程序进行优化以达到最好的效果。在开发中,通常在未达到预期结果、即将抛出运行时异常和程序性能不佳时使用。使用的步骤大致分为3步,详细描述如下:
-
设置调试断点
调试断点是执行测试开始的信号,当程序运行到调试断点之前的代码行时,程序将启动单步调试模式,Android Studio会打开Debugger控制台。设置调试断点,如下图所示

-
开启调试会话
启动调试模式是将程序以调试模式发布到Android虚拟机。此时,开发人员在Android系统中执行的操作将会与代码产生关联。点击工具栏上的“虫”按钮
开始调试会话。Android虚拟机接受调试状态,程序会停止到设置的断点处,如下图所示。

-
单步调试
要了解单步调试的功能,首先要了解Debugger控制台。Debugger控制台,如下图所示。
Debugger控制台的基本使用方法如下:
(1)调试开关按钮:负责控制当前运行程序的暂停、开始和关闭调试。
(2)变量监控区:负责当前代码中已定义的变量赋值情况,以树形结构展示。
(3)调试控制按钮:分为step over,step into、Force step into、step out和Drop frame五个操作,说明如下:
①step over:点击后程序向下执行一行(如果当前行有方法调用,该方法将被执行完毕返回,然后到下一行)。
②step into:点击后程序向下执行一行。如果该行有自定义方法,则运行进入自定义方法。
③Force step into:点击后能进入方法内部。
④step out:点击后将跳出已进入的方法体。
⑤Drop frame:点击后将返回到当前方法的调用处重新执行。
6.打包发布
打包是将所开发的Android应用程序生成APK安装包的过程。
当应用程序开发完成之后,通常会考虑将程序发布到国内外的应用程序商店,如豌豆荚和应用宝等,这一过程称为“上架”。在Android应用开发中,使用“包名”作为项目唯一标识,在安装应用时如果“包名”相同,则覆盖之前的应用程序。为避免这种情况的发生,Android程序产品都需要对其进行签名,再将程序打包。签名的具体作用如下:
(1)确定发布者的身份。身份信息包括数字证书名,证书密码,开发者姓名,单位,所在国家,省份,城市等,以避免出现应用程序覆盖的现象。
(2)确保应用的唯一性,签名会对应用包中的每个文件进行处理,从而确保程序包中的文件不会被替换。
Android应用程序打包步骤如下:
(1)在Android Studio工具的主菜单中选择“Build”->"Generate Signed APK"选项。打开【Generate Signed Bundle or APK】对话框,如下图所示。
(2)在【Generate Signed Bundle or APK】对话框中选择【Create new】创建数字签名,数字签名包括证书密码、证书有效期、作者、所属组织等重要信息。【New Key Store】对话框,如下图所示。
(3)点击【OK】按钮生成数字签名文件,该文件将生成在指定的磁盘目录。同时,返回【Generate Signed Bundle or APK】对话框,点击【Finish】按钮完成最后的打包步骤。
在图1.36中,“Build Type”指定打包版本类型,release代表发布版,debug代表测试版。
