Android Tinker 源码分析(五):加载so补丁流程

本系列 Tinker 源码解析基于 Tinker v1.9.12

校验so补丁流程

与加载资源补丁类似,加载so补丁也要先从校验开始看起。

其实总体来说,Tinker 中加载 so 补丁文件的关键代码就一句:

System.load(String filePath)

tryLoadPatchFilesInternal

1
2
3
4
5
6
7
8
9
10
11
final boolean isEnabledForNativeLib = ShareTinkerInternals.isTinkerEnabledForNativeLib(tinkerFlag);

if (isEnabledForNativeLib) {
//tinker/patch.info/patch-641e634c/lib
boolean libCheck = TinkerSoLoader.checkComplete(patchVersionDirectory, securityCheck, resultIntent);
if (!libCheck) {
//file not found, do not load patch
Log.w(TAG, "tryLoadPatchFiles:native lib check fail");
return;
}
}
阅读更多

Android Tinker源码分析(四):加载资源补丁流程

本系列 Tinker 源码解析基于 Tinker v1.9.12

加载资源补丁流程

将到资源补丁的加载,首先还要回过头来先看资源补丁的校验和检查。

我们回到 TinkerLoader.tryLoadPatchFilesInternal 方法中来看。

tryLoadPatchFilesInternal

1
2
3
4
5
6
7
8
9
10
11
//check resource
final boolean isEnabledForResource = ShareTinkerInternals.isTinkerEnabledForResource(tinkerFlag);
Log.w(TAG, "tryLoadPatchFiles:isEnabledForResource:" + isEnabledForResource);
if (isEnabledForResource) {
boolean resourceCheck = TinkerResourceLoader.checkComplete(app, patchVersionDirectory, securityCheck, resultIntent);
if (!resourceCheck) {
//file not found, do not load patch
Log.w(TAG, "tryLoadPatchFiles:resource check fail");
return;
}
}
阅读更多

Android Tinker源码分析(三):加载dex补丁流程

本系列 Tinker 源码解析基于 Tinker v1.9.12

加载dex补丁流程

TinkerDexLoader.loadTinkerJars

判断一下 dexList 和 classLoader

1
2
3
4
5
6
7
8
9
10
11
12
13
if (loadDexList.isEmpty() && classNDexInfo.isEmpty()) {
Log.w(TAG, "there is no dex to load");
return true;
}

PathClassLoader classLoader = (PathClassLoader) TinkerDexLoader.class.getClassLoader();
if (classLoader != null) {
Log.i(TAG, "classloader: " + classLoader.toString());
} else {
Log.e(TAG, "classloader is null");
ShareIntentUtil.setIntentReturnCode(intentResult, ShareConstants.ERROR_LOAD_PATCH_VERSION_DEX_CLASSLOADER_NULL);
return false;
}
阅读更多

Android Tinker源码分析(二):加载补丁流程

本系列 Tinker 源码解析基于 Tinker v1.9.12

利用反射执行的是 TinkerLoader.tryLoad 方法

tryLoad

1
2
3
4
5
6
7
8
9
10
@Override
public Intent tryLoad(TinkerApplication app) {
Intent resultIntent = new Intent();

long begin = SystemClock.elapsedRealtime();
tryLoadPatchFilesInternal(app, resultIntent);
long cost = SystemClock.elapsedRealtime() - begin;
ShareIntentUtil.setIntentPatchCostTime(resultIntent, cost);
return resultIntent;
}
阅读更多

Android Tinker 源码分析(一):TinkerApplication

本系列 Tinker 源码解析基于 Tinker v1.9.12

自动生成TinkerApplication

接入 Tinker 第一步就是改造 Application 。官方推荐是利用 @DefaultLifeCycle 动态生成 Application

1
2
3
4
5
@DefaultLifeCycle(application = "tinker.sample.android.app.SampleApplication",
flags = ShareConstants.TINKER_ENABLE_ALL,
loadVerifyFlag = false)
public class SampleApplicationLike extends DefaultApplicationLike {
}
阅读更多

