《第一行代码 Android》作为Android入门书籍,由郭霖大神编写的,这本书相对比其他入门书籍比较基础并且深度也不错。本文主要是针对第一章概况读书简记,便于日后温故,总结。
Android 系统起源
首先,作为一名Android开发人员来说,对于Android系统怎么而来的,想必大家或多或少听说一些。Android作为现如今拥有用户群体的手机系统,起初是由Andy Rubin(“Android之父”)同其他三位创始人成立了“Android公司“,为了数码相机开发出来的一套基于Linux系统,这便是Android的雏形。
随后,Android转而开发手机操作系统,并于2005年被谷歌收购,Rubin和其他创始人留在谷歌,开始了真正意义上的智能手机操作系统开发。在这个时候,Android系统的方向已经确定,比如基于Linux、开源、免费供手机厂商使用等等,谷歌则可将其服务深度集成到系统中获得利润。
2008年,谷歌发布了第一版Android系统”Android 1.0“,接着在2009年发布了1.1版本,随后在1.5版本开始出现以甜点命名版本,具体版本如下:
Android Beta,发布于2007年11月5日,同时的软件开发套件(SDK),发布于2007年11月12日。 11月5日被认为是Android的"生日"。
Android版本名称Code name | Android版本 | 版本发布时间 | 对应API |
---|---|---|---|
(no code name) | 1.0 | 2008年9月23日 | API level 1 |
(no code name) | 1.1 | 2009年2月2日 | API level 2 |
Cupcake | 1.5 | 2009年4月17日 | API level 3,NDK 1 |
Donut | 1.6 | 2009年9月15日 | API level 4,NDK 2 |
Eclair | 2.0.1 | 2009年12月3日 | API level 6 |
Eclair | 2.1 | 2010年1月12日 | API level 7,NDK3 |
Froyo | 2.2.x | 2010年1月12日 | API level 8,NDK 4 |
Gingerbread | 2.3 – 2.3.2 | 2011年1月1日 | API level 9,NDK5 |
Gingerbread | 2.3.3 – 2.3.7 | 2011年9月2日 | API level 10 |
Honeycomb | 3.0 | 2011年2月24日 | API level 11 |
Honeycomb | 3.1 | 2011年5月10日 | API level 12,NDK 6 |
Honeycomb | 3.2.x | 2011年7月15日 | API level 13 |
Ice Cream | Sandwich 4.0.1 – 4.0.2 | 2011年10月19日 | API level 14,NDK 7 |
Ice Cream | Sandwich 4.0.3 – 4.0.4 | 2012年2月6日 | API level 15,NDK 8 |
Jelly Bean | 4.1 | 2012年6月28日 | API level 16 |
Jelly Bean | 4.1.1 | 2012年6月28日 | API level 16 |
Jelly Bean | 4.2-4.2.2 | 2012年11月 | API level 17 |
Jelly Bean | 4.3 | 2013年7月 | API level 18 |
KitKat | 4.4 | 2013年7月24日 | API level 19 |
Kitkat Watch | 4.4W | 2014年6月 | API level 20 |
Lollipop(Android L) | 5.0/5.1 | 2014年6月25日 | API level 21/API level 22 |
Marshmallow(Android M) | 6.0 | 2015年5月28日 | API level 23 |
Nougat(Android N) | 7.0 | 2016年5月18日 | API level 24 |
Nougat(Android N) | 7.1 | 2016年12月 | API level 25 |
Oreo(Android O) | 8.0 | 2017年8月22日 | API level 26 |
Oreo(Android O) | 8.1 | 2017年12月5日 | API level 27 |
Pie (Android P)不是凤梨酥(PineappleCake) | 9.0 | 2018年8月7日 | API level 28 |
Android的版本,有个API Level,对应着某个Android发布版本的名称。
Android系统架构
上面我们大概了解了Android的起源以及对应的版本,并且也大概知道Android是基于Linux系统开发出来的移动终端系统,那接下来我们来了解下Android系统的内部架构,Android大致可以分为四层架构:Linux内核层、系统运行库层、应用框架层、应用层。
Linux内核层:
Android系统基于Linux内核,这一层为Android设备的各种硬件提供了底层的去驱动,如显卡驱动、音频驱动、相机驱动、蓝牙驱动、WIFI驱动、电源管理等。系统运行库层:
这层通过一些C/C++库为Android系统提供了主要的特性支持,例如SQLite库提供了数据库的支持,OpenGL|ES库提供了3D绘图的支持,Webkit库提供了浏览器内核的支持等等。
同样在这一层,还有谷歌为我们提供的Android运行时库,它主要提供了一些核心库,能够允许开发者使用Java语言来编写Android应用。另外,Android运行时库中还包含了Dalvik虚拟机(5.0系统之后改为ART运行环境,这两种环境在本质上有很大的区别,导致Android在运行性能方面更加优越,具体区别在后期会独篇说明,这里不过多阐述),它使得每个Android应用都能运行在独立的进程中,并且拥有自己的虚拟机实例。相对比于Java虚拟机,Android虚拟机是专门为移动设备定制的,它针对手机内存、CPU性能有限等情况做了优化处理。应用框架层
这层主要提供了构建应用程序时可能用到的各种API,Android自带的一些核心应用就是使用这些API完成的。应用层
所有安装在手机上的应用程序都属于这一层的,比如系统内置的联系人、短信等程序,或者从应用商城上下载下来的应用以及自己开发的程序都属于这层。
Android系统架构可以参考如下图:
Android开发环境搭建
针对于开发环境搭建,都是每个开发者老生常谈的必要走的一步,这里就不多累赘,只是贴出各个环境下载链接,便于日后查询配置使用。
- JDK
- Android Studio(可能部分小伙伴需要墙,也可以访问百度云盘资源)
- Android SDK一般这块不需要单独下载,谷歌已经将其集成到Android Studio中了,如果小伙伴有需要下载,也可以在 Android Studio上浏览到
Command line tools only
选择即可。
关于小伙伴在使用Android Studio过程中可能会遇到一些构建常见问题,可以详情了解下我的另外一篇文字《Android Studio 构建常见出错问题汇总》,以及《Android Studioc常用快捷键汇总》,不定时更新哦!
Android Studio目录结构分析
Android在早期开发还是使用Eclipse比较多,但自从2013年官方推出Android Studio(以下简称AS)之后,Android开发更多的倾向于使用AS开发,而且在推出AS之后,官方也相应停止了Eclipse开发Android对应的ADT更新,所以现在大部分都是采用AS开发。在这里有必要扯一下AS目录结构,毕竟两个IDE的编译机制是有所不同的,在Eclipse采用的Ant方式构建编译项目,而在AS中采用的是Gradle。
Eclipse在这我就不过多阐述了,我们要跟紧时代脚步,所以这里主要讲下AS中项目对应目录结构的功能与作用,新建一个项目,可得到如下所示:
.gradle和.idea
这两个目录下放置的都是AS自动生成的一些文件,所以这块我们不用关心,在拷贝项目备份或者版本管理时候,可以忽略这两个目录。app
项目中的代码、资源等内容几乎都在这个目录下,日常编写代码大部分也都在这个目录下进行的,所以这个目录的文件结构后面会单独解析具体底层目录。build
在AS高版本中这个目录已经不存在,低版本中存在这个目录,也是AS编译时自动生成的文件,不用关心,在拷贝项目备份或者文件管理时候,同样是可以忽略的目录。gradle
在这个目录下包含了gradle wrapper的配置文件,使用gradle wrapper的方式无需提前将gradle下载好,而是会自动根据本地的缓存情况决定是否需要联网下载gradle。.gitignore
这个文件用来将指定的目录或文件排除在版本控制(Git)之外的。build.gradle
这个文件是全局的gradle的构建脚本,通常这个文件中的内容是不需要修改的。后面会具有分析gradle构建脚本的内容。gradle.properties
这个文件是全局的gradle配置文件,在这里配置的属性会影响到项目中所有的gradle编译脚本。gradlew 和 gradlew.bat
这个两个文件是用来在命令行界面(Terminal)中执行gradle命令的,其中gradlew是在Linux或Mac系统中使用的,gradlew.bat是在windows系统中使用的。HelloWorld.iml
iml文件是所有IntelliJ IDEA项目都会自动生成的一个文件(AS是基于IntelliJ IDEA开发的),用于标识这是由IntelliJ IDEA项目,不需要修改此文件,可以在备份或者版本控制时候忽略。local.properties
文件是用于指定本机中的Android SDK路径,以及NDK路径,通常不需要修改,除非本地环境发生改变时候。setting.gradle
这个文件同于指定项目中所有引入的模块,由于此处只有app一个模块,因此该文件这里只引入的app这一个模块。通常情况都是自动完成的,只有手动导入模块时候,可能需要手动去修改。
整个项目的外层结构基本到这有一个大致的了解,接下来说下app目录,也就是我们代码经常需要修改调整的目录下的结构,如下所示:
build
这个目录和外层的build目录相似,主要也是包含了编译自动生成的文件,同样也无需关心,可以备份或者版本控制可以忽略。libs
项目中使用第三方jar包,需要把对应的jar包放在这个目录下,放在这个目录下的jar包会被自动添加到构建路径里去。androidTest
此处用来编写AndroidTest测试用例的,可以对项目进行一些自动化测试。java
此处用于编写应用的主要逻辑Java代码。res
这个目录主要存放应用的UI布局字符串等资源,这个目录相对比较复杂,在子目录layout下主要存放应用的布局文件,而图片根据不同的分辨率存放在以drawble-xxx目录下,当然有些类似selector选择器或者Shape自定义形状等等这些还是放在drawble中,子目录values下主要存放字符串、样式以及主题等。
在这个目录所有子目录下有一个子目录mipmap-xxx需要特别说明以下,mipmap是在Android Jelly Beans 4.3中提出来的,主要是为了让程序能够更好的兼容各种设备,在处理Launcher Icon图片渲染方面更加强大。AndroidManifest.xml
这个文件是整个应用的配置文件,在程序中定义的所有四大组件都必须在这个文件里注册,在这个文件配置需要的相应权限配置声明。test
此处用来编写Unit Test测试用例的,是对项目进行自动化测试的另外一种方式。.gitignore
这个文件用于app模块内的指定的目录或文件的排除在版本控制(Git)之外,作用与外层的.gitignore
,但一般都在外层的.gitignore
全局设置了。app.iml
IntelliJ IDEA项目自动生成的文件,不需要去修改与关心,备份或版本控制时候可以忽略。build.gradle
app模块的gradle构建脚本,这个文件会指定很多项目构建相关的配置。proguard-rules.pro
这个文件用于指定项目代码的混淆规则,当我们的代码编写打包成apk时候,如果不希望别人破解,通常会将代码进行混淆,从而让破解者难以阅读,考虑安全点,一般还会对apk进行加固。
因为Android Studio是采用Gradle来构建项目的,所以这里对Gradle的配置文件进一步讲解。Gradle是一个非常先进的项目构建工具,它使用了一种基于Groovy的领域特定语言(DSL)来声明项目设置,摒弃了传统基于XML(如Ant和Maven)的各种烦琐配置。
这里先说说项目外层中build.gradle文件的配置,如下:
// Top-level build file where you can add configuration options common to all sub-projects/modules.
buildscript {
repositories {
google()
jcenter()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.0.1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
google()
jcenter()
}
}
这些代码都是自动生成的,大部分情况下不需要我们去修改,但也得大概知道其意思。
首先两处repositories
的闭包中声明了google()、jcenter()配置,它们代表不同的代码托管仓库,很多的Android开源项目都会或多或少引用了谷歌提供开源项目,所以需要声明google(),而很多的Android开源项目都会选择将代码托管到jcenter上,声明了jcenter之后,我们就可以很方便的使用任何jcenter上的开源项目了。
接下来,dependencies闭包中使用了classpath声明了一个Gradle插件。为什么要声明这个插件呢?原来Gradle并不只是专门为构建Android项目而开发的,java、C++等很多项目都可以使用Gradle来构建。因此想要使用它来构建Android项目,则需要声明com.android.tools.build:gradle:3.0.1'这个插件,其中,最后冒号后面部分是插件的版本号,例如我现在这个项目中使用的插件版本是3.0.1.
分析完外层的build.gradle文件后,还需要分析模块里面的build.gradle文件,如下:
apply plugin: 'com.android.application'
android {
compileSdkVersion 26
buildToolsVersion "26.0.2"
defaultConfig {
applicationId "com.anand.activitylifecycletest"
minSdkVersion 15
targetSdkVersion 26
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:26.0.0-beta1'
implementation 'com.android.support.constraint:constraint-layout:1.0.2'
testImplementation 'junit:junit:4.12'
androidTestImplementation 'com.android.support.test:runner:0.5'
androidTestImplementation 'com.android.support.test.espresso:espresso-core:2.2.2'
}
这个文件相对复杂一些,首先第一行应用了一个插件,一般有两种值可选:com.android.application
表示这是一个应用程序模块,com.android.library
表示这是一个库模块。应用程序模块与库模块最大的区别在于一个是可以直接运行的,一个只能作为代码库依附于别的应用程序模块来运行。
紧接着是android
这个闭包,可以配置项目构建的各种属性。其中,compileSdkVersion
用于指定项目的编译版本,这里指定26表示使用Android 8.0系统的SDK编译,buildToolsVersion
用于指定项目构建工具的版本,这里使用了26.0.2版本。
接着是嵌套下的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
用于指定项目版本名,这个两个在安装应用文件以及版本升级方面比较重要。testInstrumentationRunner
为谷歌推荐的
AndroidJUnitRunner
单元测试(这块是Android Studio2.2以后推出的,这块我也是第一次接触,后期有学习再深入探索)
接着分析下buildTypes
闭包。buildTypes
闭包用于指定生成安装文件的相关配置。通常情况下会有两个子闭包,一个debug
,一个release
。debug
闭包用于指定生成测试版安装文件的配置,release
闭包用于指定生成正式版安装文件的配置。另外,debug
闭包是可以忽略不写的,因此默认情况下我们看到代码中只有一个release
闭包。接下来,我们来看下debug
、release
闭包中具体内容吧,minifyEnable
用于指定是否对项目代码进行混淆操作,true
表示混淆,false
表示不混淆。proguardFiles
用于指定混淆时使用的规则文件,这里指定了两个文件,第一个proguard-android.txt
是在Android SDK下\tools\proguard
目录下,这里是所有项目的通用的混淆规则;第二个proguard-rules.pro
是在当前项目的根目录下的,里面可以编写当前项目特有的混淆规则。需要注意的是,通过AS直接运行项目生成都是测试版本安装文件,除非手动切换BuildVariants
设置。
分析完android
闭包,紧接着分析最后一个dependencies
闭包。这个闭包主要作用在于指定当前项目所有的依赖关系。通常AS项目一共有3种依赖关系:本地依赖、库依赖和远程依赖。本地依赖可以对本地的Jar包、aar包或者目录添加依赖关系,库依赖可以对项目中的库模块添加依赖关系,远程依赖则可以对jcenter库上的开源项目添加依赖关系。
观察dependencies
闭包中的配置,第一行implementation fileTree
就是一个本地依赖声明,表示将 libs
目录下所有.jar
后缀的文件都添加到项目的构建路径当中。而第二行的implementation
则是远程依赖声明,com.android.support:appcompat-v7:26.0.0-beta1
就是一个标准的远程依赖库格式,其中com.android.support
是域名部分,用于和其他公司的库做区分;appcompat-v7
是组名称,用于和同一个公司中不同的库做区分;26.0.0-beta1
是版本号,用于和同一个库不同的版本做区分。加上这句声明后,Gradle在构建项目时会首先检查一下本地是否已经存在这个库的缓存,如果没有的话则会自动去互联网下载,然后再添加到项目的构建路径当中。至于库依赖这里没有使用到,它的基本格式是implementation project
后面加上要依赖的库名称,例如有一个库模块的名称叫helper,那么添加这个库依赖的声明只需要加入implementation project(':helper')
即可。后面一些是声明主要是为了声明测试用例库的,后期会单独详细说明下,具体参考Android 项目中的几种单元测试用例。
Android 的日志工具使用
Android中使用的日志工具是Log(android.util.Log)
,这个类提供了5个方法来打印日志。
- Log.v()。用于打印那些最为琐碎的、意义最小的日志信息。对应级别verbose,是Android日志里面级别最低的一种。
- Log.d()。用于打印一些调式信息,这些信息对你调试程序和分析问题有帮助的。对应级别debug,比verbose高一级。
- Log.i()。用于打印一些比较重要的数据。这些数据应该是开发者非常想要看到的,可以帮助开发者分析用户行为数据。对应级别info,比debug高一级。
- Log.w()。用于打印一些警告信息,提示程序在这个地方可能会有潜在的风险,最好去修复一下这些出现警告的地方。对应级别warn,比info高一级。
- Log.e()。用于打印程序中的错误信息,比如程序进入到了catch语句当中。当有错误信息打印出来的时候,一般都代表你的程序出现严重问题了,必须尽快修复。对应级别error,比warn高一级。
关于为什么使用Log而不使用System.out疑问?
System.out.print
对应Java初学者开说应该很熟悉,在Eclipse中syso就可以快速打印出信息来,那么为什么Android不使用这个方法,而采用多级别的Log呢,主要的原因是打印不可控、打印时间无法确定、不能添加过滤器、日志没级别区分。对于程序比较复杂的情况下,日志比较多的情况下,快速定位问题无法很快定位到。
关于Log日志一些快捷键操作可以参考《Android Studioc常用快捷键汇总》中的Tab组合快捷键。
除了快捷键, AS还为Log日志提供了locat方便我们过滤查询日志,让我们可以快速定位到对应的日志上。AS目前为开发者提供了3个过滤器,Show only selected application
表示只显示当前选中程序中的日志,Firebase
是谷歌提供的一个分析工具,No Filters
相当于没有过滤器,会把所有的日志都显示出来。当然除了一首AS提供的三种过滤器,也可以自定义自己的过滤器,选择Edit Filter Configuration
会弹出一个过滤器配置界面,可以自行配置自定义过滤器,在Log Tag中对需要过滤的tag进行配置。