Android Framework 概述
概要
Android 采用了分层架构,分为四个层,从高层到底层分别是应用程序层、应用程序框架层、系统运行库层,Linux 内核层。
整体启动过程如下:
init 进程是第一个用户进程, ContextManager、MediaServer、Zygote 进程都是其子进程。init 进程的任务就是对各种设备进行初始化,运行 Android Framework 所需要要的 Daemon、ContextManager、MediaServer、Zygote 等。
ContextManager 进程是一个管理 Android 系统服务的重要进程,所有的 Android 系统服务都需要通过 Binder IPC 将其注册到 ContextManager。
MediaServer 进程是一个启动 Native 系统服务的进程,用于启动除 SurfaceFlinger 之外的所有 Native 服务,包括但不限于:AudioFlinger、CameraService。
Zygote 进程用于缩减 Android 程序加载的时间,每当执行一个 Android 应用程序,Zygote 就会通过 fork ...
Handler Native 原理探究
前言
Native 中遇到的 RefBase,sp,wp 是 Android 提供的智能指针,详情可以参考:Android智能指针RefBase、sp、wp解析
Java 层通过 MessageQueue 和 Native 层的 NativeMessageQueue 进行通信,NativeMessageQueue 的相关能力又是通过 Native 层的 Looper 实现。
Native 层的 Looper 不仅实现了 Java 层 MessageQueue 需要的功能,还包括一些其他处理:
Native 层 Message 的发送和处理
支持 fd 监听和事件回调
Linux 相关Native 层同时用到了一些 Linux 相关的能力,因此需要先了解一下 Linux 相关的基础能力。
I/O 多路复用“I/O 多路复用”,又被称作 “事件驱动”,它本质上是将多个 I/O 操作共用少数几个甚至是一个线程,简单来说:
I/O 多路复用是一种同步 I/O 模型,实现一个线程可以监视多个 fd (文件描述符/文件句柄)
一旦某个 fd 就绪,就能够通知应用程序进行相应的读写操作 ...
Handler 原理探究
前言Handler 是什么
看看官方的解释:A Handler allows you to send and process Message and Runnable objects associated with a thread’s MessageQueue.Each Handler instance is associated with a single thread and that thread’s message queue. When you create a new Handler it is bound to a Looper.It will deliver messages and runnables to that Looper’s message queue and execute them on that Looper’s thread.
简单的来说:Handler 是一个消息处理者:可以向 Handler 发送 Message,这些 Message 会被 Looper 在对应的线程上执行。
Handler、Looper、MessageQueue 之间的关系
...
MessageBus 源码分析
前言MessageBus 类似于 EventBus,是一个消息总线框架,常用于处理跨模块通信问题。它基于订阅者模式实现,主要角色如下:
订阅者:在 MessageBus 中的订阅者是一个个被 Subscriber 注解标记的方法,被 Subscriber 标记的方法只能有一个参数:event。
订阅 class:含有被 Subscriber 注解标记方法的类,一个订阅者 class 可能有多个订阅者。订阅 class 需要通过 register 方法告诉调度中心它有哪些订阅者,否则订阅者就无法收到对应的 event。
调度中心:
接受订阅 class 的注册,将其中所有的订阅者存储起来
提供事件发送能力,并将事件通知给对应的订阅者
发布者:一般位于业务中,通过 MessageBus 发送指定的 event,使得订阅者可以执行
MessageBus初始化MessageBus 的作用决定了它的初始化方式,由于 MessageBus 需要在全局获得,所以它采用了双检锁单例模式。
12345678910public static MessageBus getInstance() ...
Lifecycle 源码分析
如何使用DefaultLifecycleObserver
注意:需要添加依赖才能生效,androidx.lifecycle:lifecycle-common-java8:xxx
12345678910111213141516class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) lifecycle.addObserver(DemoLifecycleObserver()) }}class DemoLifecycleObserver : DefaultLifecycleObserver { override fun onCreate(owner: LifecycleOwner) { ...
Glide 源码分析
前言Glide 是一个快速、高效的 Android 图片加载库,它提供了易用的 API,高性能、可扩展的图片解码管道以及自动的资源池技术。
Glide 的缓存术语:
Active 内存缓存:正在使用的图片对应的内存缓存
Cache 内存缓存:不在使用的图片对应的内存缓存
Data 磁盘缓存:原始数据对应的磁盘缓存
Resource 磁盘缓存:解码后数据对应的磁盘缓存
文档目录
Glide::with 源码分析
RequestManager::load 源码分析
RequestBuilder::into 源码分析
Engine::load 源码分析
DecodeHelper::getLoadData 源码分析
SourceGenerator::startNextLoad 源码分析
DecodeHelper::getLoadPath 源码分析
DecodeJob::decodeFromData 源码分析
Glide - 三级缓存
DiskLruCache 源码分析
Glide - 内存优化
基本使用1Glide.with(context).load(url) ...
Android Hook
本文只是粗略的介绍 Android Hook 和使用,不会涉及到原理方面
背景工作中遇到前辈们使用过的各种 Hook,所以这里就只是简单说说自己工作中遇到的哪些 Hook。
Android Hook 分类可以看这里:盘点Android常用Hook技术,本文重点讲述的是 Native Hook,更具体的说是其中的 PLT hook。
Native HookNative Hook 可以分为很多种,其中 PLT hook 和 Inline hook 是使用最广泛,并且相对来说通用性最强的两种方式。
PLT hook
原理针对某个函数整体进行 hook。修改调用方(caller)的导入表,或修改被调用方(callee)的导出表。以修改导入表为例:
找到被hook函数在调用方导入表中的位置。
修改该导入表项的值。同时备份原值。
使用方可以根据需要,通过上一步中备份的原值调用原函数。
难点对于某个目标函数,如何 hook 所有对它的调用。
优点稳定性好,hook 操作的执行速度快。可用于线上。
缺点
只能 hook 通过 PLT 执行的函数调用。
只能以函数为单位执行 hook,不能以指令 ...
链接、装载与库
本文是《程序员的自我修养—链接、装载与库》的读书笔记,内容基本和书中一致,最大的不同是书中的例子是 32 机器的,我替换成了 64 位机器的。
基础概念硬件
中央处理器 CPU
内存
I/O 控制芯片
计算机科学领域的任何问题都可以通过增加一个间接的中间层来解决
操作系统程序运行模式
多道程序:人们编写了一个监控程序,当某个程序无需使用 CPU 时,监控程序就把正在等待 CPU 资源的程序启动
分时系统:每个程序运行一段时间后都主动让出 CPU 给其它程序,使得一段时间内每个程序都有机会运行一小段时间
多任务系统:操作系统接管所有的硬件资源,本身运行在受硬件保护的级别。所有的应用程序都以进程的方式运行在比操作系统权限更低的级别,每个进程都有自己独立的地址空间,使得进程之间的地址空间相互隔离。CPU 由操作系统统一分配,每个进程根据优先级的高低都有机会得到 CPU,但是,如果运行超过一定的时间,操作系统就会暂停该线程,将 CPU 资源分配给其他等待运行的进程。(这种 CPU 分配方式称为抢占式)如果操作系统分配给每个进程的时间都很短,即 CPU 在多个进程之间快速切换,从而造成 ...
Android 混淆
主要摘自于公司内一个同事的分享
混淆是什么混淆是 “在 Android 项目进行打包时,将程序中的资源、代码以某种规则转换成功能上等价,但是难以阅读和理解的形式” 的行为。
混淆的作用
可以使得工程难以被逆向,增加反编译的成本,提升安全性
减小 Apk 的大小
混淆的分类
代码混淆
资源混淆
代码混淆Java 代码混淆ProGuard早期Android中一般使用 ProGuard 进行Java代码的混淆:
Java 编译器将源代码编译为 Java 字节码(.class)。ProGuard 可以选择优化此代码,从而生成更小,更快的 Java 字节码。dx 编译器最终可以将此 Java 字节码转换为 Dalvik 字节码(.dex)。 Dalvik 字节码打包在 apk 文件中,最终安装在设备上。
R8当使用 Android Gradle 插件 3.4.0 或更高版本编译项目时,该插件不再使用 ProGuard 执行编译时代码优化,而是使用 R8 编译器处理任务。
R8 是 D8 的衍生产品,旨在集成 ProGuard 和 D8(dx编译器的替代品) 的功能,一步到位地完成了所有的 ...
Gradle 基础知识
Gradle 相关概念基本概念
Gradle:Gradle 是个构建系统,能够简化你的编译、打包、测试,具体参考 官网
Gradle Wrapper:不同项目可能需要不同版本的 Gradle,手工部署麻烦且有可能冲突,使用 Gradle Wrapper 可以简化 Gradle 的安转和部署,具体参考 官网
Android Plugin for Gradle:它是一堆适合 Android 开发的 Gradle 插件集合,主要由 Google 的 Android 团队开发,具体参考 官网
gradle/wrapper每一个 Android 项目下都有一个 gradle/wrapper 目录,其中有两个文件:gradle-wrapper.jar、gradle-wrapper.properties,如上图所示。
gradle-wrapper.jar 包含了下载 Gradle distribution 的代码。Android Studio 安装过程中就会下载好该文件,之后每次新建项目,都会将该文件拷贝到项目的 gradle/wrapper 目录中。
gradle-wrapper.prope ...