一种鸿蒙与Android资源混编的思路

背景

由于鸿蒙现有的 Api 相对于 Android 而言仍需要完善,如三方控件、SurfaceView 或触摸事件分发等,因此完全使用鸿蒙提供的 Api 无法完成某些功能需求。因此,需要寻求一种 Android 与鸿蒙资源混编的方式。

难点

鸿蒙的应用安装包解压之后的结构如下所示


image.png

image.png

由于鸿蒙拥有自己的一套资源解析方式,因此无法正常导入和使用第三方 aar 中的资源,也无法进行 Manifest.xml 文件与 config.json 文件的合并。因此若要正常导入第三方 aar ,需要解决如下问题

  1. 如何合并 Android 与鸿蒙的资源文件。
  2. 如何合并 Android Manifest.xml 与鸿蒙的 config.json 文件。
  3. Android 的 Activity 与鸿蒙的 Ability 如何互相跳转。

实现

资源

Android 中的资源查找方式是在编译时生成 R.java 文件和 arsc 文件,运行时通过 R 文件中对应的资源整型值到 arsc 文件中查找对应资源文件的路径(图片或layout文件等)或者实际内容(string或color等)。
鸿蒙中的资源查找方式是在编译时生成了ResourceTable.java 和 resource.index 文件,作用和功能类似。
我们知道鸿蒙应用本质上是一个 Android 应用,其在编译过程中势必会需要编译生成一个 Android Apk,因此可以尝试找到其路径和对应的 gradle task,hook之,修改相应的 manifest.xml 或其他资源文件

image.png

可以看到在 build/intermediates/debug/shell 目录下对应的是 Android 应用工程的资源目录结构,我们可以在此目录下做 manifest.xml 、类或者资源的修改合并等。
现在尝试找到编译 Android Apk 对应的 gradle task。
运行 gradle tasks --all 获取所有的 task,搜索 shell 相关的 task
image.png

看上去在 processDebugShellManifest 之后就已经开始给最终产物 .hap 包签名了,尝试 hook 一把这个 task ,在执行完这个 task 后判断 build/intermediates/shell_output/debug 下是否已经生成相应的 apk 文件。
image.png

project.afterEvaluate(new Action() {
    @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);
    }

你可能感兴趣的:(一种鸿蒙与Android资源混编的思路)