自定义终端模块

很多时候 JS 需要访问对应终端的一些能力模块,比如数据库、下载、网络请求等,这时候就需要使用 Module 来暴露接口给JS使用。Hippy SDK 中默认实现了部分 Module,但这极有可能无法满足你的需求,这就需要你对 Module 进行扩展封装。

Module扩展

我们将以 TestModule 为例,从头扩展一个 Module,这个 Module 将展示前端如何调用终端能力,并且把结果返回给前端。

终端扩展Module包括四步:

  1. 创建 HippyNativeModuleBase 的子类。
  2. 添加 HippyNativeModule 注解。
  3. 实现导出给 JS 的方法。
  4. 注册 Module。

创建HippyNativeModuleBase的子类

首先我们需要创建TestModule类,并且继承HippyNativeModuleBase

  1. package com.tencent.mtt.hippy.example.modules;
  2. import com.tencent.mtt.hippy.HippyEngineContext;
  3. import com.tencent.mtt.hippy.modules.nativemodules.HippyNativeModuleBase;
  4. public class TestModule extends HippyNativeModuleBase
  5. {
  6. public LogModule(HippyEngineContext context)
  7. {
  8. super(context);
  9. }
  10. }

添加HippyNativeModule注解

HippyNativeModuleBase 要求增加注解 @HippyNativeModule

HippyNativeModule有两个注解参数:

  • name:能力名称,js调用时需要通过此访问该能力。
  • thread:能力运行的线程。包括 HippyNativeModule.Thread.DOM(Dom线程)、HippyNativeModule.Thread.MAIN(主线程)、HippyNativeModule.Thread.BRIDGE(Bridge线程、默认值)。
  1. @HippyNativeModule(name = "TestModule", thread = HippyNativeModule.Thread.BRIDGE)
  2. public class TestModule extends HippyNativeModuleBase
  3. {
  4. ...
  5. }

3. 实现导出给JS的方法

导出给 JS 使用的方法,必须使用注解 @HippyMethod ,方法必须为 public 类型,返回类型必须为 void

支持的方法参数类型包括:

  • Java基本数据类型。
  • HippyArray:类似于ArrayList,线程非安全。
  • HippyMap:类似于HashMap,线程非安全。
  • Promise:回调JS的触发器,通过 resolve 方法返回成功信息给JS。通过 reject 方法返回失败实现给JS。
  1. @HippyMethod(name="log")
  2. public void log(String msg)
  3. {
  4. Log.d("TestModule", msg);
  5. }
  6. @HippyMethod(name="helloNative")
  7. public void helloNative(HippyMap hippyMap)
  8. {
  9. String hello = hippyMap.getString("hello");
  10. Log.d("TestModule", hello);
  11. }
  12. @HippyMethod(name = "helloNativeWithPromise")
  13. public void helloNativeWithPromise(HippyMap hippyMap, Promise promise)
  14. {
  15. // 这里回来的参数可以为java的基础类型,和hippymap与hippyarry, 但是前端调用的时候必须对应上
  16. String hello = hippyMap.getString("hello");
  17. Log.d("TestModule", hello);
  18. if (true)
  19. {
  20. // TODO 如果模块这里处理成功回调resolve
  21. HippyMap hippyMap1 = new HippyMap();
  22. hippyMap1.pushInt("code", 1);
  23. hippyMap1.pushString("result", "hello i am from native");
  24. promise.resolve(hippyMap1);
  25. }
  26. else
  27. {
  28. // 失败就回调reject
  29. HippyMap hippyMap1 = new HippyMap();
  30. hippyMap1.pushInt("code", -1);
  31. promise.reject(hippyMap1);
  32. }
  33. }

4. 注册Module

然后需要注册这个Module。需要在 HippyPackagegetNativeModules 方法中添加这个 Module,这样它才能在JS中被访问到。

  1. import com.tencent.mtt.hippy.HippyEngineContext;
  2. import com.tencent.mtt.hippy.HippyPackage;
  3. import com.tencent.mtt.hippy.common.Provider;
  4. import com.tencent.mtt.hippy.example.module.TestModule;
  5. import com.tencent.mtt.hippy.modules.javascriptmodules.HippyJavaScriptModule;
  6. import com.tencent.mtt.hippy.modules.nativemodules.HippyNativeModuleBase;
  7. import com.tencent.mtt.hippy.uimanager.HippyViewController;
  8. import java.util.HashMap;
  9. import java.util.List;
  10. import java.util.Map;
  11. public class ExamplePackages implements HippyPackage
  12. {
  13. @Override
  14. public Map<Class<? extends HippyNativeModuleBase>, Provider<? extends HippyNativeModuleBase>> getNativeModules(final HippyEngineContext context)
  15. {
  16. Map<Class<? extends HippyNativeModuleBase>, Provider<? extends HippyNativeModuleBase>> modules = new HashMap<>();
  17. // regist the LogModule
  18. modules.put(ToastModule.class, new Provider<HippyNativeModuleBase>()
  19. {
  20. @Override
  21. public HippyNativeModuleBase get()
  22. {
  23. return new TestModule(context);
  24. }
  25. });
  26. return modules;
  27. }

注意事项

扩展Module中不能同步执行耗时操作,这可能卡住整个引擎通信线程。存在耗时场景,请使用异步线程处理。

混淆说明

扩展 Module 的类名和扩展方法方法名不能混淆,可以增加混淆例外。

  1. -keep class * extends com.tencent.mtt.hippy.modules.nativemodules.HippyNativeModuleBase{ public *;}