# 鸿蒙混合打包 **Repository Path**: zhang-yanqiang/ohos-mixed-packing ## Basic Information - **Project Name**: 鸿蒙混合打包 - **Description**: 鸿蒙混合打包。在现有安卓应用的基础上扩展鸿蒙的特性,以最快的速度布局鸿蒙生态! - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: master - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 3 - **Created**: 2021-07-20 - **Last Updated**: 2021-07-20 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # 鸿蒙混合打包 #### 介绍 鸿蒙混合打包。在现有安卓应用的基础上扩展鸿蒙的特性,以最快的速度布局鸿蒙生态! 参考:[京东APP鸿蒙版上架实践](https://mp.weixin.qq.com/s/v4jT-DHk5opb2wEqwQzV0w)。本项目只是这篇文章的一个验证,让更多的兄弟们可以少走弯路。 我尽可能把每一步的改动作为一个commit,这样方便大家看代码。 #### 开发步骤 1. 准备Android工程 > 本示例中,我用AS建了一个Hello World工程。 2. Android工程改造 > 请参考[京东APP鸿蒙版上架实践](https://mp.weixin.qq.com/s/v4jT-DHk5opb2wEqwQzV0w)。 > > 这一步,有两点要注意的: > 1. `abilityshell_ide_java.jar`在这里,自行copy到安卓工程中 ![](./raw/img01.png) > 1. 注意apk文件名必须是 `xxx-entry.apk`这种格式 > 3. 准备鸿蒙工程 > 本示例中,我用DevEco Studio建了一个Hello World工程。 ![](./raw/img02.jpg) 4. 配置鸿蒙工程 > 请参考[京东APP鸿蒙版上架实践](https://mp.weixin.qq.com/s/v4jT-DHk5opb2wEqwQzV0w)。 > > 这一步,有三点要注意的: > > 1. 签名就不要转了,直接重新创建,只要**秘钥和别名**和Android的保持不变。(如果在模拟器上运行,不配置签名也能跑起来) > > 2. 鸿蒙的version 和apk的version要一致 > > 3. config.json的app节点下,增加`relatedBundleName`而不是`originalName`。 > > config.json里都支持哪些字段,没必要看文档,只要按住ctrl点击相应的字段,就可以看到,比如点击app字段。 ![](./raw/img03.jpg) 5. 卡片 > 本示例中,我用DevEco Studio建了一个名为mycard的module ,并且勾选"show in service center",这样这个卡片就可以显示在"服务中心"了。![](./raw/img04.jpg) > > 有几点需要说明: > > 1. **必须签名**(我的验证结果是这样的),所以要有真机。我提交的签名文件是绑定我的机器,所以你要更新自己的签名文件。 > 2. 卡片的config.json的`app`字段要和entry的`app`字段**完全一致**(`relatedBundleName`字段只在entry里有就可以,卡片里不写也行) > 3. 多module的工程,运行的时候要勾选`Deploy Multi Hap Packages`![](./raw/img05.jpg) > 4. 为什么把卡片放在独立的module里?因为混合打包下,entry只是一个壳,我们可以把entry当作apk的占位,所以entry里的内容都不会打到appj里,鸿蒙相关的功能代码我们只能放在独立的module中。(当然,**这也是我的验证结果**,最终要等华为官方更明确的文档解释) 6. 鸿蒙打开apk中的activity > 请参考[京东APP鸿蒙版上架实践](https://mp.weixin.qq.com/s/v4jT-DHk5opb2wEqwQzV0w)。 > 7. 鸿蒙打开apk中的activity,并传递参数 - 鸿蒙`IntentParams`对应安卓`Bundle`,相应的api ```java //ohos put: IntentParams params = new IntentParams(); params.setParam("androidFile1","androidFile1----"); intent.setParams(params); //android put: Intent intent = new Intent(); intent.putExtra("androidFile1","androidFile1----"); //get: intent.getStringExtra("androidFile1"); //ohos put: Set entities = new HashSet<>(); entities.add("entity.user.c1"); ``` - 鸿蒙`Uri`对应安卓`Uri`,鸿蒙`Entity`对应安卓`Category`,相应的api ```java //ohos put: Operation operation = new Intent.OperationBuilder() .withUri(Uri.parse("https://www.baidu.com")) .withEntities(entities) .build(); //android put: Intent intent = new Intent(); intent.setData(Uri.parse("https://www.baidu.com")); intent.addCategory("entity.user.c1"); //get: intent.getData(); intent.getCategories(); ``` 8. 安卓打开鸿蒙中的ability,并传递参数 - 核心代码: ```java Intent intent = new Intent(); //CardAbility有对应的代理类CardAbilityShellActivity,我们可以这样理解。 ComponentName componentName = new ComponentName("wang.unclecat.hello","wang.unclecat.mycard.CardAbilityShellActivity"); intent.putExtra("msg","鸿蒙哥哥,我是安卓"); intent.setComponent(componentName); startActivity(intent); ``` - 原理:鸿蒙工程在编译期,Ability会生成相应的代理类XXXShellActivity。如下图所示。我们只要访问这个代理Activity,就可以在apk中访问相应的Ability了。 > 以上都只是猜测,试过之后,还真的可行。 ![](./raw/img06.jpg) ![](./raw/img06-1.jpg) 9. 创建鸿蒙ServiceAbility > 用ide生成,没什么好说的 10. 把ServiceAbility设置为前台Service > 请参考:[官方文档](https://developer.harmonyos.com/cn/docs/documentation/doc-guides/ability-service-foreground-0000000000044473) 11. 安卓向鸿蒙ServiceAbility发数据 > 有了启动Page Ablility的经验,同理我们创建一个Service Ablility,在build目录中编译器同样生成了相应的代理类`ServiceAbilityShellService`。再次大胆猜想一下,你会惊奇地发现,一样可行。 - 核心代码: ```java //建立连接 Intent intent = new Intent(); ComponentName componentName = new ComponentName("wang.unclecat.hello","wang.unclecat.mycard.ServiceAbilityShellService"); intent.setComponent(componentName); bindService(intent, connection, Context.BIND_AUTO_CREATE); //发送 Parcel data = Parcel.obtain(); Parcel reply = Parcel.obtain(); data.writeString("time:"+new Date().getTime()); try { serviceBinder.transact(2, data, reply, IBinder.FLAG_ONEWAY); } catch (RemoteException e) { e.printStackTrace(); } ``` #### 最终效果 ![](./raw/tutieshi_320x694_9s.gif)