Android系统四大组件:
分别是活动(Activity)、服务(Service)、广播接收器(Broadcast Receiver)和内容提供器(Content Provider)。
其中活动是所有Android应用程序的门面,凡是在应用中你看得到的东西,都是放在活动中的。而服务就比较低调了,你无法看到它,但它会一直在后台默默地运行,即使用户退出了应用,服务仍然是可以继续运行的。广播接收器允许你的应用接收来自各处的广播消息,比如电话、短信等,当然你的应用同样也可以向外发出广播消息。内容提供器则为应用程序之间共享数据提供了可能,比如你想要读取系统电话簿中的联系人,就需要通过内容提供器来实现。
创建你的第一个Android项目
分析你的第一个Android程序
app目录下的结构
AndroidManifest.xml文件
这段代码表示对HelloWorldActivity这个活动进行注册,没有在AndroidManifest.xml里注册的活动是不能使用的。其中intent-filter 里的两行代码非常重要,
表示HelloWorldActivity是这个项目的主活动。
HelloWorldActivity
public class HelloWorldActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hello_world_layout);
}
}
HelloWorldActivity是继承自AppCompatActivity的,这是一种向下兼容的Activity,可以将Activity在各个系统版本中增加的特性和功能最低兼容到Android 2.1系统。Activity是Android系统提供的一个活动基类,我们项目中所有的活动都必须继承它或者它的子类
才能拥有活动的特性(AppCompatActivity 是Activity的子类)。然后可以看到
HelloWorldActivity中有一个onCreate() 方法,这个方法是一个活动被创建时必定要执行的方法,其中只有两行代码,并且没有Hello World!的字样。
其实Android程序的设计讲究逻辑和视图分离,因此是不推荐在活动中直接编写界面的,更加通用的一种做法是,在布局文件中编写界面,然后在活动中引入进来。可以看到,在onCreate() 方法的第二行调用了setContentView() 方法,就是这个方法给当前的活动引入了一个hello_world_layout布局,那Hello World!一定就是在这里定义的了!我们快打开这个文件看一看。
布局文件都是定义在res/layout目录下的,当你展开layout目录,你会看到hello_world_layout.xml这个文件
详解项目中的资源
res目录下的结构
所有以drawable开头的文件夹都是用来放图片的,所有以mipmap开头的文件夹都是用来放应用图标的,所有以values开头的文件夹都是用来放字符串、样式、颜色等配置的,layout文件夹是用来放布局文件的。
之所以有这么多mipmap开头的文件夹,其实主要是为了让程序能够更好地兼容各种设备。drawable文件夹也是相同的道理,虽然Android Studio没有帮我们自动生成,但是我们应该自己创建drawable-hdpi、drawable-xhdpi、drawable-xxhdpi等文件夹
打开res/values/strings.xml文件:
HelloWorld
可以看到,这里定义了一个应用程序名的字符串,我们有以下两种方式来引用它。
在代码中通过R.string.app_name 可以获得该字符串的引用。
在XML中通过@string/app_name 可以获得该字符串的引用。
基本的语法就是上面这两种方式,其中string 部分是可以替换的,如果是引用的图片资源就可以替换成drawable ,如果是引用的应用图标就可以替换成mipmap ,如果是引用的布局文件就可以替换成layout ,以此类推。
简单的例子来帮助你理解,打开AndroidManifest.xml文件,找到如下代码:
...
HelloWorld项目的应用图标就是通过android:icon 属性来指定的,应用的名称则是通
过android:label 属性指定的。
详解build.gradle文件
Android Studio是采用Gradle来构建项目的。Gradle是一个非常先进的项目构建工具,它使用了一种基于Groovy的领域特定语言(DSL)来声明项目设置,摒弃了传统基于
XML(如Ant和Maven)的各种烦琐配置。
HelloWorld项目中有两个build.gradle文件,一个是在最外层目录下的,一个是在app目录下的。这两个文件对构建Android Studio项目都起到了至关重要的作用,下面我们就来对这两个文件中的内容进行详细的分析。
最外层目录下的build.gradle文件
buildscript {
repositories {
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:2.2.0'
}
}
allprojects {
repositories {
jcenter()
}
}
这些代码都是自动生成的,虽然语法结构看上去可能有点难以理解,但是如果我们忽略语法结构,只看最关键的部分,其实还是很好懂的。
首先,两处repositories 的闭包中都声明了jcenter() 这行配置,那么这个jcenter是什么
意思呢?其实它是一个代码托管仓库,很多Android开源项目都会选择将代码托管到jcenter上,声明了这行配置之后,我们就可以在项目中轻松引用任何jcenter上的开源项目了。
接下来,dependencies 闭包中使用classpath 声明了一个Gradle插件。为什么要声明这个插件呢?因为Gradle并不是专门为构建Android项目而开发的,Java、C++等很多种项目都可以使用Gradle来构建。因此如果我们要想使用它来构建Android项目,则需要声明com.android.tools.build:gradle:2.2.0 这个插件。其中,最后面的部分是插件的
版本号,我在写作本书时最新的插件版本是2.2.0。
app目录下的build.gradle文件
apply plugin: 'com.android.application'
android {
compileSdkVersion 24
buildToolsVersion "24.0.2"
defaultConfig {
applicationId "com.example.helloworld"
minSdkVersion 15
targetSdkVersion 24
versionCode 1
versionName "1.0"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'),
'proguard-rules.pro'
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:24.2.1'
testCompile 'junit:junit:4.12'
}
首先第一行应用了一个插件,一般有两种值可选:com.android.application 表示这是一个应用程序模块,com.android.library 表示这是一个库模块。应用程序模块和库模块的最大区别在于,一个是可以直接运行的,一个只能作为代码库依附于别的应用程序模块来运行。
接下来是一个大的android闭包 ,在这个闭包中我们可以配置项目构建的各种属性。其
中,compileSdkVersion 用于指定项目的编译版本,这里指定成24表示使用Android 7.0系统的SDK编译。buildToolsVersion 用于指定项目构建工具的版本,目前最新的版本就是24.0.2,如果有更新的版本时,Android Studio会进行提示。
然后我们看到,这里在android闭包中又嵌套了一个defaultConfig闭包 ,defaultConfig闭包中可以对项目的更多细节进行配置。其中,applicationId 用于指定项目的包名,前面我们在创建项目的时候其实已经指定过包名了,如果你想在后面对其进行修改,那么就是在这里修改的。minSdkVersion 用于指定项目最低兼容的Android系统版本,这里指定成15表示最低兼容到Android 4.0系统。targetSdkVersion 指定的值表示你在该目标版本上已经做过了充分的测试,系统将会为你的应用程序启用一些最新的功能和特性。比如说Android 6.0系统中引入了运行时权限这个功能,如果你将targetSdkVersion 指定成23或者更高,那么系统就会为你的程序启用运行时权限功能,而如果你将targetSdkVersion 指定成22,那么就说明你的程序最高只在Android 5.1系统上做过充分的测试,Android 6.0系统中引入的新功能自然就不会启用了。剩下的两个属性都比较简单,versionCode 用于指定项目的版本号,versionName 用于指定项目的版本名,这两个属性在生成安装文件的时候非常重要,我们在后面都会学到。
分析完了defaultConfig闭包,接下来我们看一下buildTypes闭包 。buildTypes闭包中用于指定生成安装文件的相关配置,通常只会有两个子闭包,一个是debug,一个是release。debug闭包用于指定生成测试版安装文件的配置,release闭包用于指定生成正式版安装文件的配置。另外,debug闭包是可以忽略不写的,因此我们看到上面的代码中就只有一个release闭包。下面来看一下release闭包中的具体内吧,minifyEnabled 用于指定是否对项目的代码进行混淆,true表示混淆,false 表示不混淆。proguardFiles 用于指定混淆时使用的规则文件,这里指定了两个文件,第一个proguard-android.txt 是在Android SDK目录下的,里面是所有项目通用的混淆规则,第二个proguard-rules.pro 是在当前项目的根目录下的,里面可以编写当前项目特有的混淆规则。需要注意的是,通过Android Studio直接运行项目生成的都是测试版安装文件,关于如何生成正式版安装文件我们将会在第15章中学习。
这样整个android闭包中的内容就都分析完了,接下来还剩一个dependencies闭包 。这个闭包的功能非常强大,它可以指定当前项目所有的依赖关系。通常Android Studio项目一共有3种依赖方式:本地依赖、库依赖和远程依赖。本地依赖可以对本地的Jar包或目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖则可以对jcenter库上的开源项目添加依赖关系。观察一下dependencies闭包中的配置,第一行的compile fileTree 就是一个本地依赖声明,它表示将libs目录下所有.jar后缀的文件都添加到项目的构建路径当中。而第二行的compile 则是远程依赖声明,com.android.support:appcompat-v7:24.2.1 就是一个标准的远程依赖库格式,其中com.android.support 是域名部分,用于和其他公司的库做区分;appcompat-v7 是组名称,用于和同一个公司中不同的库做区分;24.2.1是版本号,用于和同一个库不同的版本做区分。加上这句声明后,Gradle在构建项目时会首先检查一下本地是否已经有这个库的缓存,如果没有的话则会去自动联网下载,然后再添加到项目的构建路径当中。至于库依赖声明这里没有用到,它的基本格式是compile project 后面加上要依赖的库名称,比如说有一个库模块的名字叫helper,那么添加这个库的依赖关系只需要加compile
project(’:helper’) 这句声明即可。另外剩下的一句testCompile 是用于声明测试用例
库的,这个我们暂时用不到,先忽略它就可以了。
使用Android的日志工具Log
Android中的日志工具类是Log(android.util.Log),这个类中提供了如下5个方法来供我们打印日志。
打开HelloWorldActivity,在onCreate() 方法中添加一行打印日志的语句
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.hello_world_layout);
Log.d("HelloWorldActivity", "onCreate execute");
}
Log.d() 方法中传入了两个参数:第一个参数是tag ,一般传入当前的类名就好,主要用于对打印信息进行过滤;第二个参数是msg ,即想要打印的具体的内容。