uniapp uts插件实现AIDL与原生安卓通信

前言

上周刚完成uniapp原生插件的开发调试,正兴冲冲地去上架,结果竟告知官方不再接收原生插件了!TNND,我搞了几天,到最后发现做的都是无用功 /(ㄒoㄒ)/~~

莫得办法,谁让人家是官方呢,研究uts插件吧!不看不知道,一看都是坑,人家是摸着石头过河,我简直是摸着河床过河!这UTS语法简直了!!!

技术前提:

首先你要了解安卓的AIDL ,其次要了解Kotlin 语言,因为UTSKotlin很像,学起来不至于你崩溃😆

参考文章:
uniapp Android 原生插件开发(Module 扩展为例·2022)

uts插件开发-继uniapp原生插件nativeplugins,uts插件开发可直接操作原生安卓sdk等,支持uniappx,支持源码授权价格等等-此片文章写的是基础的uts插件,原生相机拍照和回调

官方文档:
UTS插件介绍
uts for Android

话不多说,来吧,跟随我的脚步,直接开搂!

开始


环境创建项目等简单步骤都不讲了,可以参照上面 参考文章中的两个链接,如果从0开始说,步骤太繁琐了,并且上面两个文章已经尽可能详细了。

根据 这篇文章 uts插件开发 创建完项目后,就可以直接编写uts插件代码了,

一般开发AIDL的时候,都会将AIDL相关的公共代码打包成.aar文件,方便别的项目使用,大致结构如下:

bash 复制代码
ProjectRoot/
├── app/                                // 主应用模块
│   ├── src/
│   │   ├── main/
│   │   │   ├── AndroidManifest.xml
│   │   │   ├── java/
│   │   │   │   └── com.example.app/   // 主应用的代码
│   │   │   └── res/
│   └── build.gradle                    // 主模块的 Gradle 配置
├── aidlmodule/                         // AIDL 模块 (生成 .aar 文件)
│   ├── src/
│   │   ├── main/
│   │   │   ├── aidl/
│   │   │   │   └── com.example.aidl/
│   │   │   │       └── IRemoteService.aidl   // AIDL 文件
│   │   │   ├── java/
│   │   │   │   └── com.example.aidl/   // AIDL 相关的 Java 文件
│   │   │   ├── AndroidManifest.xml
│   │   │   └── res/                    // 资源文件
│   └── build.gradle                    // AIDL 模块的 Gradle 配置
└── build.gradle                        // 根项目的 Gradle 配置

在uts中也可以将 将jar/aar 添加到 utssdk/app-android/libs 目录下直接使用,可以参考官方 hello uts 项目示例,注意是直接使用,复制进去后不用额外配置。

当然如果使用标准基座进行调试的话,你只能获取到.aar文件中的公开常量,如果要获取相关类的话,就会报错,提示:
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.xxx.xxx.IBaseServiceInterface$Stub" on path: DexPathList[[dex file...

真的很神奇,你能获取到里面的静态变量,却无法获取到类,这个问题让我反复搞了一天,快下班的时候打完了自定义基座,再尝试一下才能成功获取到aar 包中的类,打包自定义基座可以参考这篇文章:uniapp Android 原生插件开发(Module 扩展为例·2022) ,真是快崩溃的时候,又给了你希望!😒

既然aar 包可以正常使用了,那就开始写绑定服务代码吧,由于第一次接触UTS语言,只能边学边写,参照着原生的实现方式,一行代码一行代码地写,TNND,真是全程边骂边写完的,看完官方文档和没看差不多,写一行代码报错一行,举步维艰,好久才把绑定服务连接接口实现出来,看下面代码是不是很熟悉,很像Kotlin,但你真写起来,感觉像个四不像😆

uts 复制代码
class BaseServiceConnection implements ServiceConnection {
	onServiceConnected(name : ComponentName, service : IBinder) : void {
		console.log("onResponse---onServiceConnected--" + service.interfaceDescriptor);

		serviceInterface = IBaseServiceInterface.Stub.asInterface(service);
	}

	onServiceDisconnected(name : ComponentName) : void {
		console.log("onResponse---onServiceDisconnected---");
		serviceInterface = null;
	}
}

这里实现接口不用写 override ,但继承类时重写方法需要加上 override

注意: 在HX中写aar包相关类和属性是没有提示的,导包也需要手动导包,不然编译时会报错,例如:

bash 复制代码
import ServiceConnection from 'android.content.ServiceConnection';
import IBinder from 'android.os.IBinder';
import ComponentName from 'android.content.ComponentName';

