首先上官方文档:https://nativesupport.dcloud.net.cn/NativePlugin/course/android
下载官方demo:https://nativesupport.dcloud.net.cn/AppDocs/download/android
官方demo的UniPlugin-Hello-AS工程可直接运行,包括了uniplugin_component、uniplugin_module和uniplugin_richalert三个插件例子
官方例子就不多说了,没啥问题,现在记录我自定义的插件的开发过程。
首先尝试用android studio新建空白项目,从零做起。结果,失败。因为uni-app开发安卓插件时,app目录中是没有MainActivity.java的。阅读官方demo的代码,app目录的AndroidManifest.xml中,有很多配置,其应用入口处代码为:
<!-- 应用入口 -->
<activity
android:name="io.dcloud.PandoraEntry"
android:theme="@style/TranslucentTheme"
android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
...(详见官方demo中app的AndroidManifest.xml)
io.dcloud.PandoraEntry就是它的activity,故要按照uni-app的模式开发其插件,AndroidManifest.xml中的配置需要和官方demo一致。
自己改配置总是让人烦躁,索性直接以官方demo为基础项目,在此基础上进行开发。
之后我又解压出一个干净的UniPlugin-Hello-AS工程,删除app示例文件夹,开始开发。
首先项目根目录点右键,新建module:

新建时务必选择Android Library:

然后就是踩到的一个坑,大概是因为官方demo的app的minSdkVersion是19,可以在app目录下的build.gradle中看到:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.HBuilder.UniPlugin"
minSdkVersion 19 ←←←←←←←←←←←← 这里!!
targetSdkVersion 26 //建议此属性值设为21 io.dcloud.PandoraEntry 作为apk入口时 必须设置 targetSDKVersion>=21 沉浸式才生效
versionCode 1
versionName "1.0"
multiDexEnabled true
ndk {
abiFilters 'x86','armeabi-v7a'
}
}
我们在新建Android Library时,如果使用的minimum SDK高于19的话,后面在项目运行时,虽然build不会报错,但是run的时候,会出现我们的应用在手机上打开后马上秒退。可尝试过minimum SDK高于19时,将app目录下的build.gradle中的minSdkVersion 提高到25,buildToolsVersion 提高到30.0.3,但是仍然会出现运行后应用闪退的现象。所以在新建Android Library时,如果是以官方demo为基础工程的话,我建议Android Library的minimum SDK设置为19。
下面我以我新建的:test_module为例再说下后续的开发。
首先需要编写test_module的依赖,直接从官方demo中拷贝一个过来,即修改test_module的build.gradle,其中:
dependencies {
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
compileOnly 'com.android.support:recyclerview-v7:28.0.0'
compileOnly 'com.android.support:support-v4:28.0.0'
compileOnly 'com.android.support:appcompat-v7:28.0.0'
compileOnly 'com.alibaba:fastjson:1.2.75'
compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar'])
compileOnly 'com.alibaba:fastjson:1.2.75'
}
如果有第三方的SDK的jar包需要引入,则直接将jar放到app目录的libs下即可,不需要单独放到test_module的libs下。如果放到了../app/libs之后,jar还是无法识别,可以修改依赖中的:
compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar']),在include数组中直接把你需要的jar写在里面即可:
compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar','xxx.jar'])。
之后为test_module编写插件的java类,我写的是TestModule:

package com.example.test_module;
import com.alibaba.fastjson.JSONObject;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.common.UniModule;
public class TestModule extends UniModule {
@UniJSMethod(uiThread = true)
public void testAsyncFunc(JSONObject params) {
System.out.println("DualScreenModule testAsyncFunc" + params);
}
}
这个类要继承UniModule以及注解@UniJSMethod的使用,看官方文档说明即可,一定一定一定要加注解,否则vue页面无法调用。
类写好后,还需要配置app目录中的dcloud_uniplugins.json,也是详见官方文档,具体位于app目录的src\main\assets\dcloud_uniplugins.json,在其中加上对象:
{
"plugins": [
{
"type": "module",
"name": "TestModule",
"class": "com.example.test_module.TestModule"
}
]
}
最后一步是要在app中引入该插件,修改app目录下的build.gradle,在最后可以看到:
// 添加uni-app插件
implementation project(':uniplugin_component')
implementation project(':uniplugin_module')
implementation project(':uniplugin_richalert')
把我们的test_module也加入即可:
implementation project(':test_module')
这样插件就开发好了,我们去我们的uni-app项目中,在某个页面调用插件即可:

之后就是把uni-app进行离线打包,然后把编译出来的__UNI__EC1Exxx目录拷贝到我们插件工程的app目录的src\main\assets\apps\__UNI__EC1Exxx处,然后再把src\main\assets\data\dcloud_control.xml中的appid修改为__UNI__EC1Exxx:
<hbuilder>
<apps>
<app appid="__UNI__EC1Exxx" appver=""/>
</apps>
</hbuilder>
最后在Android studio中直接运行到手机或者AVD中就行,调用插件时可以在控制台中看到我用标准输出输出的System.out.println("DualScreenModule testAsyncFunc" + params);
完事。
再总结一下,感觉uni-app这个插件开发需要两个工程,一个是在Android Studio中搭建的Android工程,我称之为插件工程,一个是在HbuilderX中搭建的uni-app工程,我称之为页面工程。实际做下来我理解为其实这样混合开发后,插件工程反而成为了主工程,页面工程成了辅工程。我们在页面工程中开发好页面后,需要离线打包,将打包结果全部拷贝到插件工程之中,最终通过插件工程打包成apk发布即可。
下载官方demo:https://nativesupport.dcloud.net.cn/AppDocs/download/android
官方demo的UniPlugin-Hello-AS工程可直接运行,包括了uniplugin_component、uniplugin_module和uniplugin_richalert三个插件例子
官方例子就不多说了,没啥问题,现在记录我自定义的插件的开发过程。
首先尝试用android studio新建空白项目,从零做起。结果,失败。因为uni-app开发安卓插件时,app目录中是没有MainActivity.java的。阅读官方demo的代码,app目录的AndroidManifest.xml中,有很多配置,其应用入口处代码为:
<!-- 应用入口 -->
<activity
android:name="io.dcloud.PandoraEntry"
android:theme="@style/TranslucentTheme"
android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
...(详见官方demo中app的AndroidManifest.xml)
io.dcloud.PandoraEntry就是它的activity,故要按照uni-app的模式开发其插件,AndroidManifest.xml中的配置需要和官方demo一致。
自己改配置总是让人烦躁,索性直接以官方demo为基础项目,在此基础上进行开发。
之后我又解压出一个干净的UniPlugin-Hello-AS工程,删除app示例文件夹,开始开发。
首先项目根目录点右键,新建module:

新建时务必选择Android Library:

然后就是踩到的一个坑,大概是因为官方demo的app的minSdkVersion是19,可以在app目录下的build.gradle中看到:
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion '28.0.3'
defaultConfig {
applicationId "com.HBuilder.UniPlugin"
minSdkVersion 19 ←←←←←←←←←←←← 这里!!
targetSdkVersion 26 //建议此属性值设为21 io.dcloud.PandoraEntry 作为apk入口时 必须设置 targetSDKVersion>=21 沉浸式才生效
versionCode 1
versionName "1.0"
multiDexEnabled true
ndk {
abiFilters 'x86','armeabi-v7a'
}
}
我们在新建Android Library时,如果使用的minimum SDK高于19的话,后面在项目运行时,虽然build不会报错,但是run的时候,会出现我们的应用在手机上打开后马上秒退。可尝试过minimum SDK高于19时,将app目录下的build.gradle中的minSdkVersion 提高到25,buildToolsVersion 提高到30.0.3,但是仍然会出现运行后应用闪退的现象。所以在新建Android Library时,如果是以官方demo为基础工程的话,我建议Android Library的minimum SDK设置为19。
下面我以我新建的:test_module为例再说下后续的开发。
首先需要编写test_module的依赖,直接从官方demo中拷贝一个过来,即修改test_module的build.gradle,其中:
dependencies {
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
compileOnly 'com.android.support:recyclerview-v7:28.0.0'
compileOnly 'com.android.support:support-v4:28.0.0'
compileOnly 'com.android.support:appcompat-v7:28.0.0'
compileOnly 'com.alibaba:fastjson:1.2.75'
compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar'])
compileOnly 'com.alibaba:fastjson:1.2.75'
}
如果有第三方的SDK的jar包需要引入,则直接将jar放到app目录的libs下即可,不需要单独放到test_module的libs下。如果放到了../app/libs之后,jar还是无法识别,可以修改依赖中的:
compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar']),在include数组中直接把你需要的jar写在里面即可:
compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar','xxx.jar'])。
之后为test_module编写插件的java类,我写的是TestModule:

package com.example.test_module;
import com.alibaba.fastjson.JSONObject;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.common.UniModule;
public class TestModule extends UniModule {
@UniJSMethod(uiThread = true)
public void testAsyncFunc(JSONObject params) {
System.out.println("DualScreenModule testAsyncFunc" + params);
}
}
这个类要继承UniModule以及注解@UniJSMethod的使用,看官方文档说明即可,一定一定一定要加注解,否则vue页面无法调用。
类写好后,还需要配置app目录中的dcloud_uniplugins.json,也是详见官方文档,具体位于app目录的src\main\assets\dcloud_uniplugins.json,在其中加上对象:
{
"plugins": [
{
"type": "module",
"name": "TestModule",
"class": "com.example.test_module.TestModule"
}
]
}
最后一步是要在app中引入该插件,修改app目录下的build.gradle,在最后可以看到:
// 添加uni-app插件
implementation project(':uniplugin_component')
implementation project(':uniplugin_module')
implementation project(':uniplugin_richalert')
把我们的test_module也加入即可:
implementation project(':test_module')
这样插件就开发好了,我们去我们的uni-app项目中,在某个页面调用插件即可:

之后就是把uni-app进行离线打包,然后把编译出来的__UNI__EC1Exxx目录拷贝到我们插件工程的app目录的src\main\assets\apps\__UNI__EC1Exxx处,然后再把src\main\assets\data\dcloud_control.xml中的appid修改为__UNI__EC1Exxx:
<hbuilder>
<apps>
<app appid="__UNI__EC1Exxx" appver=""/>
</apps>
</hbuilder>
最后在Android studio中直接运行到手机或者AVD中就行,调用插件时可以在控制台中看到我用标准输出输出的System.out.println("DualScreenModule testAsyncFunc" + params);
完事。
再总结一下,感觉uni-app这个插件开发需要两个工程,一个是在Android Studio中搭建的Android工程,我称之为插件工程,一个是在HbuilderX中搭建的uni-app工程,我称之为页面工程。实际做下来我理解为其实这样混合开发后,插件工程反而成为了主工程,页面工程成了辅工程。我们在页面工程中开发好页面后,需要离线打包,将打包结果全部拷贝到插件工程之中,最终通过插件工程打包成apk发布即可。