Android系统架构
- Linux内核层
- Android系统是基于Linux内核的,这一层为Android设备的各种硬件提供了底层的驱动,如显示驱动、音频驱动、照相机驱动、蓝牙驱动、WI-FI驱动、电源管理等。
- 系统运行库层
- 通过一些c\c++库来为Android系统提供了主要的特性支持。比如SQLite提供了数据库的支持。
- 在这一层还有Android运行时库,它主要提供 了一些核心库,能够允许开发者使用java语言来编写Android应用。
- Android运行时库包含了Dalvik虚拟机(5.0系统之后改为ART运行环境),它使得每一个Android应用都能运行在独立的进程当中,并且拥有一个自己的Dalvik虚拟机。
- Dalvik虚拟机是Android程序的虚拟机,是Android中Java程序的运行基础。其指令集基于寄存器架构,执行其特有的文件格式——dex字节码来完成对象生命周期管理、堆栈管理、线程管理、安全异常管理、垃圾回收等重要功能。它的核心内容是实现库(libdvm.so),大体由C语言实现。依赖于Linux内核的一部分功能——线程机制、内存管理机制,能高效使用内存,并在低速CPU上表现出的高性能。每一个Android应用在底层都会对应一个独立的Dalvik虚拟机实例,其代码在虚拟机的解释下得以执行。
- 应用框架层
- 这一层主要提供了构建应用程序时可能用的各种API,Android自带的一些核心应用就是使用这些API完成的,开发者也可以通过使用这些API来构建自己的应用程序。
应用层
- 所有安装在手机上的应用程序都是属于这一层的,比如系统自带的联系人、短信等程序。
Android系统架构图
四大组件
- 活动(activity)
- 定义:用户操作的可视化界面;它为用户提供了一个完成操作指令的窗口。当我们创建完毕Activity之后,需要调用
setContentView()
方法来完成界面的显示;以此来为用户提供交互的入口。在Android App 中只要能看见的几乎都要依托于Activity,所以Activity是在开发中使用最频繁的一种组件。 - Activity之间通过Intent进行通信。
- android应用中每一个Activity都必须要在AndroidManifest.xml配置文件中声明,否则系统将不识别也不执行该Activity。在android stdio会自动生成,但eclipse需要自己手动添加
- Activity的生命周期
在Android中会维持一个Activity Stack(Activity栈),当一个新的Activity创建时,它就会放到栈顶,这个Activity就处于运行状态。当再有一个新的Activity被创建后,会重新压人栈顶,而之前的Activity则会在这个新的Activity底下,就像枪梭压入子弹一样。而且之前的Activity就会进入后台。 - 一个Activity实质上有四种状态:
- 运行中(Running/Active):这时Activity位于栈顶,是可见的,并且可以用户交互。
- .暂停(Paused):当Activity失去焦点,不能跟用户交互了,但依然可见,就处于暂停状态。当一个新的非全屏的Activity或者一个透明的Activity放置在栈顶,Activity就处于暂停状态;这个时候Activity的各种数据还被保持着;只有在系统内存在极低的状态下,系统才会自动的去销毁Activity。
- 停止(Stoped):当一个Activity被另一个Activity完全覆盖,或者点击HOME键退入了后台,这时候Activity处于停止状态。这里有些是跟暂停状态相似的:这个时候Activity的各种数据还被保持着;当系统的别的地方需要用到内容时,系统会自动的去销毁Activity。
- 销毁(Detroyed):当我们点击返回键或者系统在内存不够用的情况下就会把Activity从栈里移除销毁,被系统回收,这时候,Activity处于销毁状态。
- 定义:用户操作的可视化界面;它为用户提供了一个完成操作指令的窗口。当我们创建完毕Activity之后,需要调用
- 服务
- 服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
不过需要注意的是,服务并不是运行在一个独立的进程当中的,而是依赖于创建服务时所在的应用程序进程。某个应用程序进程被杀掉时,所有依赖于该进程的服务也会停止运行。另外.也不要被服务的后台概念所迷惑,实际上服务并不会自动开启线程,所有的代码都是默认运行在主线程当中的。也就是说,我们需要在服务的内部手动创建子线程,并在这里执行具体的任务,否则就有可能出现主线程被阻塞住的情况。
- 服务(Service)是Android中实现程序后台运行的解决方案,它非常适合去执行那些不需要和用户交互而且还要求长期运行的任务。服务的运行不依赖于任何用户界面,即使程序被切换到后台,或者用户打开了另外一个应用程序,服务仍然能够保持正常运行。
- 广播接收器
- 允许应用接收来自各处的广播消息,比如电话、短信等,同样,应用也可以向外发出广播消息。
- 内容提供器
- 为应用程序之间共享数据提供了可能。
SQLite数据库
- 轻量级,运算速度极快、嵌入四、关系型。
Android SDK
- 谷歌提供的Android开发工具包,在进行Android开发时需要引入(用来使用Android相关的API)。
第一个Android项目
如何新建一个Android项目已写在另一篇文档中,并且发布到了语雀中,链接为:
https://www.yuque.com/aidushudexiaoluo/cz9b7o/oewwn7
程序分析
整体分析
- .gradle和.idea
这两个目录放置的都是Android Studio自动生成的一些文件,我们无须关心,也不要去手动编辑。 - app
项目中的代码、资源等内容几乎都是放置在这个目录下的,我们后面的开发工作也基本都是在这个目录下进行的。 - build
这个目录不需要过多关心,它主要包含了一些在编译时自动生成的文件。 - gradle
这个目录下包含了gradle wrapper的配置文件,使用gradle wrapple的方式不需要提前将gradle下载好,而是会自动根据本地的缓存情况决定是否要联网下载gradle。Android Studio默认没有启用gradle wrapper的方式。 - .gitgnore
这个文件是用来将指定的目录或文件排除在版本控制之外的。 - build.gradle
这是项目全局的gradle构建脚本,通常这个文件中的内容是不需要修改的。 - gradle.properties
这个文件是全局的gralde配置文件,在这配置的属性将会影响到项目中所有的gralde编译脚本。 - gradlew和gradlew.bat
这两个文件是用来在命令行界面中执行gradle命令的,其中gradlew是在Linux或Mac系统中使用的,gradlew.bat是在Windows系统中使用的。 - local.properties
这个文件用于指定本机中的Android SDK路径,通常内容都是自动生成的,不需要修改。除非本机中的Android SDK位置发生了变化,那么就将这个文件中的路径改成新的位置即可。 - settings.gradle
这个文件用于指定项目中所有引入的模块。由于HelloWorld项目中就只有一个app模块。通常情况下模块的引入都是自动完成的,需要我们手动去修改这个文件的场景可能比较少。
app目录分析
- build
这个目录和外层的build目录类似,主要包含了一些在编译时自动生成的文件,不过它里面的内容会更多更复杂,我们不需要过多关心。 - libs
如果项目中使用了第三方jar包,就需要把这些jar包都放在libs目录下,放在这个目录下的jar包都会被自动添加到构建路径中。 - androidTest
此处是用来编写Android Test测试用例的,可以对项目进行一些自动化测试。 - java
毫无疑问,java目录是放置我们所有java代码的地方,展开该目录,你将看到我们刚才创建的HelloWorldActivity文件就在里面 - res
这个目录放的内容就有点多了,简单说来,就是在项目中使用到的所有图片、布局、字符串等资源都要存放在这个目录下。当然这个目录下还有很多子目录,图片放在drawable目录下,布局放在layout目录下,字符串放在values目录下。 - AndroidMainifest.xml
这是整个Android项目的配置文件,在程序中定义的所有四大组件都需要在这个文件里注册,另外还可以在这个文件中给应用程序添加权限声明。 - test
此处是用来编写Unit Test测试用例的,是对项目进行自动化测试的另一种方式。 - .gitgnore
这个文件用于将app模块内的指定的目录或文件排除在版本控制之外,作用和外层的.gtignore文件类似。 - build.gradle
Intellij IDEA项目自动生成的文件,我们不需要关心或修改这个文件中的内容。 - proguard-rules
这个文件用于指定项目代码的混淆规则,当代码开发完成后达成安装包文件,如果不希望代码被别人破解,通常会将代码进行混淆,从而让破解者难以阅读。
gradle
Gradle是一个基于Apache Ant和Apache Maven概念的项目自动化构建开源工具。它使用一种基于Groovy的特定领域语言(DSL)来声明项目设置,目前也增加了基于Kotlin语言的kotlin-based DSL,抛弃了基于XML的各种繁琐配置。
MainActivity
- MainActivity是继承自AppCompatActivity的,是一种向下兼容的Activity,可以将Activity在各个系统版本中增加的特性和功能最低兼容到Android2.1系统。
- Activity是Android系统提供的一个活动基类,项目中所有的活动必须继承它或者它的子类才能拥有活动的特性。
- onCreat()方法:活动被创建时必定要执行的方法。
- setContentView():给当前的活动引入了一个hello_world_layout布局。
- 布局文件都是定义在res/layout目录下的。
详解项目中的资源
- 所有drawable开头的文件夹都是用来放图片的。
- 所有mipmap开头的文件夹都是用来放应用图标的。
- 所有以values开头的文件夹都是用来放字符串、样式、颜色等配置的。
- layout文件夹是用来放布局文件的。
多个相同开头的文件的目的是为了让程序能够更好地兼容各种设备。
如何修改应用的图标或者名称
<resources>
<string name="app_name">HelloWorld</string>
</resources>
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.HelloWorld">
两种方式进行引用:
- 在代码中通过R.string.xxxxxxxxxx
- 在XML中通过@XXX/XXXXXXX
详解build.gradle文件
外层build.gradle文件
allprojects {
repositories {
google()
mavenCentral()
jcenter() // Warning: this repository is going to shut down soon
}
}
- 这段配置的意思是,指定当前的项目工程可以从哪些仓库上去拉取依赖库给当前项目使用。
- jcenter():代码托管仓库,即将关闭。
- mavenCenteral():代码托管仓库。
- JCenter() 与 mavenCenter()在完全不同的服务器上维护,由不同的人提供内容,两者之间毫无关系。在jcenter上有的可能 Maven Central 上没有,反之亦然。
dependencies {
classpath "com.android.tools.build:gradle:4.2.2"
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
这里使用classpath声明了一个gradle插件
app目录下的build.gradle文件
plugins {
id 'com.android.application'
id 'kotlin-android'
}
这里应用了一个插件,一般有两种值可以可选。
com.android.application表示这是一个应用程序模块。可以直接运行。
com.android.library表示这是一个库模块。只能作为代码库依附于别的应用程序模块来运行。
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.helloworld"
minSdkVersion 16
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
- compileSdkVersion:用于指定项目的编译版本。
- buildToolsVersion:用于指定项目构建工具的版本。
- applicationId:用于指定项目的包名。
- minSdkVersion:用于指定项目最低兼容的Android系统版本。
- targetSdkVersion:指定的值,表示项目在该目标版本上已经做过了充分的测试。
- versionCode:用于指定项目的版本号。
- versionName:用于指定项目的版本名。
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
- debug闭包:指定生成测试版安装文件的配置,可以忽略不写。
- release闭包:指定生成正式版安装文件的配置。
- minifyEnable:用于指定是否对项目的代码进行混淆,true表示混淆,false表示不混淆。
- proguardFiles:用于指定混淆时使用的规则文件。
dependencies {
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation 'androidx.core:core-ktx:1.3.1'
implementation 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.google.android.material:material:1.2.1'
implementation 'androidx.constraintlayout:constraintlayout:2.0.1'
testImplementation 'junit:junit:4.+'
androidTestImplementation 'androidx.test.ext:junit:1.1.2'
androidTestImplementation 'androidx.test.espresso:espresso-core:3.3.0'
}
指定当前项目所有的依赖关系。
日志工具的使用
使用Android的日志工具Log
打印日志的五种方法:
- Log.v():打印最为琐碎的、意义最小的日志信息。对应级别是verbose,是Android日志里面级别最低的一种。
- Log.d():打印一些调试信息,对应级别debug,比verbose高一级。
- Log.i():打印一些比较重要的数据,对应级别info,比debug高一级。
- Log.w():打印一些警告信息,对应界别warn,比info高一级。
- Log,e():打印程序中的错误信息,对应级别error,比warn高一级。