这些是系统自带的类,你编写时会有提示,按照提示点回车可以自动导包,但是不是系统自带的就需要一个一个手动操作了,例如:

bash 复制代码
import AidlRequest from 'com.xxx.xxx.AidlRequest';
import BaseRequest from 'com.xxx.xxx.BaseRequest';
import BaseResponse from 'com.xxx.xxx.BaseResponse';
import IBaseServiceInterface from 'com.xxx.xxxx.IBaseServiceInterface';
import IBaseServiceCallback from 'com.xxx.xxxx.IBaseServiceCallback';

新手体验贼不好,差评!

绑定服务代码如下,参照着原生的来:

uts 复制代码
	public static bindService() {
		var intent = new Intent("xxxxxxxxxxx")
		intent.setPackage("xxxxxxxxxx")
		var bind = UTSAndroid.getAppContext()?.bindService(intent, new BaseServiceConnection(), Context.BIND_AUTO_CREATE)
		console.log("bindService " + bind)
	}

注意,如果使用到aar 包相关类时,别忘记导包哦!运行UTS代码,可以参考上面这篇文章 uts插件开发index.uts(即uts插件)文件写完暴露接口后,在index.vue中导入要使用的插件

bash 复制代码
import { myApi } from "../../uni_modules/xxx-xxx";

然后就可以直接调用 myApi 方法了,myApi 为官方自动生成的暴露示例方法,index.uts有使用说明,运行即可成功绑定服务。

bash 复制代码
export const myApi : MyApi = function (options : MyApiOptions) {
	if (options.paramA == true) {
		// 返回数据
		const res : MyApiResult = {
			fieldA: 85,
			fieldB: true,
			fieldC: 'some message'
		};
		options.success?.(res);
		options.complete?.(res);
	} else {
		// 返回错误
		const err = new MyApiFailImpl(9010001);
		options.fail?.(err)
		options.complete?.(err)
	}
}

至于将回调的数据返回到界面,仍可以参考官方的 myApi 示例方法,大致就是先在interface.uts中定义接口,上面代码中 : MyApi 就是定义的接口,定义完需要引入下,你加入新的方法 在{ }中添加即可。

bash 复制代码
/* 引入 interface.uts 文件中定义的变量 */
import { MyApiOptions, MyApiResult, MyApi, MyApiSync } from '../interface.uts';

放心,有示例你也会出错的,慢慢来,最后都能解决的😁

AIDL回调:

bash 复制代码
class AidlCallback extends IBaseServiceCallback.Stub() {
	override onResponse(json : String) : void {
		xxx.options?.response?.(json);
		console.log("AidlCallback onResponse :" + json)
	}
}

还有一需要注意,就是uts喜欢在调用方法时加上 ?.,比如 正常情况下 调用一个不为null的方法 写法是options?.response(json) 但是在uts中就编译不过,必须这样写: options?.response?.(json)

还有,你传进来一个不为null的对象,在调用时也必须加上 ?,否则不单报错而且报错内容你都看不懂是这个原因,例如:

bash 复制代码
	public static bindService(callback : BindCallback) {
		callback?.result?.(true);
	}

最后


写完回头一看,其实也不是很麻烦,但是步步踩雷谁能受得了啊🤣,再会!

另外给喜欢记笔记的同学安利一款好用的云笔记软件,对比大部分国内的这个算还不错的,免费好用:wolai

相关推荐
DONSEE广东东信智能读卡器7 小时前
蓝牙身份证阅读器使用Uniapp调用二次开发demo
javascript·uni-app·蓝牙·身份证阅读器
潜龙95277 小时前
第3.2.3节 Android动态调用链路的获取
android·调用链路
追随远方8 小时前
Android平台FFmpeg音视频开发深度指南
android·ffmpeg·音视频
撰卢9 小时前
MySQL 1366 - Incorrect string value:错误
android·数据库·mysql
恋猫de小郭9 小时前
Flutter 合并 ‘dot-shorthands‘ 语法糖,Dart 开始支持交叉编译
android·flutter·ios
牛马程序小猿猴9 小时前
15.thinkphp的上传功能
android
林家凌宇10 小时前
Flutter 3.29.3 花屏问题记录
android·flutter·skia
时丶光10 小时前
Android 查看 Logcat (可纯手机方式 无需电脑)
android·logcat
血手人屠喵帕斯10 小时前
事务连接池
android·adb
恋猫de小郭11 小时前
React Native 前瞻式重大更新 Skia & WebGPU & ThreeJS,未来可期
android·javascript·flutter·react native·react.js·ios