Android 利用 AOP 对点击事件作防抖处理

Header

最近项目中有一个需求,需要对重复的点击事件作过滤处理。

可能第一个想到的方法是在 OnClickListener.onClick 中根据时间间隔来判断,这也是比较传统的方案。但是缺点同样也很明显,就是对现有代码的侵入性太强了。因为点击事件回调的代码我们早已写好了,现在再去改动会很痛苦,并且改动的范围也很广。

那么有没有一种方法是不需要改动源代码,就可以实现对点击事件去重的呢?当然有,我们可以利用 AOP 来实现一套方案。接下来就来讲讲这套方案就具体实现。

Body

在写代码之前,需要先设置 AOP 的配置,AOP 一般采用的是 AspectJ 。而在 Android 中一般直接使用 hugo 或者 gradle_plugin_android_aspectjx 插件,这样就省去了配置 AspectJ 的麻烦。在这里我使用的就是 gradle_plugin_android_aspectjx 插件,gradle_plugin_android_aspectjx 具体的配置就不详细展开了,可以自行去了解。

阅读更多

Android 使用 OpenCV 对图片进行二值化和去燥处理

最近做的项目中有使用到 OpenCV ,并且利用了 OpenCV 对图片做一些简单的处理。所以今天打算记录一下一些常用的 OpenCV 操作。

以下的 OpenCV 代码都是基于 OpenCV v3.3.0 aar 版本

二值化

所谓的二值化,就是将图片上的像素点的灰度值设置为0或255,也就是将整个图片呈现出明显的只有黑和白的视觉效果。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public static Bitmap binarization(Bitmap bitmap) {
// 创建一张新的bitmap
Bitmap result = Bitmap.createBitmap(bitmap.getWidth(), bitmap.getHeight(), Bitmap.Config.ARGB_8888);
Mat origin = new Mat();
Mat gray = new Mat();
Mat out = new Mat();
Utils.bitmapToMat(bitmap, origin);
Imgproc.cvtColor(origin, gray, Imgproc.COLOR_RGB2GRAY);
// 二值化处理
Imgproc.adaptiveThreshold(gray, out, 255.0D, Imgproc.ADAPTIVE_THRESH_MEAN_C, Imgproc.THRESH_BINARY, 25, 10.0D);
Utils.matToBitmap(out, result);
origin.release();
gray.release();
out.release();
return result;
}
阅读更多

Android ARouter 源码解析(五)

arouter-gradle-plugin version : 1.0.2

AutoRegister : https://github.com/luckybilly/AutoRegister

前言

在本系列的第一篇中讲过,ARouter 可以通过扫描 dex 文件中 class 的全类名,来加载 compiler 生成的路由类。但这种方式影响性能,并且效率也不高。所以在 ARouter v1.3.0 之后的版本中,加入了自动注册的方式进行路由表的加载,自动注册可以缩短初始化时间,解决应用加固导致无法直接访问 dex 文件从而初始化失败的问题。

阅读更多

Android ARouter 源码解析(四)

arouter-compiler version : 1.2.2

前言

之前对 arouter-api 做了整个流程的分析,今天来看看 arouter-compiler 。

arouter-compiler 主要是利用 apt 在编译期自动生成代码的。之前我们看到的 ARouter$$Root$$appARouter$$Group$$testTest1Activity$$ARouter$$Autowired 等都是 arouter-compiler 生成的。

阅读更多

Android ARouter 源码解析(三)

arouter-api version : 1.4.1

前言

到现在为止,ARouter 还有最后的依赖注入还没有解析过,那么今天就来深入探究一下其实现原理。

PS : 因为依赖注入的原理还比较简单,所以本篇篇幅会较短。

@Autowired解析

想要用 ARouter 实现依赖注入,需要在 Activity/Fragment 中加上

阅读更多