diff --git a/docs/NativePlugin/course/android.md b/docs/NativePlugin/course/android.md
index 6ce4c73009a4d8f952f12fcc35e8b31b37f34822..7c16c71e7e806934c9394b62f01c88cf21824746 100644
--- a/docs/NativePlugin/course/android.md
+++ b/docs/NativePlugin/course/android.md
@@ -1,809 +1,809 @@
-## 开发者须知
-在您阅读此文档时,我们假定您已经具备了相应Android应用开发经验,使用Android Studio开发过Android原生。也应该对HTML,JavaScript,CSS等有一定的了解, 并且熟悉在JavaScript和JAVA环境下的JSON格式数据操作等。
-
-**为了插件开发者更方便快捷的开发uni原生插件!2.9.8版本起修改了uni插件开发API及规范。当然还会继续兼容老的插件运行及开发。推荐插件开发者按新版规范实现开发插件。方便日后更高效的更新迭代uni原生插件!**
-
-## 开发环境
-- JAVA环境 jdk1.8
-- Android Studio 下载地址:[Android Studio官网](https://developer.android.google.cn/studio/index.html) OR [Android Studio中文社区](http://www.android-studio.org/)
-- App离线SDK下载:请下载2.9.8+版本的[android平台SDK](/AppDocs/download/android.md)
-- HBuilderX 下载地址:[官方下载地址](https://www.dcloud.io/hbuilderx.html)
-
+## 开发者须知
+在您阅读此文档时,我们假定您已经具备了相应Android应用开发经验,使用Android Studio开发过Android原生。也应该对HTML,JavaScript,CSS等有一定的了解, 并且熟悉在JavaScript和JAVA环境下的JSON格式数据操作等。
+
+**为了插件开发者更方便快捷的开发uni原生插件!2.9.8版本起修改了uni插件开发API及规范。当然还会继续兼容老的插件运行及开发。推荐插件开发者按新版规范实现开发插件。方便日后更高效的更新迭代uni原生插件!**
+
+## 开发环境
+- JAVA环境 jdk1.8
+- Android Studio 下载地址:[Android Studio官网](https://developer.android.google.cn/studio/index.html) OR [Android Studio中文社区](http://www.android-studio.org/)
+- App离线SDK下载:请下载2.9.8+版本的[android平台SDK](/AppDocs/download/android.md)
+- HBuilderX 下载地址:[官方下载地址](https://www.dcloud.io/hbuilderx.html)
+
#### 版本升级注意
-- 最新注意事项 `HX3.8.7+版本开始 androidx适配库升级为1.1.0 还在使用support/v4老版本适配的插件同学请尽快升级适配androidx 避免打包机环境不支持导致的编译失败或闪退`
-- **gradle版本注意事项**
- + HX3.0.0+版本云打包及相应版本SDK都将gradle版本4.6-all升级到6.5-all,tools.build:gradle版本3.2.1升级到4.1.1。
- - 修复部分SDK集成后编译打包失败问题
- - 适配android11的编译新特性。
- - 修复tools.build:gradle:3.2.1版本编译检测是否需要AndroidX依赖库不准确问题。**如果您的插件在HX3.0.0+版本编译报错需要AndroidX依赖库。那证明您之前集成的SDK是需要AndroidX的。请配置useAndroidX。**具体可查看[package.json](NativePlugin/course/package)
- - 如果您下载的SDK是3.0.0+版本请将本地gradle版本升级到6.5-all,tools.build:gradle版本升级到4.1.1。防止编译报错等问题。如果遇到编译内存不足可能是关闭了R8混淆导致 需要开启。
- - **tools.build:gradle:4.1.1版本编译器可能无法适配老的插件原生编译。会导致之前的插件可能无法正常编译通过或编译完成apk无法正常使用!需要插件开发者尽快适配4.1.1的编译环境。**
-- **Activity变更为FragmentActivity注意事项**
- + HX3.0.7版本云打包及相应版本SDK开始将`Activity`变更为`FragmentActivity`.解决部分插件开发者需要加载Fragment的需求。但也带来了一些代码与之前不同的修改。需要注意以下问题:
- - requestPermissions需要限制requestCode的值域,之前`Activity`没有限制requestCode的值域。`FragmentActivity`的权限申请限制requestCode的值域不能为负值,也不能大于16位bit值65536。否则报异常或崩溃`Can only use lower 16 bits for requestCode`,强烈推荐使用0~60500之间取值。
-- **HX3.1.6+开始 集成SDK需要将compileSdkVersion调高至29+**
-- **HX3.1.10版本起需要申请 Appkey(dcloud_appkey),否则无法正常运行uniapp并调试插件,申请[参考](/AppDocs/usesdk/appkey.md)**
-- **HX3.2.5+版本开始改为Androidx依赖库。需注意!!项目需要默认配置useAndroidX=true**
-- **HX3.2.13+版本开始 默认targetSdkVersion将由26改为28 插件开发者同学们需要注意!!如果你的插件不支持targetSdkVersion=28需要告知插件使用者!!21-11-19 更新**
-- **HX3.8.7+版本开始 androidx适配库升级为1.1.0 还在使用support/v4老版本适配的插件同学请尽快升级适配androidx 避免打包机环境不支持导致的编译失败或闪退**
-## 导入uni插件原生项目
-
-- UniPlugin-Hello-AS工程请在[App离线SDK](/AppDocs/download/android.md)中查找
-- 点击Android Studio菜单选项File--->New--->Import Project。
-
-
-
-- 导入选择UniPlugin-Hello-AS工程,点击OK! 等待工程导入完毕。
-
-
-
-- 如果出现Android SDK路径不对问题,请在Android Studio中鼠标右键UniPlugin-Hello-AS选择Open Module Settings, 在SDK Location 中设置相关环境路径
-
-
-
-
-
-
-## 插件开发
-
-可以根据自己的业务进行定制自己的功能。 主要分为两类扩展:
-
-+ Module 扩展 非 UI 的特定功能.
-
-+ Component 扩展 实现特别功能的 Native 控件.
-
-**Tips**
-
-- 特别注意uni-app插件目前仅支持Module扩展和Component扩展,暂时不支持Adapter扩展!!!
-
-### 扩展 Module
-
-- Module 扩展 非 UI 的特定功能
-- Module 不支持代码通过 new Module的方式创建对象。无法正常使用!
-
-下面以TestModule为例,源码请查看 UniPlugin-Hello-AS(2.9.8+)工程中的`uniplugin_module`模块;
-
-#### 创建Android Studio的Module模块
-
-- 在现有Android项目中创建library的Module。例如`uniplugin_module`
-- 配置刚创建的Module的build.gradle信息。
-
-**示例:**
-
-```
-//导入aar需要的配置
-repositories {
- flatDir {
- dirs 'libs'
- }
-}
-dependencies {
- //必须添加的依赖
- compileOnly 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0',
- compileOnly 'androidx.core:core:1.1.0'
+- 最新注意事项 `HX3.8.7+版本开始 androidx适配库升级为1.1.0 还在使用support/v4老版本适配的插件同学请尽快升级适配androidx 避免打包机环境不支持导致的编译失败或闪退`
+- **gradle版本注意事项**
+ + HX3.0.0+版本云打包及相应版本SDK都将gradle版本4.6-all升级到6.5-all,tools.build:gradle版本3.2.1升级到4.1.1。
+ - 修复部分SDK集成后编译打包失败问题
+ - 适配android11的编译新特性。
+ - 修复tools.build:gradle:3.2.1版本编译检测是否需要AndroidX依赖库不准确问题。**如果您的插件在HX3.0.0+版本编译报错需要AndroidX依赖库。那证明您之前集成的SDK是需要AndroidX的。请配置useAndroidX。**具体可查看[package.json](NativePlugin/course/package)
+ - 如果您下载的SDK是3.0.0+版本请将本地gradle版本升级到6.5-all,tools.build:gradle版本升级到4.1.1。防止编译报错等问题。如果遇到编译内存不足可能是关闭了R8混淆导致 需要开启。
+ - **tools.build:gradle:4.1.1版本编译器可能无法适配老的插件原生编译。会导致之前的插件可能无法正常编译通过或编译完成apk无法正常使用!需要插件开发者尽快适配4.1.1的编译环境。**
+- **Activity变更为FragmentActivity注意事项**
+ + HX3.0.7版本云打包及相应版本SDK开始将`Activity`变更为`FragmentActivity`.解决部分插件开发者需要加载Fragment的需求。但也带来了一些代码与之前不同的修改。需要注意以下问题:
+ - requestPermissions需要限制requestCode的值域,之前`Activity`没有限制requestCode的值域。`FragmentActivity`的权限申请限制requestCode的值域不能为负值,也不能大于16位bit值65536。否则报异常或崩溃`Can only use lower 16 bits for requestCode`,强烈推荐使用0~60500之间取值。
+- **HX3.1.6+开始 集成SDK需要将compileSdkVersion调高至29+**
+- **HX3.1.10版本起需要申请 Appkey(dcloud_appkey),否则无法正常运行uniapp并调试插件,申请[参考](/AppDocs/usesdk/appkey.md)**
+- **HX3.2.5+版本开始改为Androidx依赖库。需注意!!项目需要默认配置useAndroidX=true**
+- **HX3.2.13+版本开始 默认targetSdkVersion将由26改为28 插件开发者同学们需要注意!!如果你的插件不支持targetSdkVersion=28需要告知插件使用者!!21-11-19 更新**
+- **HX3.8.7+版本开始 androidx适配库升级为1.1.0 还在使用support/v4老版本适配的插件同学请尽快升级适配androidx 避免打包机环境不支持导致的编译失败或闪退**
+## 导入uni插件原生项目
+
+- UniPlugin-Hello-AS工程请在[App离线SDK](/AppDocs/download/android.md)中查找
+- 点击Android Studio菜单选项File--->New--->Import Project。
+
+
+
+- 导入选择UniPlugin-Hello-AS工程,点击OK! 等待工程导入完毕。
+
+
+
+- 如果出现Android SDK路径不对问题,请在Android Studio中鼠标右键UniPlugin-Hello-AS选择Open Module Settings, 在SDK Location 中设置相关环境路径
+
+
+
+
+
+
+## 插件开发
+
+可以根据自己的业务进行定制自己的功能。 主要分为两类扩展:
+
++ Module 扩展 非 UI 的特定功能.
+
++ Component 扩展 实现特别功能的 Native 控件.
+
+**Tips**
+
+- 特别注意uni-app插件目前仅支持Module扩展和Component扩展,暂时不支持Adapter扩展!!!
+
+### 扩展 Module
+
+- Module 扩展 非 UI 的特定功能
+- Module 不支持代码通过 new Module的方式创建对象。无法正常使用!
+
+下面以TestModule为例,源码请查看 UniPlugin-Hello-AS(2.9.8+)工程中的`uniplugin_module`模块;
+
+#### 创建Android Studio的Module模块
+
+- 在现有Android项目中创建library的Module。例如`uniplugin_module`
+- 配置刚创建的Module的build.gradle信息。
+
+**示例:**
+
+```
+//导入aar需要的配置
+repositories {
+ flatDir {
+ dirs 'libs'
+ }
+}
+dependencies {
+ //必须添加的依赖
+ compileOnly 'androidx.localbroadcastmanager:localbroadcastmanager:1.0.0'
+ compileOnly 'androidx.core:core:1.1.0'
compileOnly 'androidx.fragment:fragment:1.1.0'
compileOnly 'androidx.appcompat:appcompat:1.1.0'
- compileOnly 'androidx.recyclerview:recyclerview:1.1.0'
- compileOnly 'com.alibaba:fastjson:1.2.83'
-
- compileOnly fileTree(include: ['uniapp-v8-release.aar'], dir: '../app/libs')
-}
-```
-
-**Tips:**
-
-uniapp-v8-release.aar是扩展module主要依赖库,必须导入此依赖库!
-
-#### 创建TestModule类
-
-- Module 扩展必须继承 UniModule 类
-
-**示例:**
-
-```JAVA
-public class TestModule extends UniModule
-```
-
-- 扩展方法必须加上@UniJSMethod (uiThread = false or true) 注解。UniApp 会根据注解来判断当前方法是否要运行在 UI 线程,和当前方法是否是扩展方法。
-- UniApp是根据反射来进行调用 Module 扩展方法,所以Module中的扩展方法必须是 public 类型。
-
-**示例:**
-
-```JAVA
-//run ui thread
-@UniJSMethod(uiThread = true)
-public void testAsyncFunc(JSONObject options, UniJSCallback callback) {
- Log.e(TAG, "testAsyncFunc--"+options);
- if(callback != null) {
- JSONObject data = new JSONObject();
- data.put("code", "success");
- callback.invoke(data);
- }
-}
-
-//run JS thread
-@UniJSMethod (uiThread = false)
-public JSONObject testSyncFunc(){
- JSONObject data = new JSONObject();
- data.put("code", "success");
- return data;
-}
-```
-
-- 同样因为是通过反射调用,Module 不能被混淆。请在混淆文件中添加代码:
-
-```
--keep public class * extends io.dcloud.feature.uniapp.common.UniModule{*;}
-```
-
-- Module 扩展的方法可以使用 int, double, float, String, Map, List ,com.alibaba.fastjson.JSONObject 类型的参数
-
-### 扩展组件 Component
-
-- Component 扩展 实现特别功能的 Native 控件
-- Component 不支持代码中 new Component 创建对象。无法正常使用!
-
-下面以`TestComponent`为例,源码请查看 UniPlugin-Hello-AS(2.9.8+)工程中的`uniplugin_component`模块;
-
-#### 创建Android Studio的Module模块
-
-请参考 [扩展 Module](/NativePlugin/course/android?id=创建android-studio的module模块)
-
-#### 创建TestComponent类
-
-- Component 扩展类必须继承 UniComponent, 父容器Component(例如ViewGroup组件)则需要继承UniVContainer
-
-**示例:**
-
-```JAVA
-public class TestText extends UniComponent
-```
-- UniComponent的initComponentHostView回调函数。构建Component的view时会触发此回调函数。
-
-**示例:**
-
-```JAVA
-@Override
-protected TextView initComponentHostView(@NonNull Context context) {
- TextView textView = new TextView(context);
- textView.setTextSize(20);
- textView.setTextColor(Color.BLACK);
- return textView;
-}
-```
-
-- Component 对应的设置属性的方法必须添加注解 @UniComponentProp(name=value(value is attr or style of dsl))
-
-**示例:**
-
-```JAVA
-@UniComponentProp(name = "tel")
-public void setTel(String telNumber) {
- getHostView().setText("tel: " + telNumber);
-}
-```
-- UniApp sdk 通过反射调用对应的方法,所以 Component 对应的属性方法必须是 public,并且不能被混淆。请在混淆文件中添加代码
-```
--keep public class * extends io.dcloud.feature.uniapp.ui.component.UniComponent{*;}
-```
-- Component 扩展的方法可以使用 int, double, float, String, Map, List , com.alibaba.fastjson.JSONObject类型的参数,
-- Component 定义组件方法.
-
- **示例:**
- + 在组件中如下声明一个组件方法
- ```JAVA
- @UniJSMethod
- public void clearTel() {
- getHostView().setText("");
- }
- ```
- + 注册组之后,你可以在nvue 文件中调用
-
- ```JS
-
-
-
-
-
-
- ```
-
-### component 自定义发送事件
-
-向JS环境发送一些事件,比如click事件
-
-```
-void fireEvent(elementRef,type)
-void fireEvent(elementRef,type, data)
-void fireEvent(elementRef,type,data,domChanges)
-```
-
-- `elementRef`(String):产生事件的组件id
-- `type`(String): 事件名称,UniApp默认事件名称格式为"onXXX",比如`OnPullDown`
-- `data`(Map): 需要发送的一些额外数据,比如`click`时,view大小,点击坐标等等。
-- `domChanges`(Map): 目标组件的属性和样式发生的修改内容
-
-**示例:**
-
-以myText标签为例, 通过 @事件名="方法名" 添加事件,如下添加`onTel`事件,源码请查看 UniPlugin-Hello-AS工程中的`uniplugin_component`模块
-
-```JAVA
-//原生触发fireEvent 自定义事件onTel
-Map params = new HashMap<>();
-Map number = new HashMap<>();
-number.put("tel", telNumber);
-//目前uni限制 参数需要放入到"detail"中 否则会被清理
-params.put("detail", number);
-fireEvent("onTel", params);
-```
-
-```JS
-//标签注册接收onTel事件
-
-//事件回调
-methods: {
- onTel: (e)=> {
- console.log("onTel="+e.detail.tel);
- }
-}
-```
-### UniJSCallback结果回调
-
-JS调用时,有的场景需要返回一些数据,比如以下例子,返回x、y坐标
-```
-void invoke(Object data);
-void invokeAndKeepAlive(Object data);
-```
-- `invoke`调用javascript回调方法,此方法将在调用后被销毁。
-- `invokeAndKeepAlive` 调用javascript回调方法并保持回调活动以备以后使用。
-
-**示例:**
-
-```JAVA
-@UniJSMethod(uiThread = true)
-public void testAsyncFunc(JSONObject options, UniJSCallback callback) {
- Log.e(TAG, "testAsyncFunc--"+options);
- if(callback != null) {
- JSONObject data = new JSONObject();
- data.put("code", "success");
- callback.invoke(data);
- }
-}
-```
-
-**注意**
-
-执行自定义事件fireEvent时params的数据资源都要放入到"detail"中。如果没有将你得返回的数据放入"detail"中将可能丢失。请注意!!!
-
-### globalEvent 事件
-
-用于页面监听持久性事件,例如定位信息,陀螺仪等的变化。
-
-**示例:**
-
-页面监听event事件
-
-```JS
-var globalEvent = uni.requireNativePlugin('globalEvent');
-globalEvent.addEventListener('myEvent', function(e) {
- console.log('myEvent'+JSON.stringify(e));
-});
-```
-
-插件 原生代码发出`myEvent`事件
-
-```JAVA
-Map params=new HashMap<>();
-params.put("key","value");
-mUniSDKInstance.fireGlobalEventCallback("myEvent", params);
-```
-
-**注意**
-globalEvent事件只能通过页面的UniSDKInstance实例给当前页面发送globalEvent事件。其他页面无法接受。
-
-### Module、Component扩展申请权限
-
-使用PermissionControler实现权限申请
-
-```JAVA
-PermissionControler.requestPermissions(Activity, permissions, REQUEST_CODE);
-```
-
-UniModule、UniComponent都有onRequestPermissionsResult周期函数 实现并处理数据即可监听权限申请结果
-
-```JAVA
-@Override
-public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
-}
-```
-
-**简单示例:**
-```JAVA
-import io.dcloud.common.core.permission.PermissionControler;
-import android.Manifest;
-...
-...
-
-public class TestModule extends UniModule {
- final int REQUEST_CODE = 11111;
- private static String[] permissions = new String[]{
- Manifest.permission.ACCESS_FINE_LOCATION,
- Manifest.permission.ACCESS_COARSE_LOCATION
- };
-
- @UniJSMethod(uiThread = true)
- public void requestPermissions() {
- if(mUniSDKInstance.getContext() != null) {
- Activity activity = (Activity) mUniSDKInstance.getContext();
- PermissionControler.requestPermissions(activity, permissions, REQUEST_CODE);
- }
- }
-
- @Override
- public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
- if(requestCode == REQUEST_CODE) {
- for(int i= 0; i< permissions.length; i++) {
- String preName = permissions[i];
- int granted = grantResults[i];
- if(Manifest.permission.ACCESS_FINE_LOCATION.equals(preName) && granted == PackageManager.PERMISSION_GRANTED) {
- //获取权限结果
- }
- }
- }
- super.onRequestPermissionsResult(requestCode, permissions, grantResults);
- }
-}
-```
-
-### 插件示例--RichAlert
-
-封装了一个 RichAlertModule, 富文本alert弹窗Module
-
-#### 代码可参考UniPlugin-Hello-AS工程中的uniplugin_richalert模块。(UniPlugin-Hello-AS工程请在App离线SDK中查找)
-
-```JAVA
-public class RichAlertModule extends UniDestroyableModule {
- ...
- @UniJSMethod(uiThread = true)
- public void show(JSONObject options, UniJSCallback jsCallback) {
- if (mUniSDKInstance.getContext() instanceof Activity) {
- ...
- RichAlert richAlert = new RichAlert(mUniSDKInstance.getContext());
- ...
- richAlert.show();
- ...
- }
- }
- ...
- ...
- @UniJSMethod(uiThread = true)
- public void dismiss() {
- destroy();
- }
-
- @Override
- public void destroy() {
- if (alert != null && alert.isShowing()) {
- UniLogUtils.w("Dismiss the active dialog");
- alert.dismiss();
- }
- }
-
-}
-```
-
-#### HBuilderX 项目中使用RichAlert示例
-
-```JS
-// require插件名称
-const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert');
-// 使用插件
-dcRichAlert.show({
- position: 'bottom',
- title: "提示信息",
- titleColor: '#FF0000',
- content: "uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架!\n免费的\n免费的\n免费的\n重要的事情说三遍",
- contentAlign: 'left',
- checkBox: {
- title: '不再提示',
- isSelected: true
- },
- buttons: [{
- title: '取消'
- },
- {
- title: '否'
- },
- {
- title: '确认',
- titleColor: '#3F51B5'
- }
- ]
-}, result => {
- switch (result.type) {
- case 'button':
- console.log("callback---button--" + result.index);
- break;
- case 'checkBox':
- console.log("callback---checkBox--" + result.isSelected);
- break;
- case 'a':
- console.log("callback---a--" + JSON.stringify(result));
- break;
- case 'backCancel':
- console.log("callback---backCancel--");
- break;
- }
-});
-```
-
-## 插件调试
-
-### 本地注册插件
-
-以上两种方式选一即可
-
-+ 第一种方式
- - 在UniPlugin-Hello-AS工程下 “app” Module根目录assets/dcloud_uniplugins.json文件。 在moudles节点下 添加你要注册的Module 或 Component
-
-+ 第二种方式
- - 创建一个实体类并实现UniAppHookProxy接口,在onCreate函数中添加组件注册相关参数 或 填写插件需要在启动时初始化的逻辑。
- - 在UniPlugin-Hello-AS工程下 “app” Module根目录assets/dcloud_uniplugins.json文件,在hooksClass节点添加你创建实现UniAppHookProxy接口的实体类完整名称填入其中即可 (有些需要初始化操作的需求可以在此处添加逻辑,无特殊操作仅使用第一种方式注册即可无需集成UniAppHookProxy接口)
-
- ```JAVA
- public class RichAlert_AppProxy implements UniAppHookProxy {
- @Override
- public void onCreate(Application application) {
- //当前uni应用进程回调 仅触发一次 多进程不会触发
- //可通过UniSDKEngine注册UniModule或者UniComponent
- }
-
- @Override
- public void onSubProcessCreate(Application application) {
- //其他子进程初始化回调 可用于初始化需要子进程初始化需要的逻辑
- }
- }
- ```
-
-#### dcloud_uniplugins.json说明
-
-- `nativePlugins`: 插件跟节点 可存放多个插件
-- `hooksClass`: 生命周期代理(实现AppHookProxy接口类)格式(完整包名加类名)
-- `plugins`: 插件数组
-- `name` : 注册名称
-- `class` : module 或 component 实体类完整名称
-- `type` : module 或 component类型。
-
-```JSON
-{
- "nativePlugins": [
- {
- "hooksClass": "uni.dcloud.io.uniplugin_richalert.apphooks",
- "plugins": [
- {
- "type": "module",
- "name": "DCloud-RichAlert",
- "class": "uni.dcloud.io.uniplugin_richalert.RichAlertModule"
- }
- ]
- }
- ]
-}
-```
-
-### uni-app项目中获取插件
-
-通过使用uni.requireNativePlugin获取插件对象。
-
-```
-const pluginImpl = uni.requireNativePlugin('插件 name')
-```
-
-### 集成uni-app项目测试插件
-
-- 安装最新[HbuilderX](http://www.dcloud.io/hbuilderx.html) 大于等于1.4.0+
-
-- 创建uni-app工程或在已有的uni-app工程编写相关的.nvue 和.vue文件。使用uni-app插件中的module 或 component。
-
-- xxx.vue 示例代码(源码请参考UniPlugin-Hello-AS项目中`uniapp示例工程源码`文件夹的`unipluginDemo`工程,**导入示例工程时需要重新获取appid**)
-
-
-
-- 选择 发行--->原生APP-本地打包--->生成本地打包App资源 等待资源生成!
-
-
-
-- 在控制台会输出编译日志,编译成功会给出App资源路径
-
-
-
-- 把APP资源文件放入到UniPlugin-Hello-AS工程下 `app` Module根目录assets/apps/测试工程appid/www对应目录下,再修改assets/data/dcloud_control.xml!修改其中appid=“测试工程appid”!,测试工程UniPlugin-Hello-AS 已有相关配置可参考。具体可查看[App离线打包](/AppDocs/usesdk/android.md)。
-
-- appid注意 一定要统一否则会导致应用无法正常运行!
-
-
-
-- 配置"app"Module下的 build.gradle. 在dependencies节点添加插件project引用 (以uniplugin_richalert为例)
-
-```
-// 添加uni-app插件
-implementation project(':uniplugin_richalert')
-```
-- 运行测试。测试运行时一切要以真机运行为主。
-
-## 生成uni-app插件
-
-+ 完整的android 插件包.ZIP包含:
- - android文件
- - .aar文件 : 包括插件aar、插件所依赖的aar。
- - libs文件夹 : 存放插件包依赖的第三方 .jar文件和.so文件
- - package.json 插件信息
- - [点击查看具体说明](/NativePlugin/course/package.md)
-
-#### 准备相关文件
-
-+ 创建以插件id命名的文件夹
-+ 创建android文件夹。并将该文件夹放入到新建的插件id命名的文件夹中
-
-**示例:**
-
-```
-|-- DCloud-RichAlert --->插件id命名的文件夹
- |-- android --->安卓插件目录
- |--libs
- - xxx.jar --->依赖的jar
- - libxxx.so --->依赖的so文件
- - vendor.aar --->依赖的aar
- - unipluginRichAlert.aar --->插件module的aar
-```
-
-
-+ 生成插件的aar并放入到android目录下
- + 选择Gradle--->插件module--->Tasks--->build或other--->assembleRelease编译module的aar文件
-
- **注意:新版本Android studio将assembleRelease放入other中了**
-
-
-
-+ 创建[package.json](/NativePlugin/course/package.md)文件并填写必要的信息。放入到android目录下
-+ 创建libs文件夹。并放入到android目录下
- + 将插件依赖的jar文件放入到libs文件夹中
- + 将插件依赖的.so文件放入到libs文件夹中
-+ 将插件依赖的aar文件放入到插件android目录下
-
-**注意**
-
-**目前发现部分同学将开发插件的uniapp-v8-release.aar、uniapp-release.aar放到了插件包libs中。导致冲突。切记不要放进libs里去!!!
-插件所依赖的aar要放到android目录下。**
-
-## 插件编写命名规范
-+ 源代码的package中一定要作者标识防止与其他插件冲突导致插件审核失败,无法上传。
-
- **如示例中插件类的“package uni.dcloud.io.uniplugin_richalert;” “dcloud”就是作者标识!**
-
-+ Module的注册命名首先必须要使用[id](/NativePlugin/course/package?id=id)为前缀。与[id](/NativePlugin/course/package?id=id)完全相同也可以!如果你的插件中可能存在多个Module就需要注意[id](/NativePlugin/course/package?id=id)为前缀的重要性。
-+ Component的注册命名还没有严格要求。但开发者尽量使用[id](/NativePlugin/course/package?id=id)前缀。减少与其他插件的命名冲突导致插件无法正常运行。
-
-**Tips:**
-
-`id`?请阅读[package.json](/NativePlugin/course/package.md)
-
-**示例:**
-```
-{
- "name": "插件名称",
- "id": "DCloud-RichAlert", // 插件标识
- "version": "插件版本号",
- "description": "插件描述信息",
- "_dp_type":"nativeplugin",
- "_dp_nativeplugin":{
- "android": {
- "plugins": [
- {
- "type": "module",
- "name": "DCloud-RichAlert_TestModule", //id为前缀
- "class": "uni.dcloud.io.uniplugin_richalert.TestModule"
- },
- {
- "type": "component",
- "name": "DCloud-RichAlert_TestComponent",
- "class": "uni.dcloud.io.uniplugin_richalert.TestComponent"
- }
- ]
- }
- }
- ...
- ...
-```
-
-
-#### 生成uni插件压缩包
-
-压缩插件id命名的文件夹为zip即可。具体目录机构如下:
-
-- 一级目录以插件id命名,对应package.json中的id字段! 存放android文件夹和package.json文件。
-
-
-
-- 二级目录 android 存放安卓插件 .aar 文件 .jar .so放入到libs下
-
-
-
-**注意:.os文件需要注意 armeabi-v7a、x86 、arm64-v8a以上三种类型的.so必须要有,如果没有无法正常使用!!**
-
-
-## 提交插件市场
-
-** 登录注册**[DCloud插件市场](http://ext.dcloud.net.cn/) 按提示步骤提交插件(需要编写对应插件的说明文档,md(markdown) 格式)
-
-## [本地插件提交云端打包](/NativePlugin/use/use_local_plugin.md)
-
-## 插件注意事项
-
-#### 目前对UniApp支持的问题
-+ Activity的获取方式。通过mUniSDKInstance.getContext()强转Activity。建议先instanceof Activity判断一下再强转
-+ .vue暂时只能使用module形式。component还不支持在.vue下使用
-+ component、module的生命周回调,暂时只支持onActivityDestroy 、onActivityPause、onActivityResult其他暂时不支持
-
-**Tips** onActivityResume事件存在缺陷。应用第一次启动无法正常收到onActivityResume事件,后台切换到前台是可以收到的。
-
-**示例:**
-
-```
-@Override
-public void onActivityPause() {
- UniLogUtils.e(TAG, "onActivityPause");
-}
-
-@Override
-public void onActivityResume() {
- UniLogUtils.e(TAG, "onActivityResume");
-}
-```
-
-#### 第三方依赖库
-+ 请参考[android平台所有依赖库列表](http://ask.dcloud.net.cn/article/35419), 编写自己插件时需要查看是否与编译的程序依赖有冲突,防止审核失败或编译失败等问题。
-+ 对有些插件需要引用到.so文件,需要特殊配置一下.请参考[Android studio添加第三方库和so](https://blog.csdn.net/anhenzhufeng/article/details/78913341)
-+ 代码中用到的JSONObject、JSONArray 要使用com.alibaba.fastjson.JSONArray;com.alibaba.fastjson.JSONObject; 不要使用org.json.JSONObject;org.json.JSONArray 否则造成参数无法正常传递使用等问题。
-+ aar放到android目录下。jar放到libs目录下。也可使用compileOnly修饰,然后将相应的依赖库名称配置到package.json中的dependencies节点下。具体参考[package.json文档](NativePlugin/course/package?id=packagejson)
-+ 第三方库依赖冲突。一种是主app已完整集成相关第三方库。可使用compileOnly修饰即可。如果主app仅集成了部分第三方库。可参考https://blog.csdn.net/wapchief/article/details/80514880
-+ .os文件需要注意 armeabi-v7a必须存在,没有可能无法正常使用!其他cpu类型os库x86 、arm64-v8a、x86-64如有最好添加。
-+ 插件中包含FileProvider云打包冲突,可通过http://ask.dcloud.net.cn/article/36105此贴配置绕过。
-+ 插件中有资源路径返回时,请使用绝对路径file://开头防止不必要的路径转换问题。
-
-
-#### 广告插件说明
-+ 由于官方 UniAD 广告组件集成了“广点通”和“穿山甲”SDK,目前不支持自行开发包含这两个SDK的原生插件,云打包会导致冲突;
-
-#### 插件混淆配置
-
-请将以下混淆配置信息添加到相应的原生插件proguard配置文件中即可。
-
-```
--keep public class * extends io.dcloud.weex.AppHookProxy{*;}
--keep public class * extends io.dcloud.feature.uniapp.UniAppHookProxy{*;}
--keep public class * extends io.dcloud.feature.uniapp.common.UniModule{*;}
--keep public class * extends io.dcloud.feature.uniapp.ui.component.UniComponent{*;}
-```
-
-## 常见问题
-
-Q:云打包 运行插件提示"XXX"插件不存在?
-
-A:按以下步骤检测自己项目:
-
-1、请使用自定义基座测试自己插件。默认基座并不包含你的插件。
-
-2、确认打包时是否勾选了"XXX"插件。
-
-3、查看插件配置`package.json`这也是多数同学容易犯错的地方。主要检查`class`配置的信息与插件中的aar是否匹配。
-
-4、插件中依赖库没有添加到配置或者aar中。多数为离线工程没问题,云打包有问题!认真检查依赖库是否都包含在插件中。
-
-5、以上都不能解决你的问题,请@客服
-
-Q:插件中怎么跳转原生Activity页面
-A:获取UniSDKInstance对象。该对象中可以获取到上下文.通过startActivity跳转
-
-**示例**
-
-```
-@UniJSMethod (uiThread = true)
-public void gotoNativePage(){
- if(mUniSDKInstance != null) {
- Intent intent = new Intent(mUniSDKInstance.getContext(), NativePageActivity.class);
- mUniSDKInstance.getContext().startActivity(intent);
- }
-}
-```
-
-Q:插件跳转Activity页面后。Activity页面关闭后有数据需要返回。怎么能实现?
-A:可以按以下步骤操作实现:
- * 在插件的UniModule/UniComponent实现onActivityResult方法。通过标识code和参数KEY去区分当前的Result是你需要的返回值
-
- **示例**
-
- ```JAVA
- public static int REQUEST_CODE = 1000; //数据返回标识code
- @Override
- public void onActivityResult(int requestCode, int resultCode, Intent data) {
- if(requestCode == REQUEST_CODE && data.hasExtra("respond")) {
- Log.e("TestModule", "原生页面返回----"+data.getStringExtra("respond"));
- } else {
- super.onActivityResult(requestCode, resultCode, data);
- }
- }
- ```
- * 通过startActivityForResult加上返回标识code跳转其他Activity页面。
-
- **示例**
-
- ```JAVA
- @UniJSMethod (uiThread = true)
- public void gotoNativePage(){
- if(mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) {
- Intent intent = new Intent(mUniSDKInstance.getContext(), NativePageActivity.class);
- ((Activity)mUniSDKInstance.getContext()).startActivityForResult(intent, REQUEST_CODE);
- }
- }
- ```
- * Activity页面在关闭前调用setResult设置标识code将要返回的参数放进Intent中。
-
- **示例**
-
- ```JAVA
- Intent intent = new Intent();
- intent.putExtra("respond", "我是原生页面");
- setResult(TestModule.REQUEST_CODE, intent);
- finish();
- ```
-
-Q:插件开发支持Androidx吗?
-A:设置useAndroidX = true 目前已知讯飞语音无法支持androidx配置不能兼容需要注意并提醒插件使用者。
-
-Q:component、module的生命周回调 不支持OnActivityCreate(),某些注册服务需要该事件注册怎么办。
-A:component可以在的构造函数中调用相关注册初始化服务等操作, module的构造无法获取到上下文。可能需要换一个思路。通过js调用相关初始化的函数。
-
-Q:打包发现集成的三方库与主APP集成的三方库有冲突。导致无法打包成功?
-
-A:
-
- + 请尽量使用主APP集成的三方库去实现你的插件依赖集成。请告知使用该插件需要‘XXX’模块才可正常运行。版本号可[查看](https://ask.dcloud.net.cn/article/35419)
- + 如果集成的三方库无法使用主APP集成的三方库。请告知插件使用者不要集成‘XXX’模块。防止打包失败。
-
-Q:HX3.0.0+版本云打包编译之前插件无法编译通过。HX2.9.8版本云打包是可以的。
-
-A:
-
- + 请检查一下之前编译插件的配置`build.gradle`文件。检测是否使用`api files(xxx.aar)`引入某些依赖库aar文件。如果有这样的配置请改为使用compileOnly 修饰。否则无法在3.0.0+编译通过。主要原因就是资源冲突。 `api files(xxx.aar)`这种玩法是错误的。
- + 检查一下自己插件aar中的`classes.jar`文件。使用压缩工具查看一下`classes.jar`里的文件是否存在资源文件。如`AndroidManifest.xml`、`res`等资源文件需要删除。否则无法在3.0.0+编译通过。
-
-Q:插件SDK部分需要在Application初始化。目前在AppHookProxy中onCreate初始化无效
-
-A: 请使用UniAppHookProxy接口(此处注意!不是AppHookProxy是UniAppHookProxy) 有onSubProcessCreate子进程初始化回调。将SDK需要在Application初始化的代码onCreate和onSubProcessCreate都放一份就可以了。
-
-Q:插件可以重写Application吗?
-
-A:不支持。重写Application存在很多安全隐患。
-
-Q:插件生产文件路径需要注意哪些?
-
-A:
-
-+ 插件生成的路径尽量添加`file://`防止路径被转换导致无法正确获取文件
-+ 尽量将文件放到`/storage/emulated/0/Android/data/$应用的包名$/apps/$uniapp的appid$/doc/`目录下
-
-Q: 如何查看如何查看uniapp console日志
-
+ compileOnly 'androidx.recyclerview:recyclerview:1.1.0'
+ compileOnly 'com.alibaba:fastjson:1.2.83'
+
+ compileOnly fileTree(include: ['uniapp-v8-release.aar'], dir: '../app/libs')
+}
+```
+
+**Tips:**
+
+uniapp-v8-release.aar是扩展module主要依赖库,必须导入此依赖库!
+
+#### 创建TestModule类
+
+- Module 扩展必须继承 UniModule 类
+
+**示例:**
+
+```JAVA
+public class TestModule extends UniModule
+```
+
+- 扩展方法必须加上@UniJSMethod (uiThread = false or true) 注解。UniApp 会根据注解来判断当前方法是否要运行在 UI 线程,和当前方法是否是扩展方法。
+- UniApp是根据反射来进行调用 Module 扩展方法,所以Module中的扩展方法必须是 public 类型。
+
+**示例:**
+
+```JAVA
+//run ui thread
+@UniJSMethod(uiThread = true)
+public void testAsyncFunc(JSONObject options, UniJSCallback callback) {
+ Log.e(TAG, "testAsyncFunc--"+options);
+ if(callback != null) {
+ JSONObject data = new JSONObject();
+ data.put("code", "success");
+ callback.invoke(data);
+ }
+}
+
+//run JS thread
+@UniJSMethod (uiThread = false)
+public JSONObject testSyncFunc(){
+ JSONObject data = new JSONObject();
+ data.put("code", "success");
+ return data;
+}
+```
+
+- 同样因为是通过反射调用,Module 不能被混淆。请在混淆文件中添加代码:
+
+```
+-keep public class * extends io.dcloud.feature.uniapp.common.UniModule{*;}
+```
+
+- Module 扩展的方法可以使用 int, double, float, String, Map, List ,com.alibaba.fastjson.JSONObject 类型的参数
+
+### 扩展组件 Component
+
+- Component 扩展 实现特别功能的 Native 控件
+- Component 不支持代码中 new Component 创建对象。无法正常使用!
+
+下面以`TestComponent`为例,源码请查看 UniPlugin-Hello-AS(2.9.8+)工程中的`uniplugin_component`模块;
+
+#### 创建Android Studio的Module模块
+
+请参考 [扩展 Module](/NativePlugin/course/android?id=创建android-studio的module模块)
+
+#### 创建TestComponent类
+
+- Component 扩展类必须继承 UniComponent, 父容器Component(例如ViewGroup组件)则需要继承UniVContainer
+
+**示例:**
+
+```JAVA
+public class TestText extends UniComponent
+```
+- UniComponent的initComponentHostView回调函数。构建Component的view时会触发此回调函数。
+
+**示例:**
+
+```JAVA
+@Override
+protected TextView initComponentHostView(@NonNull Context context) {
+ TextView textView = new TextView(context);
+ textView.setTextSize(20);
+ textView.setTextColor(Color.BLACK);
+ return textView;
+}
+```
+
+- Component 对应的设置属性的方法必须添加注解 @UniComponentProp(name=value(value is attr or style of dsl))
+
+**示例:**
+
+```JAVA
+@UniComponentProp(name = "tel")
+public void setTel(String telNumber) {
+ getHostView().setText("tel: " + telNumber);
+}
+```
+- UniApp sdk 通过反射调用对应的方法,所以 Component 对应的属性方法必须是 public,并且不能被混淆。请在混淆文件中添加代码
+```
+-keep public class * extends io.dcloud.feature.uniapp.ui.component.UniComponent{*;}
+```
+- Component 扩展的方法可以使用 int, double, float, String, Map, List , com.alibaba.fastjson.JSONObject类型的参数,
+- Component 定义组件方法.
+
+ **示例:**
+ + 在组件中如下声明一个组件方法
+ ```JAVA
+ @UniJSMethod
+ public void clearTel() {
+ getHostView().setText("");
+ }
+ ```
+ + 注册组之后,你可以在nvue 文件中调用
+
+ ```JS
+
+
+
+
+
+
+ ```
+
+### component 自定义发送事件
+
+向JS环境发送一些事件,比如click事件
+
+```
+void fireEvent(elementRef,type)
+void fireEvent(elementRef,type, data)
+void fireEvent(elementRef,type,data,domChanges)
+```
+
+- `elementRef`(String):产生事件的组件id
+- `type`(String): 事件名称,UniApp默认事件名称格式为"onXXX",比如`OnPullDown`
+- `data`(Map): 需要发送的一些额外数据,比如`click`时,view大小,点击坐标等等。
+- `domChanges`(Map): 目标组件的属性和样式发生的修改内容
+
+**示例:**
+
+以myText标签为例, 通过 @事件名="方法名" 添加事件,如下添加`onTel`事件,源码请查看 UniPlugin-Hello-AS工程中的`uniplugin_component`模块
+
+```JAVA
+//原生触发fireEvent 自定义事件onTel
+Map params = new HashMap<>();
+Map number = new HashMap<>();
+number.put("tel", telNumber);
+//目前uni限制 参数需要放入到"detail"中 否则会被清理
+params.put("detail", number);
+fireEvent("onTel", params);
+```
+
+```JS
+//标签注册接收onTel事件
+
+//事件回调
+methods: {
+ onTel: (e)=> {
+ console.log("onTel="+e.detail.tel);
+ }
+}
+```
+### UniJSCallback结果回调
+
+JS调用时,有的场景需要返回一些数据,比如以下例子,返回x、y坐标
+```
+void invoke(Object data);
+void invokeAndKeepAlive(Object data);
+```
+- `invoke`调用javascript回调方法,此方法将在调用后被销毁。
+- `invokeAndKeepAlive` 调用javascript回调方法并保持回调活动以备以后使用。
+
+**示例:**
+
+```JAVA
+@UniJSMethod(uiThread = true)
+public void testAsyncFunc(JSONObject options, UniJSCallback callback) {
+ Log.e(TAG, "testAsyncFunc--"+options);
+ if(callback != null) {
+ JSONObject data = new JSONObject();
+ data.put("code", "success");
+ callback.invoke(data);
+ }
+}
+```
+
+**注意**
+
+执行自定义事件fireEvent时params的数据资源都要放入到"detail"中。如果没有将你得返回的数据放入"detail"中将可能丢失。请注意!!!
+
+### globalEvent 事件
+
+用于页面监听持久性事件,例如定位信息,陀螺仪等的变化。
+
+**示例:**
+
+页面监听event事件
+
+```JS
+var globalEvent = uni.requireNativePlugin('globalEvent');
+globalEvent.addEventListener('myEvent', function(e) {
+ console.log('myEvent'+JSON.stringify(e));
+});
+```
+
+插件 原生代码发出`myEvent`事件
+
+```JAVA
+Map params=new HashMap<>();
+params.put("key","value");
+mUniSDKInstance.fireGlobalEventCallback("myEvent", params);
+```
+
+**注意**
+globalEvent事件只能通过页面的UniSDKInstance实例给当前页面发送globalEvent事件。其他页面无法接受。
+
+### Module、Component扩展申请权限
+
+使用PermissionControler实现权限申请
+
+```JAVA
+PermissionControler.requestPermissions(Activity, permissions, REQUEST_CODE);
+```
+
+UniModule、UniComponent都有onRequestPermissionsResult周期函数 实现并处理数据即可监听权限申请结果
+
+```JAVA
+@Override
+public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+}
+```
+
+**简单示例:**
+```JAVA
+import io.dcloud.common.core.permission.PermissionControler;
+import android.Manifest;
+...
+...
+
+public class TestModule extends UniModule {
+ final int REQUEST_CODE = 11111;
+ private static String[] permissions = new String[]{
+ Manifest.permission.ACCESS_FINE_LOCATION,
+ Manifest.permission.ACCESS_COARSE_LOCATION
+ };
+
+ @UniJSMethod(uiThread = true)
+ public void requestPermissions() {
+ if(mUniSDKInstance.getContext() != null) {
+ Activity activity = (Activity) mUniSDKInstance.getContext();
+ PermissionControler.requestPermissions(activity, permissions, REQUEST_CODE);
+ }
+ }
+
+ @Override
+ public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
+ if(requestCode == REQUEST_CODE) {
+ for(int i= 0; i< permissions.length; i++) {
+ String preName = permissions[i];
+ int granted = grantResults[i];
+ if(Manifest.permission.ACCESS_FINE_LOCATION.equals(preName) && granted == PackageManager.PERMISSION_GRANTED) {
+ //获取权限结果
+ }
+ }
+ }
+ super.onRequestPermissionsResult(requestCode, permissions, grantResults);
+ }
+}
+```
+
+### 插件示例--RichAlert
+
+封装了一个 RichAlertModule, 富文本alert弹窗Module
+
+#### 代码可参考UniPlugin-Hello-AS工程中的uniplugin_richalert模块。(UniPlugin-Hello-AS工程请在App离线SDK中查找)
+
+```JAVA
+public class RichAlertModule extends UniDestroyableModule {
+ ...
+ @UniJSMethod(uiThread = true)
+ public void show(JSONObject options, UniJSCallback jsCallback) {
+ if (mUniSDKInstance.getContext() instanceof Activity) {
+ ...
+ RichAlert richAlert = new RichAlert(mUniSDKInstance.getContext());
+ ...
+ richAlert.show();
+ ...
+ }
+ }
+ ...
+ ...
+ @UniJSMethod(uiThread = true)
+ public void dismiss() {
+ destroy();
+ }
+
+ @Override
+ public void destroy() {
+ if (alert != null && alert.isShowing()) {
+ UniLogUtils.w("Dismiss the active dialog");
+ alert.dismiss();
+ }
+ }
+
+}
+```
+
+#### HBuilderX 项目中使用RichAlert示例
+
+```JS
+// require插件名称
+const dcRichAlert = uni.requireNativePlugin('DCloud-RichAlert');
+// 使用插件
+dcRichAlert.show({
+ position: 'bottom',
+ title: "提示信息",
+ titleColor: '#FF0000',
+ content: "uni-app 是一个使用 Vue.js 开发跨平台应用的前端框架!\n免费的\n免费的\n免费的\n重要的事情说三遍",
+ contentAlign: 'left',
+ checkBox: {
+ title: '不再提示',
+ isSelected: true
+ },
+ buttons: [{
+ title: '取消'
+ },
+ {
+ title: '否'
+ },
+ {
+ title: '确认',
+ titleColor: '#3F51B5'
+ }
+ ]
+}, result => {
+ switch (result.type) {
+ case 'button':
+ console.log("callback---button--" + result.index);
+ break;
+ case 'checkBox':
+ console.log("callback---checkBox--" + result.isSelected);
+ break;
+ case 'a':
+ console.log("callback---a--" + JSON.stringify(result));
+ break;
+ case 'backCancel':
+ console.log("callback---backCancel--");
+ break;
+ }
+});
+```
+
+## 插件调试
+
+### 本地注册插件
+
+以上两种方式选一即可
+
++ 第一种方式
+ - 在UniPlugin-Hello-AS工程下 “app” Module根目录assets/dcloud_uniplugins.json文件。 在moudles节点下 添加你要注册的Module 或 Component
+
++ 第二种方式
+ - 创建一个实体类并实现UniAppHookProxy接口,在onCreate函数中添加组件注册相关参数 或 填写插件需要在启动时初始化的逻辑。
+ - 在UniPlugin-Hello-AS工程下 “app” Module根目录assets/dcloud_uniplugins.json文件,在hooksClass节点添加你创建实现UniAppHookProxy接口的实体类完整名称填入其中即可 (有些需要初始化操作的需求可以在此处添加逻辑,无特殊操作仅使用第一种方式注册即可无需集成UniAppHookProxy接口)
+
+ ```JAVA
+ public class RichAlert_AppProxy implements UniAppHookProxy {
+ @Override
+ public void onCreate(Application application) {
+ //当前uni应用进程回调 仅触发一次 多进程不会触发
+ //可通过UniSDKEngine注册UniModule或者UniComponent
+ }
+
+ @Override
+ public void onSubProcessCreate(Application application) {
+ //其他子进程初始化回调 可用于初始化需要子进程初始化需要的逻辑
+ }
+ }
+ ```
+
+#### dcloud_uniplugins.json说明
+
+- `nativePlugins`: 插件跟节点 可存放多个插件
+- `hooksClass`: 生命周期代理(实现AppHookProxy接口类)格式(完整包名加类名)
+- `plugins`: 插件数组
+- `name` : 注册名称
+- `class` : module 或 component 实体类完整名称
+- `type` : module 或 component类型。
+
+```JSON
+{
+ "nativePlugins": [
+ {
+ "hooksClass": "uni.dcloud.io.uniplugin_richalert.apphooks",
+ "plugins": [
+ {
+ "type": "module",
+ "name": "DCloud-RichAlert",
+ "class": "uni.dcloud.io.uniplugin_richalert.RichAlertModule"
+ }
+ ]
+ }
+ ]
+}
+```
+
+### uni-app项目中获取插件
+
+通过使用uni.requireNativePlugin获取插件对象。
+
+```
+const pluginImpl = uni.requireNativePlugin('插件 name')
+```
+
+### 集成uni-app项目测试插件
+
+- 安装最新[HbuilderX](http://www.dcloud.io/hbuilderx.html) 大于等于1.4.0+
+
+- 创建uni-app工程或在已有的uni-app工程编写相关的.nvue 和.vue文件。使用uni-app插件中的module 或 component。
+
+- xxx.vue 示例代码(源码请参考UniPlugin-Hello-AS项目中`uniapp示例工程源码`文件夹的`unipluginDemo`工程,**导入示例工程时需要重新获取appid**)
+
+
+
+- 选择 发行--->原生APP-本地打包--->生成本地打包App资源 等待资源生成!
+
+
+
+- 在控制台会输出编译日志,编译成功会给出App资源路径
+
+
+
+- 把APP资源文件放入到UniPlugin-Hello-AS工程下 `app` Module根目录assets/apps/测试工程appid/www对应目录下,再修改assets/data/dcloud_control.xml!修改其中appid=“测试工程appid”!,测试工程UniPlugin-Hello-AS 已有相关配置可参考。具体可查看[App离线打包](/AppDocs/usesdk/android.md)。
+
+- appid注意 一定要统一否则会导致应用无法正常运行!
+
+
+
+- 配置"app"Module下的 build.gradle. 在dependencies节点添加插件project引用 (以uniplugin_richalert为例)
+
+```
+// 添加uni-app插件
+implementation project(':uniplugin_richalert')
+```
+- 运行测试。测试运行时一切要以真机运行为主。
+
+## 生成uni-app插件
+
++ 完整的android 插件包.ZIP包含:
+ - android文件
+ - .aar文件 : 包括插件aar、插件所依赖的aar。
+ - libs文件夹 : 存放插件包依赖的第三方 .jar文件和.so文件
+ - package.json 插件信息
+ - [点击查看具体说明](/NativePlugin/course/package.md)
+
+#### 准备相关文件
+
++ 创建以插件id命名的文件夹
++ 创建android文件夹。并将该文件夹放入到新建的插件id命名的文件夹中
+
+**示例:**
+
+```
+|-- DCloud-RichAlert --->插件id命名的文件夹
+ |-- android --->安卓插件目录
+ |--libs
+ - xxx.jar --->依赖的jar
+ - libxxx.so --->依赖的so文件
+ - vendor.aar --->依赖的aar
+ - unipluginRichAlert.aar --->插件module的aar
+```
+
+
++ 生成插件的aar并放入到android目录下
+ + 选择Gradle--->插件module--->Tasks--->build或other--->assembleRelease编译module的aar文件
+
+ **注意:新版本Android studio将assembleRelease放入other中了**
+
+
+
++ 创建[package.json](/NativePlugin/course/package.md)文件并填写必要的信息。放入到android目录下
++ 创建libs文件夹。并放入到android目录下
+ + 将插件依赖的jar文件放入到libs文件夹中
+ + 将插件依赖的.so文件放入到libs文件夹中
++ 将插件依赖的aar文件放入到插件android目录下
+
+**注意**
+
+**目前发现部分同学将开发插件的uniapp-v8-release.aar、uniapp-release.aar放到了插件包libs中。导致冲突。切记不要放进libs里去!!!
+插件所依赖的aar要放到android目录下。**
+
+## 插件编写命名规范
++ 源代码的package中一定要作者标识防止与其他插件冲突导致插件审核失败,无法上传。
+
+ **如示例中插件类的“package uni.dcloud.io.uniplugin_richalert;” “dcloud”就是作者标识!**
+
++ Module的注册命名首先必须要使用[id](/NativePlugin/course/package?id=id)为前缀。与[id](/NativePlugin/course/package?id=id)完全相同也可以!如果你的插件中可能存在多个Module就需要注意[id](/NativePlugin/course/package?id=id)为前缀的重要性。
++ Component的注册命名还没有严格要求。但开发者尽量使用[id](/NativePlugin/course/package?id=id)前缀。减少与其他插件的命名冲突导致插件无法正常运行。
+
+**Tips:**
+
+`id`?请阅读[package.json](/NativePlugin/course/package.md)
+
+**示例:**
+```
+{
+ "name": "插件名称",
+ "id": "DCloud-RichAlert", // 插件标识
+ "version": "插件版本号",
+ "description": "插件描述信息",
+ "_dp_type":"nativeplugin",
+ "_dp_nativeplugin":{
+ "android": {
+ "plugins": [
+ {
+ "type": "module",
+ "name": "DCloud-RichAlert_TestModule", //id为前缀
+ "class": "uni.dcloud.io.uniplugin_richalert.TestModule"
+ },
+ {
+ "type": "component",
+ "name": "DCloud-RichAlert_TestComponent",
+ "class": "uni.dcloud.io.uniplugin_richalert.TestComponent"
+ }
+ ]
+ }
+ }
+ ...
+ ...
+```
+
+
+#### 生成uni插件压缩包
+
+压缩插件id命名的文件夹为zip即可。具体目录机构如下:
+
+- 一级目录以插件id命名,对应package.json中的id字段! 存放android文件夹和package.json文件。
+
+
+
+- 二级目录 android 存放安卓插件 .aar 文件 .jar .so放入到libs下
+
+
+
+**注意:.os文件需要注意 armeabi-v7a、x86 、arm64-v8a以上三种类型的.so必须要有,如果没有无法正常使用!!**
+
+
+## 提交插件市场
+
+** 登录注册**[DCloud插件市场](http://ext.dcloud.net.cn/) 按提示步骤提交插件(需要编写对应插件的说明文档,md(markdown) 格式)
+
+## [本地插件提交云端打包](/NativePlugin/use/use_local_plugin.md)
+
+## 插件注意事项
+
+#### 目前对UniApp支持的问题
++ Activity的获取方式。通过mUniSDKInstance.getContext()强转Activity。建议先instanceof Activity判断一下再强转
++ .vue暂时只能使用module形式。component还不支持在.vue下使用
++ component、module的生命周回调,暂时只支持onActivityDestroy 、onActivityPause、onActivityResult其他暂时不支持
+
+**Tips** onActivityResume事件存在缺陷。应用第一次启动无法正常收到onActivityResume事件,后台切换到前台是可以收到的。
+
+**示例:**
+
+```
+@Override
+public void onActivityPause() {
+ UniLogUtils.e(TAG, "onActivityPause");
+}
+
+@Override
+public void onActivityResume() {
+ UniLogUtils.e(TAG, "onActivityResume");
+}
+```
+
+#### 第三方依赖库
++ 请参考[android平台所有依赖库列表](http://ask.dcloud.net.cn/article/35419), 编写自己插件时需要查看是否与编译的程序依赖有冲突,防止审核失败或编译失败等问题。
++ 对有些插件需要引用到.so文件,需要特殊配置一下.请参考[Android studio添加第三方库和so](https://blog.csdn.net/anhenzhufeng/article/details/78913341)
++ 代码中用到的JSONObject、JSONArray 要使用com.alibaba.fastjson.JSONArray;com.alibaba.fastjson.JSONObject; 不要使用org.json.JSONObject;org.json.JSONArray 否则造成参数无法正常传递使用等问题。
++ aar放到android目录下。jar放到libs目录下。也可使用compileOnly修饰,然后将相应的依赖库名称配置到package.json中的dependencies节点下。具体参考[package.json文档](NativePlugin/course/package?id=packagejson)
++ 第三方库依赖冲突。一种是主app已完整集成相关第三方库。可使用compileOnly修饰即可。如果主app仅集成了部分第三方库。可参考https://blog.csdn.net/wapchief/article/details/80514880
++ .os文件需要注意 armeabi-v7a必须存在,没有可能无法正常使用!其他cpu类型os库x86 、arm64-v8a、x86-64如有最好添加。
++ 插件中包含FileProvider云打包冲突,可通过http://ask.dcloud.net.cn/article/36105此贴配置绕过。
++ 插件中有资源路径返回时,请使用绝对路径file://开头防止不必要的路径转换问题。
+
+
+#### 广告插件说明
++ 由于官方 UniAD 广告组件集成了“广点通”和“穿山甲”SDK,目前不支持自行开发包含这两个SDK的原生插件,云打包会导致冲突;
+
+#### 插件混淆配置
+
+请将以下混淆配置信息添加到相应的原生插件proguard配置文件中即可。
+
+```
+-keep public class * extends io.dcloud.weex.AppHookProxy{*;}
+-keep public class * extends io.dcloud.feature.uniapp.UniAppHookProxy{*;}
+-keep public class * extends io.dcloud.feature.uniapp.common.UniModule{*;}
+-keep public class * extends io.dcloud.feature.uniapp.ui.component.UniComponent{*;}
+```
+
+## 常见问题
+
+Q:云打包 运行插件提示"XXX"插件不存在?
+
+A:按以下步骤检测自己项目:
+
+1、请使用自定义基座测试自己插件。默认基座并不包含你的插件。
+
+2、确认打包时是否勾选了"XXX"插件。
+
+3、查看插件配置`package.json`这也是多数同学容易犯错的地方。主要检查`class`配置的信息与插件中的aar是否匹配。
+
+4、插件中依赖库没有添加到配置或者aar中。多数为离线工程没问题,云打包有问题!认真检查依赖库是否都包含在插件中。
+
+5、以上都不能解决你的问题,请@客服
+
+Q:插件中怎么跳转原生Activity页面
+A:获取UniSDKInstance对象。该对象中可以获取到上下文.通过startActivity跳转
+
+**示例**
+
+```
+@UniJSMethod (uiThread = true)
+public void gotoNativePage(){
+ if(mUniSDKInstance != null) {
+ Intent intent = new Intent(mUniSDKInstance.getContext(), NativePageActivity.class);
+ mUniSDKInstance.getContext().startActivity(intent);
+ }
+}
+```
+
+Q:插件跳转Activity页面后。Activity页面关闭后有数据需要返回。怎么能实现?
+A:可以按以下步骤操作实现:
+ * 在插件的UniModule/UniComponent实现onActivityResult方法。通过标识code和参数KEY去区分当前的Result是你需要的返回值
+
+ **示例**
+
+ ```JAVA
+ public static int REQUEST_CODE = 1000; //数据返回标识code
+ @Override
+ public void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if(requestCode == REQUEST_CODE && data.hasExtra("respond")) {
+ Log.e("TestModule", "原生页面返回----"+data.getStringExtra("respond"));
+ } else {
+ super.onActivityResult(requestCode, resultCode, data);
+ }
+ }
+ ```
+ * 通过startActivityForResult加上返回标识code跳转其他Activity页面。
+
+ **示例**
+
+ ```JAVA
+ @UniJSMethod (uiThread = true)
+ public void gotoNativePage(){
+ if(mUniSDKInstance != null && mUniSDKInstance.getContext() instanceof Activity) {
+ Intent intent = new Intent(mUniSDKInstance.getContext(), NativePageActivity.class);
+ ((Activity)mUniSDKInstance.getContext()).startActivityForResult(intent, REQUEST_CODE);
+ }
+ }
+ ```
+ * Activity页面在关闭前调用setResult设置标识code将要返回的参数放进Intent中。
+
+ **示例**
+
+ ```JAVA
+ Intent intent = new Intent();
+ intent.putExtra("respond", "我是原生页面");
+ setResult(TestModule.REQUEST_CODE, intent);
+ finish();
+ ```
+
+Q:插件开发支持Androidx吗?
+A:设置useAndroidX = true 目前已知讯飞语音无法支持androidx配置不能兼容需要注意并提醒插件使用者。
+
+Q:component、module的生命周回调 不支持OnActivityCreate(),某些注册服务需要该事件注册怎么办。
+A:component可以在的构造函数中调用相关注册初始化服务等操作, module的构造无法获取到上下文。可能需要换一个思路。通过js调用相关初始化的函数。
+
+Q:打包发现集成的三方库与主APP集成的三方库有冲突。导致无法打包成功?
+
+A:
+
+ + 请尽量使用主APP集成的三方库去实现你的插件依赖集成。请告知使用该插件需要‘XXX’模块才可正常运行。版本号可[查看](https://ask.dcloud.net.cn/article/35419)
+ + 如果集成的三方库无法使用主APP集成的三方库。请告知插件使用者不要集成‘XXX’模块。防止打包失败。
+
+Q:HX3.0.0+版本云打包编译之前插件无法编译通过。HX2.9.8版本云打包是可以的。
+
+A:
+
+ + 请检查一下之前编译插件的配置`build.gradle`文件。检测是否使用`api files(xxx.aar)`引入某些依赖库aar文件。如果有这样的配置请改为使用compileOnly 修饰。否则无法在3.0.0+编译通过。主要原因就是资源冲突。 `api files(xxx.aar)`这种玩法是错误的。
+ + 检查一下自己插件aar中的`classes.jar`文件。使用压缩工具查看一下`classes.jar`里的文件是否存在资源文件。如`AndroidManifest.xml`、`res`等资源文件需要删除。否则无法在3.0.0+编译通过。
+
+Q:插件SDK部分需要在Application初始化。目前在AppHookProxy中onCreate初始化无效
+
+A: 请使用UniAppHookProxy接口(此处注意!不是AppHookProxy是UniAppHookProxy) 有onSubProcessCreate子进程初始化回调。将SDK需要在Application初始化的代码onCreate和onSubProcessCreate都放一份就可以了。
+
+Q:插件可以重写Application吗?
+
+A:不支持。重写Application存在很多安全隐患。
+
+Q:插件生产文件路径需要注意哪些?
+
+A:
+
++ 插件生成的路径尽量添加`file://`防止路径被转换导致无法正确获取文件
++ 尽量将文件放到`/storage/emulated/0/Android/data/$应用的包名$/apps/$uniapp的appid$/doc/`目录下
+
+Q: 如何查看如何查看uniapp console日志
+
A:修改项目中assets/data/dcloud_control.xml 内部信息。将syncDebug改为true,开启调试模式。 注意正式版需要改为false!!! 查看log.TAG为console
Q: HX3.8.7插件编译失败或运行插件闪退