背景
由于鸿蒙现有的 Api 相对于 Android 而言仍需要完善,如三方控件、SurfaceView 或触摸事件分发等,因此完全使用鸿蒙提供的 Api 无法完成某些功能需求。因此,需要寻求一种 Android 与鸿蒙资源混编的方式。
难点
鸿蒙的应用安装包解压之后的结构如下所示


由于鸿蒙拥有自己的一套资源解析方式,因此无法正常导入和使用第三方 aar 中的资源,也无法进行 Manifest.xml 文件与 config.json 文件的合并。因此若要正常导入第三方 aar ,需要解决如下问题
- 如何合并 Android 与鸿蒙的资源文件。
- 如何合并 Android Manifest.xml 与鸿蒙的 config.json 文件。
- Android 的 Activity 与鸿蒙的 Ability 如何互相跳转。
实现
资源
Android 中的资源查找方式是在编译时生成 R.java 文件和 arsc 文件,运行时通过 R 文件中对应的资源整型值到 arsc 文件中查找对应资源文件的路径(图片或layout文件等)或者实际内容(string或color等)。
鸿蒙中的资源查找方式是在编译时生成了ResourceTable.java 和 resource.index 文件,作用和功能类似。
而我们知道鸿蒙应用本质上是一个 Android 应用,其在编译过程中势必会需要编译生成一个 Android Apk,因此可以尝试找到其路径和对应的 gradle task,hook之,修改相应的 manifest.xml 或其他资源文件。

可以看到在 build/intermediates/debug/shell 目录下对应的是 Android 应用工程的资源目录结构,我们可以在此目录下做 manifest.xml 、类或者资源的修改合并等。
现在尝试找到编译 Android Apk 对应的 gradle task。
运行
gradle tasks --all
获取所有的 task,搜索 shell 相关的 task
看上去在 processDebugShellManifest 之后就已经开始给最终产物 .hap 包签名了,尝试 hook 一把这个 task ,在执行完这个 task 后判断 build/intermediates/shell_output/debug 下是否已经生成相应的 apk 文件。

project.afterEvaluate(new Action<Project>() {
@Override
void execute(Project p) {
p.tasks.findByName("processDebugShellManifest ").doLast {
//做资源文件和类以及 manifest 文件的修改
...
}
}
})
Activity 与 Ability 相互跳转
我们知道鸿蒙的 Ability 在编译时最终都会生成对应的四大组件。
Ability 跳转 Activity
public static Application getAndroidApp() {
return Reflect.on("android.app.ActivityThread").call("currentApplication").get();
}
public static viod skipToActivity(Context context,Intent intent) {
intent.setFlag(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent);
}
Activity 跳转 Ability
public void skipAbility() {
Intent getIntent = new Intent();
Operation opt = new Intent
.OperationBuilder()
.withBundleName(getBundleName())
.withAbilityName(SecondAbility.class.getName())
.build();
getIntent.setOperation(opt);
getIntent.setFlag(android.content.Intent.FLAG_ACTIVITY_NEW_TASK);
startAbility(getIntent);
}
网友评论