官方文档

uni原生插件

uni原生插件指的是将您原生开发的功能按照规范封装成插件包,然后即可在 uni-app 前端项目中通过js调用您开发的原生能力。

SDK 包结构说明(版本3.1.2)

  1. |--iOSSDK
  2. |-- 5+app-uniplugin-demo // 在 uni-app 中按照 5+ App 规范开发插件工程
  3. |-- HBuilder-Hello // uni-app 或 5+ App 离线打包工程
  4. |-- HBuilder-Integrate // 5+ App 插件开发工程
  5. |-- HBuilder-uniPluginDemo // uni-app 插件开发主工程 (本文档需要使用的工程)
  6. |-- SDK // 依赖库及依赖资源文件
  7. |-- Feature-iOS.xls // 功能模块与依赖库对应关系说明表格
  8. |-- readme.txt // 目录说明

image.png

创建插件工程

image.png
image.png

1、生成插件位置最好放在 HBuilder-uniPluginDemo目录下,与其他插件平行。

image.png

2、进行插件工程配置

  • 然后选中工程名,在TARGETS->Build Settings中,将 Mach-O Type 设置为 Static Library 如下图所示

image.png
image.png

导入插件工程

1、打开 iOSSDK/HBuilder-uniPluginDemo工程目录,双击目录中的HBuilder-uniPlugin.xcodeproj 文件运行插件开发主工程

image.png

2、然后选择您刚刚创建的插件工程路径中,选中插件工程文件,勾选 Create folder referencesAdd to targets 两项,然后点击Add

image.png

3、导入效果

image.png

配置导入的插件工程

1、在 Xcode 项目左侧目录选中主工程名,在TARGETS->Build Phases->Dependencies中点击+

image.png

2、在Link Binary With Libraries 中添加库文件

image.png

3、引入开发所需的插件头文件

接下来需要在插件工程的Header Search Paths中添加开发插件所需的头文件引用,头文件存放在主工程的HBuilder-Hello/inc中,添加方法如下图所示,在 Xcode 项目左侧目录选中插件工程名,找到TARGETS->Build Settings->Header Search Paths双击右侧区域打开添加窗口,然后将inc目录拖入会自动填充相对路径,然后将模式改成recursive

插入.gif

代码实现

HBuilderX 3.0.5 版本开始, 推荐使用新的插件写法。 如果插件按照新写法,出现云打包报错, 请先确认HBuilderX版本在3.0.5或其以上。

参照官方文档


插件扩展方式

原生插件是基于 DCUniPlugin 规范来实现,扩展原生功能有两种方式:

  • module:不需要参与页面布局,只需要通过 API 调用原生功能,比如:获取当前定位信息、数据请求等功能,通过扩展module的方式来实现;
  • component:需要参与页面布局,比如:mapimage等需要显示UI的功能,通过扩展component即组件的方法来实现;

您需要根据实际的情况选择扩展方式,当然插件中可以同时存在 modulecomponent,也可以是多个 module 和 多个 component
特别注意 如果需要扩展自定义的 module 或者 component ,一定注意不要将 ocruntime 暴露给 JS ,不要将一些诸如 dlopen()dlsym()respondsToSelector:performSelector:method_exchangeImplementations() 的动态和不可控的方法暴露给JS,也不要将系统的私有API暴露给JS。否则将可能面临苹果上架审核问题。

Hook系统事件

