目录
matrix做
arm能兼容v7,v8但是不能兼容
so库的崩溃是因为指令集不同,
splits {
abi {
enable true
reset()
include 'arm64-v8a','armeabi-v7a'
exclude 'armeabi'
universalApk true //是否打包一个包含所有so的apk
}
}
按照上图配置,会打3个包,分笔试v8a,v7a,以及包含全部so库的名叫universalApk的一个apk。
linker框架 + soloader做远端so的自动化的下载,用来兼容低版本的手机
so库的兼容性问题,不能向下兼容。
安卓中的R文件
红框表示资源ID(Identitify document),蓝框表示资源的值;绿框便是资源的类型。
public final class R { ...
public static final class string { ...
/**
* Description of the choose target button in a ShareActionProvider (share UI). [CHAR LIMIT=NONE]
*/
public static final int abc_shareactionprovider_share_with = 0x7f0a000c;
/**
* Description of a share target (both in the list of such or the default share button) in a ShareActionProvider (share UI). [CHAR LIMIT=NONE]
*/
public static final int abc_shareactionprovider_share_with_application = 0x7f0a000b;
public static final int action_settings = 0x7f0a000f;
public static final int app_name = 0x7f0a000d;
public static final int menu_home = 0x7f0a000e;
} ...
}
混淆的核心:
就是将Name压缩,将路径压缩。
比如上图中混淆之后就变成了
这个修改的原理就是,读取每一个字节,改成abcd之类的就行了。混淆的信息,将映射的名字简化了。
AndResGuard缩小包体积
AndResGuard的配置,对于apk体积帮助不大, 面试可以说一说这种方式。
andResGuard {
// 压缩文件
// mappingFile = file("./resource_mapping.txt")
mappingFile = null
// 手否签名。
use7zip = true
useSign = true
// 打开这个开关,会keep住所有资源的原始路径,只混淆资源的名字
keepRoot = false
// 设置这个值,会把arsc name列混淆成相同的名字,减少string常量池的大小
// fixedResName = "arg"
// 打开这个开关会合并所有哈希值相同的资源,但请不要过度依赖这个功能去除去冗余资源
mergeDuplicatedRes = true
// 白名单的资源都不能混淆。如果有反射调用的地方,需要进行添加到这里边。
whiteList = [
// for your icon
"R.drawable.ic_launcher",
"R.drawable.ic_launcher_round",
// for fabric
"R.string.com.crashlytics.*",
// for google-services
"R.string.google_app_id",
"R.string.gcm_defaultSenderId",
"R.string.default_web_client_id",
"R.string.ga_trackingId",
"R.string.firebase_database_url",
"R.string.google_api_key",
"R.string.google_crash_reporting_api_key"
]
// 压缩什么文件
compressFilePattern = [
"*.png",
"*.jpg",
"*.jpeg",
"*.gif",
]
// 压缩使用的工具。
sevenzip {
artifact = 'com.tencent.mm:SevenZip:1.2.19'
//path = "/usr/local/bin/7za"
}
/**
* 可选: 如果不设置则会默认覆盖assemble输出的apk
**/
// finalApkBackupPath = "${project.rootDir}/final.apk"
/**
* 可选: 指定v1签名时生成jar文件的摘要算法
* 默认值为“SHA-1”
**/
// digestalg = "SHA-256"
}
Android studio自带的Unused resource使用时需要小心,因为会移出反射调用的资源。
Matrix-ApkChecker分析Apk包
使用方式
调研-》看别人的代码-》优化-》自己输出。
matrix
动态加载的两种方案
(1)Linker + soloader(FB)
(2)Tinker,重要的一个类,TinkerLoaderLibrary#installNativeLibrary()//实现so动态加载,不用Tinker也能用。
下边是Tinker实现动态下载的简易结构图:
图讲解:将一个文件下载到sdcard,然后拷贝到应用内部的一个目录,之后调用Tinker的loaderLibrary实现so的加载。
系统加载so的路程:
(1)PMS把对应的so 拷贝到data/data/包名/lib
(2)app启动,so文件的路径会传递到BaseDexClassLoader,这个类里边有一个变量叫做DexpathList,里边有可以加载so库的方法;
(3)之后调用System.loadLibrary就可以了。
热修复一定要注意这个构造方法:
dalvik.system.DexPathList#DexPathList(ClassLoader, String)
/**
* Construct an instance.
*
* @param definingContext the context in which any as-yet unresolved
* classes should be defined
*
* @param dexFiles the bytebuffers containing the dex files that we should load classes from.
*/
public DexPathList(ClassLoader definingContext, String librarySearchPath) {
if (definingContext == null) {
throw new NullPointerException("definingContext == null");
}
this.definingContext = definingContext;
this.nativeLibraryDirectories = splitPaths(librarySearchPath, false);
this.systemNativeLibraryDirectories =
splitPaths(System.getProperty("java.library.path"), true);
this.nativeLibraryPathElements = makePathElements(getAllNativeLibraryDirectories());
}
Tinker的加载流程:
将我们自定义的so文件加载到 dalvik.system.DexPathList#nativeLibraryDirectories这个List集合中,这样子应用启动后就能够加载这些so文件了。
Tinker的核心代码: