Android 开发 集成 uni 小程序,并实现相互通信
前言
本文主要实现在Android环境下以wgt包的形式集成uni小程序,并实现小程序跟安卓宿主之间的相互通信,主要包括安卓宿主集成uni小程序的SDK,安卓项目准备,导入依赖,资源配置,uniapp的打包,导入等注意事项
一、Android 集成 uni 小程序
1 下载uni小程序的SDK
点击红色箭头即跳转到下载链接 官方SDK 官方集成文档
2 创建安卓项目
下面我们创建一个项目,项目的名称和包名你自己设置就可以了,项目创建完成,我们先通过手机真机运行一下,检查是否能正常运行。当你看到手机上出现Hello World!
就表示你的项目没有问题,
如果运行失败,报 gradle 下载失败,则是 gradle 下载源导致的 替换下国内腾讯云的镜像服务器地址
在app 目录下新建libs文件夹
3 添加uniSDK基础依赖及文件
Libs文件夹中的依赖库
是不用全部都集成到宿主项目中。除视频、地图、分享、支付、登录、直播pusher等SDK,只集成基础模块如下:
把以上aar包复制到项目里 如下 注意:minSdkVersion 必须是19以上 导入aar需要新增配置
defaultConfig {applicationId "com.summer.my35"minSdkVersion 23 // uniapp必须是19及以上targetSdkVersion 31versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}
注意 此处配置必须添加 否则UNI无法正确运行
//此处配置必须添加 否则UNI无法正确运行aaptOptions {additionalParameters '--auto-add-overlay'//noCompress 'foo', 'bar'ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"}
在新版本的 build.gradle 的 dependencies 中 依赖声明方式 发生了改变 新版方式为
libs.xxx , 这是 Android Studio 近年来引入的 Version Catalog(版本目录)管理方式。
所有依赖的坐标(如androidx.appcompat:appcompat
)和版本号(如1.6.1)都统一定义在项目的 libs.versions.toml ,
在build.gradle
中只需通过libs.xxx
引用,无需重复写版本号。
而新版中也无需再 build.gradle 中 导入aar 配置 ,而是在 setting.gradle 中 配置
新版旧版还有很多不习惯的地方,也只有慢慢在项目中碰 ,再去熟悉
最终的buid.gradle为
plugins {alias(libs.plugins.android.application)
}android {namespace 'com.example.my35'compileSdk 35defaultConfig {applicationId "com.example.my35"minSdk 21 // uniapp必须是19及以上targetSdk 35versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"}//此处配置必须添加 否则UNI无法正确运行aaptOptions {additionalParameters '--auto-add-overlay'//noCompress 'foo', 'bar'ignoreAssetsPattern "!.svn:!.git:.*:!CVS:!thumbs.db:!picasa.ini:!*.scc:*~"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}compileOptions {sourceCompatibility JavaVersion.VERSION_11targetCompatibility JavaVersion.VERSION_11}
}dependencies {implementation libs.appcompatimplementation libs.materialimplementation libs.activityimplementation libs.constraintlayouttestImplementation libs.junitandroidTestImplementation libs.ext.junitandroidTestImplementation libs.espresso.coreimplementation(name: 'android-gif-drawable-1.2.28', ext: 'aar')implementation(name: 'base_oaid_sdk', ext: 'aar')implementation(name: 'breakpad-build-release', ext: 'aar')implementation(name: 'DCUniMPSDK-V2-release', ext: 'aar')implementation(name: 'uniapp-v8-release', ext: 'aar')implementation 'androidx.recyclerview:recyclerview:1.0.0' //必须集成,android 自带recyclerview支持implementation 'androidx.legacy:legacy-support-v4:1.0.0' //必须集成,androidx support支持implementation 'androidx.appcompat:appcompat:1.0.0' //必须集成,androidx appcompat支持implementation 'com.alibaba:fastjson:1.2.83' //必须集成,fastjson功能需要implementation 'com.facebook.fresco:fresco:2.5.0'//必须集成,图片加载需要implementation 'com.facebook.fresco:animated-gif:2.5.0'//必须集成,图片加载需要implementation 'com.github.bumptech.glide:glide:4.9.0'//必须集成,图片加载需要implementation 'androidx.webkit:webkit:1.5.0' //4.45版本之后 必须集成,用来支持暗黑模式
}
拷贝 DEMO 下的 assets 文件夹到自己项目中 ,其中apps 文件夹下为小程序wgt包,data下不要动,每次更新wgt包就好
4 初始化uniSDK
开发者需要在Application
的OnCreate
方法内,调用DCUniMPSDK.getInstance().initialize 进行初始化。
在项目下新建全局初始化类Myapplication 继承 Application 并在AndroidManifest 中 引用
public class Myapplication extends Application {private Myapplication instance;@Overridepublic void onCreate() {super.onCreate();instance = this;/*** 初始化uniMPSDK*/MenuActionSheetItem item = new MenuActionSheetItem("关于", "gy");List<MenuActionSheetItem> sheetItems = new ArrayList<>();sheetItems.add(item);DCSDKInitConfig config = new DCSDKInitConfig.Builder().setCapsule(true)//设置是否使用胶囊按钮.setMenuDefFontSize("16px")//设置菜单默认按钮字体大小.setMenuDefFontColor("#ff00ff")//设置菜单默认按钮文字有颜色.setMenuDefFontWeight("normal")//设置菜单默认按钮上文字的粗细.setMenuActionSheetItems(sheetItems)//设置默认菜单按钮items.setEnableBackground(false)//设置小程序退出时是否进入后台.build();DCUniMPSDK.getInstance().initialize(this, config);}
}
5 启动uni小程序
修改 activity_main 布局文件
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"xmlns:tools="http://schemas.android.com/tools"android:layout_width="match_parent"android:layout_height="match_parent"android:gravity="center"tools:context=".MainActivity"><Buttonandroid:id="@+id/qd_btn"android:layout_width="wrap_content"android:layout_height="wrap_content"android:text="启动小程序" />
</LinearLayout>
修改 MainActivity
package com.example.my35;import android.annotation.SuppressLint;
import android.os.Bundle;
import android.view.View;import androidx.appcompat.app.AppCompatActivity;import io.dcloud.feature.sdk.DCUniMPSDK;
import io.dcloud.feature.unimp.config.UniMPOpenConfiguration;public class MainActivity extends AppCompatActivity {private UniMPOpenConfiguration uniMPOpenConfiguration;@SuppressLint("MissingInflatedId")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.qd_btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {DCUniMPSDK.getInstance().openUniMP(MainActivity.this, "__UNI__F743940");} catch (Exception e) {e.printStackTrace();}}});}
}
最终如下,到这里 Android 原生 以wgt 包的形式集成uni 小程序就成功了
二、 uni小程序 打 wgt 包
上一篇已经讲过uni的网络请求,咱试着把上一篇的小程序打包完植入这一篇的安卓宿主里
1.制作wgt包
鼠标点击到你的项目上再点击 ---> 发行 ---> 找到App-制作应用wgt包 (G)
然后会弹出一下弹窗,不用修改直接点击确定,控制台就会编译中,稍等一会等待制作完成
等待控制台编译完成,点击输出路径进入
这时就能看见已打好的wgt包
然后选中右键重命名修改尾部格式为zip点击是
最后的得到一个压缩包,然后选中右键选择 压到"__UNI__316E08D\",
双击进入新建一个文件夹命名为 www ,然后把所有的文件都移动到这个文件夹下
最后复制解压完的文件夹 __UNI__316E08D 移动到 宿主app下的 apps 中,然后启动时替换appid即可
点击启动即可,但是每次启动都会弹出版本不匹配很是烦人,这样咱设置一下兼容模式即可,如下图
"compatible": { //uni-app兼容模式"ignoreVersion": false,"runtimeVersion": "4.75", //字符串类型,兼容的uni-app运行环境版本号,多个版本使用,分割"compilerVersion": "4.76" //字符串类型,兼容的编译器版本号}
三、 安卓原生与小程序之间通信
宿主与小程序通讯适用于简单的数据交互。如果希望小程序调用宿主提供的API方法,实现复杂扩展能力请使用Android原生扩展实现
1 uniApp发送消息给安卓
uni.sendNativeEvent("aa", this.uniData, (e) => {this.uniData = e;});
在安卓宿主Myapplication接收,多用途可自行封装,再此只做示例
//安卓接收数据并发送回调DCUniMPSDK.getInstance().setOnUniMPEventCallBack(new IOnUniMPEventCallBack() {@Overridepublic void onUniMPEventReceive(String appId, String event, Object data, DCUniMPJSCallback callback) {Log.d("c--s", "onUniMPEventReceive event=" + event);callback.invoke("测试数据");}});
2 安卓发送消息给uniApp
在跳转到小程序时发送数据 iUniMP ,注意:需要先获取iUniMP接口对象!可通过openUniMP获取IUniMP接口对象
JSONObject data = new JSONObject();data.put("sj", "点击了关于");iUniMP.sendUniMPEvent("gy", data);
在uni接收为
//uni小程序JS代码 监听宿主触发给小程序的事件uni.onNativeEventReceive(function(event, data) {this.nativeMsg = event + " data: " + data;});
3 完整代码
安卓
public class MainActivity extends AppCompatActivity {private UniMPOpenConfiguration uniMPOpenConfiguration;@SuppressLint("MissingInflatedId")@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);findViewById(R.id.qd_btn).setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {try {uniMPOpenConfiguration = new UniMPOpenConfiguration();uniMPOpenConfiguration.extraData.put("darkmode", "Hello uni microprogram");IUniMP iUniMP = DCUniMPSDK.getInstance().openUniMP(MainActivity.this, "__UNI__316E08D", uniMPOpenConfiguration);JSONObject data = new JSONObject();data.put("sj", "点击了关于");iUniMP.sendUniMPEvent("gy", data);} catch (Exception e) {e.printStackTrace();}}});}
public class Myapplication extends Application {private Myapplication instance;@Overridepublic void onCreate() {super.onCreate();instance = this;/*** 初始化uniMPSDK*/MenuActionSheetItem item = new MenuActionSheetItem("关于", "gy");List<MenuActionSheetItem> sheetItems = new ArrayList<>();sheetItems.add(item);DCSDKInitConfig config = new DCSDKInitConfig.Builder().setCapsule(true)//设置是否使用胶囊按钮.setMenuDefFontSize("16px")//设置菜单默认按钮字体大小.setMenuDefFontColor("#ff00ff")//设置菜单默认按钮文字有颜色.setMenuDefFontWeight("normal")//设置菜单默认按钮上文字的粗细.setMenuActionSheetItems(sheetItems)//设置默认菜单按钮items.setEnableBackground(false)//设置小程序退出时是否进入后台.build();DCUniMPSDK.getInstance().initialize(this, config);//安卓接收数据并发送回调DCUniMPSDK.getInstance().setOnUniMPEventCallBack(new IOnUniMPEventCallBack() {@Overridepublic void onUniMPEventReceive(String appId, String event, Object data, DCUniMPJSCallback callback) {Log.d("c--s", "onUniMPEventReceive event=" + event);callback.invoke("测试数据");}});}
}
uni
<template><view><!-- 显示加载状态 --><!-- <view v-if="loading" class="loading">{{ tooltips.loading }}</view> --><!-- 显示Bing图片 --><!-- <image v-else :src="fullImageUrl" mode="widthFix" class="bing-image"></image> --><button class="btn" @click="showToast1" type="primary">安卓发送消息给uniApp</button><button class="btn" @click="showToast2" type="primary">uniApp发送消息给安卓</button></view>
</template><script>export default {data() {return {// loading: true, // 加载状态// fullImageUrl: "", // 拼接后的完整图片URLuniData: "",nativeMsg: ""};},onShow() {uni.sendNativeEvent("aa", this.uniData, (e) => {this.uniData = e;});},onLoad(options) {//uni小程序JS代码 监听宿主触发给小程序的事件uni.onNativeEventReceive(function(event, data) {this.nativeMsg = event + " data: " + data;});// uni.showLoading({// title: '请稍后',// mask: true // 防止用户重复操作// });// this.fetchBingImage()// .finally(() => {// this.loading = false; // 确保 loading 被关闭// uni.hideLoading(); // 无论成功失败都关闭加载框// });},methods: {showToast1() {uni.showToast({title: this.nativeMsg,mask: true});},showToast2() {uni.showToast({title: this.uniData,mask: true});}// fetchBingImage() {// return this.$api.byImageList()// .then(res => {// console.log("请求成功:", res);// console.log('images 数组:', res.data.images);// // 2. 提取 images 数组的第一项// const imageData = res.data.images[0];// console.log('images图片:', imageData.url);// // 3. 拼接完整URL(http://cn.bing.com + url)// this.fullImageUrl = `https://cn.bing.com${imageData.url}`;// console.log('images图片地址:', this.fullImageUrl);// })// .catch(err => {// // 此时的err只可能是:HTTP错误、解析异常、业务失败(result≠0000)// console.error("请求失败:", err);// uni.showToast({// title: err.error || err.timeout ? '请求超时' : '请求失败',// icon: 'none',// duration: 2000// });// return Promise.reject(err); // 继续抛出,供上层处理// });// }}};
</script><style>/* .loading {font-size: 16px;color: #999;text-align: center;margin-top: 50px;}.bing-image {width: 100%;height: auto;} */.btn {margin-left: 20rpx;margin-right: 20rpx;margin-top: 20rpx;}.text {margin-left: 20rpx;margin-right: 20rpx;margin-top: 20rpx;}
</style>
最后贴一下gif 图片
但是现在遇见一个问题,就是安卓再打开小程序时传参,在小程序这边接不到,如有知晓感谢评论指出问题所在,谢谢
总结
对于新鲜事物要敢于面对,走出舒适圈,今天就到这吧