如果需要在 App 启动时初始化或者需要获取系统的一些事件, 需要新建一个XXXXProxy类(注意命名加前缀防止冲突),继承 NSObject 遵守UniPluginProtocol协议

  1. -(void)onCreateUniPlugin;
  2. - (BOOL)application:(UIApplication *_Nullable)application didFinishLaunchingWithOptions:(NSDictionary *_Nullable)launchOptions;
  3. - (void)application:(UIApplication *_Nullable)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *_Nullable)deviceToken;
  4. - (void)application:(UIApplication *_Nullable)application didFailToRegisterForRemoteNotificationsWithError:(NSError *_Nullable)err;
  5. - (void)application:(UIApplication *_Nullable)application didReceiveRemoteNotification:(NSDictionary *_Nullable)userInfo;
  6. - (void)application:(UIApplication *_Nullable)application didReceiveLocalNotification:(UILocalNotification *_Nullable)notification;
  7. - (BOOL)application:(UIApplication *_Nullable)application handleOpenURL:(NSURL *_Nullable)url;
  8. - (BOOL)application:(UIApplication *_Nullable)app openURL:(NSURL *_Nonnull)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id> *_Nullable)options NS_AVAILABLE_IOS(9_0);
  9. - (void)applicationWillResignActive:(UIApplication *)application;
  10. - (void)applicationDidBecomeActive:(UIApplication *)application;
  11. - (void)applicationDidEnterBackground:(UIApplication *)application;
  12. - (void)applicationWillEnterForeground:(UIApplication *)application;
  13. - (BOOL)application:(UIApplication *_Nullable)application continueUserActivity:(NSUserActivity *_Nullable)userActivity restorationHandler:(void(^_Nullable)(NSArray * __nullable restorableObjects))restorationHandler API_AVAILABLE(ios(8.0));

Module 进阶

待完善

配置插件信息

插件信息配置很重要,在进行插件配置时进行过几次尝试均出现报错信息无法处理导致返工。

  1. <dict>
  2. <key>hooksClass</key>
  3. <string>填写 hooksClass 类名 </string>
  4. <key>plugins</key>
  5. <array>
  6. <dict>
  7. <key>class</key>
  8. <string>填写 module 或 component 的类名</string>
  9. <key>name</key>
  10. <string>填写暴露给js端对应的 module 或 component 名称</string>
  11. <key>type</key>
  12. <string>填写 module 或 component</string>
  13. </dict>
  14. </array>
  15. </dict>

配置说明

  • hooksClass:App系统方法钩子类,值是类名,是给有些插件需要在 app 启动时做初始化或者获取系统事件用的,如果没有可以不填为空
  • class:module 或 component 对应的原生类名(示例中为 TestModule
  • name:暴露给js端使用的 module 或 component 对应的名称(注意:module 的 name 必须以插件id为前缀或和插件id相同,示例为DCTestUniPlugin-TestModule其中 DCTestUniPlugin 为插件的id,需要保证唯一性,避免与其他插件冲突,component 的name 没有强制要求,但是也要保证唯一比如 dc-map
  • type:module 或 component (示例为module

image.png

  1. <script>
  2. // 首先需要通过 uni.requireNativePlugin("ModuleName") 获取 module
  3. var testModule = uni.requireNativePlugin("NETestUniPlugin-NETestModule")
  4. export default {
  5. data() {
  6. return {
  7. }
  8. },
  9. methods: {
  10. testAsyncFunc() {
  11. // 调用异步方法
  12. testModule.testAsyncFunc({
  13. 'name': 'uni-app',
  14. 'age': 1
  15. },
  16. (ret) => {
  17. uni.showToast({
  18. title:'custerm调用异步方法 ' + ret,
  19. icon: "none"
  20. })
  21. })
  22. },
  23. testSyncFunc() {
  24. // 调用同步方法
  25. var ret = testModule.testSyncFunc({
  26. 'name': 'uni-app',
  27. 'age': 1
  28. })
  29. uni.showToast({
  30. title:'custerm调用异步方法 ' + ret,
  31. icon: "none"
  32. })
  33. },
  34. }
  35. }
  36. </script>

导入uni-app资源

生成本地打包资源

image.png

替换或添加uni-app资源

  • 当APPID相同时将离线打包的资源对项目中的旧资源进行替换。
  • 也可在 Pandora-> apps 目录下存在多个不同APPID的资源文件。
  • 在control.xml中进行配置。

image.png

配置 control.xml文件

image.png

注意事项

1、生成本地资源并进行测试时最好将模拟器或真机上的项目进行卸载。

2、防止存在缓存信息导致无法达到预期效果。

简单实践成果

  • 在原SDK上添加了一个SDK,进行3个SDK的js调原生function测试。

插入.gif

添加插件方法

1、手动添加bugly.framework到工程进行hook 插件类中进行注册。(XCFramework 方式待完善)

想要添加项目的pod_framework到插件工程失败

image.png
image.png
image.png