目录
Instrumentation和ActivityThread
-
创建流程
-
环境设置与准备:
首先,您需要在计算机上搭建Android开发环境。这包括下载并安装Java JDK(Java Development Kit)以及Android Studio(Google官方的Android开发工具)。这些工具将为您提供开发Android APP所需的一切。
-
学习Java编程语言:
Java是Android手机APP开发的主要编程语言。学习Java语法和面向对象编程(OOP)的基础概念是非常重要的。
-
理解Android应用的结构:
了解Android应用的结构对您很有帮助。Android应用由活动(Activities)、布局(Layouts)、服务(Services)、广播接收器(Broadcast Receivers)和内容提供器(Content Providers)等组件组成。学习这些组件的功能和交互方式将为您的APP开发奠定坚实基础。
-
学习XML布局:
Android使用XML文件来定义应用的布局。学习XML布局语言可以让您创建用户界面,安排各种UI元素的位置和样式。
-
编写第一个APP:
现在,您已经准备好编写您的第一个Android APP了。通过Android Studio创建一个新项目,并开始编写代码。您可以创建简单的“Hello World”APP,然后逐步增加更多功能和交互性。
-
掌握Android API和SDK:
Android提供了丰富的API(应用程序接口)和SDK(软件开发工具包),包含了各种功能和服务。学习如何使用这些API和SDK将为您的APP开发带来更多可能性。
-
测试与调试:
在开发过程中,经常进行测试和调试是必不可少的。您可以在模拟器上测试APP,也可以将APP安装在真实的Android设备上进行测试。
这个过程不仅涉及技术层面的学习和实践,还包括对Android开发环境的熟悉、编程语言的学习、应用结构的理解、布局设计以及调试测试等各个环节。通过逐步完成这些步骤,开发者可以顺利地完成从零到一的Android App创建过程。
-
编码流程
Android 应用编译是将开发者编写的 Java 或 Kotlin 代码转化为 Android 可执行的 Dalvik 字节码的过程。
-
编译流程如下:
Android 应用编译流程包括以下几个主要步骤:
-
代码编译:将 Java 或 Kotlin 代码编译为字节码。
-
资源处理:处理应用的资源文件。
-
打包:将编译后的字节码和资源文件打包成 APK 文件。
-
签名:对 APK 文件进行数字签名,以确保应用的完整性和安全性。
-
代码编译
代码编译是将开发者编写的 Java 或 Kotlin 代码转化为 Android 可执行的 Dalvik 字节码的过程。Android 开发工具提供了编译器将 Java 或 Kotlin 代码编译为字节码。在 Android Studio 中,可以使用 Gradle 构建工具来自动完成代码编译。
简单的 Java 代码示例:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
}
-
资源处理
资源处理是处理应用的资源文件的过程,包括图片、布局文件、字符串等。资源文件通常存储在 res 目录下,Android 开发工具将这些资源文件编译为二进制格式,方便应用在运行时加载和使用。
简单的布局文件示例:
<LinearLayout xmlns:android="
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">
<TextView
android:id="@+id/textView"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!" />
</LinearLayout>
-
打包
打包是将编译后的字节码和资源文件打包成 APK 文件的过程。APK 文件是 Android 应用的安装包,其中包含了应用的所有组件以及资源文件。通过打包,可以将应用发布到各个 Android 设备上进行安装和使用。
-
签名
签名是对 APK 文件进行数字签名的过程,以确保应用的完整性和安全性。数字签名由开发者的私钥生成,可以保证 APK 文件在传输和安装过程中没有被篡改。Android 系统会验证 APK 文件的签名信息,以确保应用的安全性。
-
类图
以下是 Android 应用编译的类图示例:
上述类图展示了一个简单的 Android 应用中的主活动类 MainActivity 及其继承自 AppCompatActivity 的关系。
-
流程图
以下是 Android 应用编译的流程图示例:
上述流程图展示了 Android 应用编译的基本流程,包括代码编译、资源处理、打包和签名等步骤。
-
总结
Android 应用编译是将开发者编写的 Java 或 Kotlin 代码转化为 Android 可执行的 Dalvik 字节码的过程。
-
打包流程
Android App打包是将开发完成的Android应用程序转化为可安装的APK文件的过程。
下面是整个Android App打包的流程:
-
确定开发环境和工具
-
创建一个Android项目
-
编写和测试代码
-
配置构建参数
-
打包生成APK文件
-
安装和测试应用
-
确定开发环境和工具
在开始之前,你需要确保你已经安装了以下开发环境和工具:
-
Android Studio:用于开发Android应用程序的集成开发环境(IDE)。
-
Android SDK:包含了Android开发所需的各种工具和库。
-
创建一个Android项目
在Android Studio中创建一个新的Android项目。这可以通过选择"File" -> “New” -> "New Project"来完成。在创建项目的过程中,你需要设置项目的名称、包名、目标Android版本等。
-
编写和测试代码
在项目创建完成后,你可以开始编写和测试你的Android应用程序代码。这包括编写Java代码、布局文件和资源文件等。
-
配置构建参数
在打包之前,你需要配置构建参数,以指定应用程序的一些基本信息。这可以在项目的build.gradle文件中完成。
下面是一个示例的build.gradle文件:
android {
compileSdkVersion 30
buildToolsVersion "30.0.3"
defaultConfig {
applicationId "com.example.myapp"
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
}
// 其他配置项...
}
在上述代码中,你需要根据你的应用程序的要求来配置各个参数,如applicationId表示应用程序的包名,minSdkVersion表示最低支持的Android版本,versionCode和versionName表示应用程序的版本信息。
-
打包生成APK文件
当你的应用程序代码编写完成后,你可以开始进行打包操作。首先,在Android Studio的工具栏中选择"Build" -> “Build Bundle(s) / APK(s)” -> “Build APK(s)”。这将生成一个APK文件。
-
安装和测试应用
生成的APK文件可以通过多种方式进行安装和测试,例如:
-
将APK文件手动拷贝到Android设备中,然后在设备上进行安装。
-
使用Android Studio提供的"Run"按钮来自动安装和运行应用程序。
以上就是Android App打包的基本流程。通过按照上述步骤进行操作,你可以将你的Android应用程序成功打包成可安装的APK文件。
下面是一个甘特图,展示了Android App打包流程的时间安排:
-
安装流程
在安装APK之前,我们需要确保设备的ADB(Android Debug Bridge)连接正常,并且具有适当的文件权限。
应用安装涉及到如下几个目录:
system/app 系统自带的应用程序,无法删除
data/app 用户程序安装的目录,有删除权限。安装时把apk文件复制到此目录
data/data 存放应用程序的数据
Data/dalvik-cache 将apk中的dex文件安装到dalvik-cache目录下(dex文件是dalvik虚拟机的可执行文件,其大小约为原始apk文件大小的四分之一)
安装过程:
复制APK安装包到data/app目录下,解压并扫描安装包,把dex文件(Dalvik字节码)保存到dalvik-cache目录,并data/data目录下创建对应的应用数据目录。
卸载过程:
删除安装过程中在上述三个目录下创建的文件及目录。
-
Android应用安装的四种方式:
1.系统应用安装:开机时完成,没有安装界面 2.网络下载应用安装:通过market应用完成,没有安装界面 3.ADB工具安装:没有安装界面。 4.第三方应用安装:通过SD卡里的APK文件安装,有安装界面,由packageinstaller.apk应用处理安装及卸载过程的界面。
-
安装流程图
-
APK文件结构
APK(Android Package),可以看做是一个zip压缩包,可以通过解压缩工具解开,其文件结构如下:
目录 or 文件 | 描述 |
assert | 存放的原生资源文件,通过AssetManager类访问 |
lib | native库文件 |
META-INF | 存放签名信息,用来保证APK包的完整性和系统的安全。系统安装APK时,应用管理器会按照对应算法对包里文件做校验,如果校验结果与META-INF中内容不一致,则不会安装这个APK。 |
res | 种资源文件系统会在R.java里面自动生成该资源文件的ID,所以访问这种资源文件比较简单,通过R.XXX.ID即可 |
AndroidManifest.xml | 每个应用都必须定义和包含,描述应用的名字、版本权限、引用的库文件等信息。apk中的AndroidManifest.xml经过压缩,可以通过AXMLPrinter2工具解开。 |
classes.dex | 是JAVA源码编译后生成的JAVA字节码文件。但Android使用的dalvik虚拟机与标准的JAVA虚拟机不兼容,dex文件与class文件相比,不论是文件结构还是opcode都不一样。 |
resources.arsc | 编译后的二进制资源文件。 |
-
安装APK
安装应用程序,最常用的方法就是在PC上运行命令adb install 加APK的文件路径,回车等待Android设备安装完成,安装成功命令行会显示Success。那么其内部是怎样的一个过程呢?
-
将APK包push到手机
首先,adb会将PC端的APK文件push到Android设备的/data/local/tmp目录下,一些手机会将拷贝的进度反馈给adb客户端,于是PC上的命令行会展示拷贝的进度。
-
执行pm命令
PC端的adb程序会向Android端的adbd发送shell:pm命令,于是adbd会向系统的PackageManagerService(PMS)进程发送消息,通知其安装apk包。这里可以有两个理解:
理解一:我们平常也可以在adb shell上执行pm命令与PMS交互,那么pm应该是个独立的进程,adbd执行pm命令,是启动了pm这个进程,这个进程再向PMS进程发送消息,通知其安装APK。
理解二:adbd直接向PMS进程发送消息,通知其安装APK。
不知哪个正确,这个有待继续研究。
-
触发安装过程
PMS首先将APK包拷贝到另外一个目录/data/app,这个目录是非系统应用的apk存放的目录,与之相对应的,系统应用的apk存放的目录是/system/frameworks、/system/app和/vendor/app。
PMS内部有个AppDirObserver类,其监听着/data/app目录的变化,当apk被复制到/data/app目录之后,该类随即触发PMS对APK进行解析。
-
APK的解析
我们可以先想想,Android系统是如何启动一个APP的?比如点击屏幕上的应用图标,然后一个Activity就被启动了。这个过程中,桌面程序Launcher先是向ActivityManagerService(AMS)进程发送了一个Intent,AMS随即会将这个Intent扔给PMS,PMS则解析这个Intent得到Activity的信息给到AMS,然后AMS会启动一个空进程,并通知该进程创建该Activity。那么PMS为什么会有这个Activity的信息呢?
这就是PMS解析APK要做的事情了,而解析APK的时机又要分成两种场景:
-
系统启动时解析APK
Android系统在启动的时候,会启动一个system_server进程,这个进程驻留着系统多个重要的服务,其中便包含了与APK最相关的PackageManagerService服务,这个服务在启动的时候,会扫描Android系统中几个目标文件夹中的APK,对每个APK进行解析。
-
安装过程中解析APK
安装一个apk的过程,PMS也会对这个APK进行解析,其调用的是PackageManagerService.java的scanPackageLI()方法,其实在系统启动时扫描全部apk的过程也是调用该方法。
可以这样理解,系统启动的时候,是解析已经安装的所有APK,而安装单个APK时,则是用同样的方法解析这个APK,过程是一样的。
解析APK具体做的是什么事情呢?
以下是详细的步骤和相关命令说明:
-
开机后连上网线
首先确保设备已经连接到网络。通过网线连接设备后,可以通过以下步骤查看设备的IP地址。
-
查看网线的IP地址
打开命令行终端(CMD)输入以下命令查看设备的IP地址:
adb shell ifconfig
-
检查ADB连接
在CMD中输入以下命令,检查是否能连接到设备:
adb devices
如果设备列表中显示了连接的设备,说明ADB连接正常。
-
修改文件权限
在某些情况下,我们需要修改设备中文件或目录的权限以便进行后续操作。以下是详细步骤:
步骤
-
adb root - 以root权限重启ADB守护进程
adb root
-
adb remount - 将设备的/system分区重新挂载为可读写权限
adb remount
-
adb shell - 在连接的设备上打开一个命令行界面
adb shell
cd /system/app - 进入系统应用目录
chmod 0 XbhSetting - 将XbhSetting文件权限改为0
chmod 0 XbhSetting
reboot - 重启设备
连接IP:设备重启后,重新通过ADB连接设备的IP地址
安装APK
adb install [APK文件的路径]
-
启动流程
App启动流程分为2个部分:
-
一个是系统开机,拉起Launcher APP。
-
另一个流程分为Launcher APP点击桌面应用图标,然后启动APP。
安卓的启动流程大致分为几个阶段。
-
BootRom:启动电源以及系统启动。
当电源按下时,引导芯片代码从预定义的地方(固化在ROM中)开始执行。加载引导程序BootLoader到RAM,然后执行。
-
引导程序Bootloader
引导程序BootLoader是在android操作系统开始运行前的一个小程序,他的主要作用是把系统OS拉起来并运行。
-
Linux kernel启动
当内核启动时,设置缓存、被保护存储器、计划列表、加载驱动。当内核完成系统设置时,它首先在系统文件中寻找init.rc文件,并启动init进程。
-
init进程启动
初始化和启动属性服务,并且启动Zygote进程。
-
Zygote进程启动
创建Java虚拟机并为Java虚拟机注册JNI方法,创建服务器端Socket,启动SystemServer进程。
-
systemserver进程启动
启动Binder线程池和SystemServiceManager,并且启动各种系统服务。
-
Launcher进程启动
被SystemServer进程启动的AMS会启动Launcher,Launcher启动后会将已安装应用的快捷图标显示到界面上。
1.1、冷启动和热启动
-
冷启动:当启动应用时,后台没有该应用的进程,这时系统会重新创建一个新的进程分配给该应用,然后再根据启动的参数,启动对应的进程组件,这个启动方式就是冷启动。
-
热启动:当启动应用时,后台已有该应用的进程(例:按back键、home键,应用虽然会退出,但是该应用的进程是依然会保留在后台,可进入任务列表查看),所以在已有进程的情况下,这种启动会从已有的进程中来启动对应的进程组件,这个方式叫热启动。
1.2、启动架构图:
启动流程
①点击桌面App图标,Launcher进程采用Binder IPC向system_server进程发起startActivity请求;
②system_server进程接收到请求后,向zygote进程发送创建进程的请求;
③Zygote进程fork出新的子进程,即App进程;
④App进程,通过Binder IPC向sytem_server进程发起attachApplication请求;
⑤system_server进程在收到请求后,进行一系列准备工作后,再通过binder IPC向App进程发送scheduleLaunchActivity请求;
⑥App进程的binder线程(ApplicationThread)在收到请求后,通过handler向主线程发送LAUNCH_ACTIVITY消息;
⑦主线程在收到Message后,通过发射机制创建目标Activity,并回调Activity.onCreate()等方法。
⑧App便正式启动,开始进入Activity生命周期,执行完onCreate/onStart/onResume方法,UI渲染结束后便可以看到App的主界面。
主要类介绍
2.1、zygote
zygote意为“受精卵“。Android是基于Linux系统的,而在Linux中,所有的进程都是由init进程直接或者是间接fork出来的,zygote进程也不例外。
Android系统zygote是一个进程的名字。Android是基于Linux System的,当你的手机开机的时候,Linux的内核加载完成之后就会启动一个叫“init“的进程。在Linux System里面,所有的进程都是由init进程fork出来的,我们的zygote进程也不例外。
App:
● 一个单独的dalvik虚拟机 ● 一个单独的进程
系统里面的第一个zygote进程运行之后,在这之后再开启App,就相当于开启一个新的进程。而为了实现资源共用和更快的启动速度,Android系统开启新进程的方式,是通过fork第一个zygote进程实现的
2.2、System_server
SystemServer也是一个进程,而且是由zygote进程fork出来的。知道了SystemServer的本质,这个进程是Android Framework里面两大非常重要的进程之-—另外一个进程就是上面的zygote进程。SystemServer非常重要,因为系统里面重要的服务都是在这个进程里面开启的,比如ActivityManagerService、PackageManagerService、WindowManagerService
2.3、ActivityManagerService
ActivityManagerService,简称AMS,服务端对象,负责系统中所有Activity的生命周期。ActivityManagerService进行初始化的时机很明确,就是在SystemServer进程开启的时候,就会初始化ActivityManagerService。
下面介绍下Android系统里面的服务器和客户端的概念。
App与AMS通过Binder进行IPC通信,AMS(SystemServer进程)与zygote通过Socket进行IPC通信
Instrumentation和ActivityThread
每个Activity都持有Instrumentation对象的一个引用,但是整个进程只会存在一个Instrumentation对象。Instrumentation这个类里面的方法大多数和Application和Activity有关,这个类就是完成对Application和Activity初始化和生命周期的工具类。Instrumentation这个类很重要,对Activity生命周期方法的调用根本就离不开他,他可以说是一个大管家。
ActivityThread,依赖于UI线程。App和AMS是通过Binder传递信息的,那么ActivityThread就是专门与AMS的外交工作的。
2.5、ApplicationThread
而且由于继承了同样的公共接口类,ActivityManagerProxy提供了与ActivityManagerService一样的函数原型,使用户感觉不出Server是运行在本地还是远端,从而可以更加方便的调用这些重要的系统服务。
服务端–>客户端
还是通过Binder通信,不过是换了另外一对,换成了ApplicationThread和ApplicationThreadProxy。
他们也都实现了相同的接口IApplicationThread
private class ApplicationThread extends ApplicationThreadNative {}
public abstract class ApplicationThreadNative extends Binder implements IApplicationThread{}
class ApplicationThreadProxy implements IApplicationThread {}