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

相关推荐
Henry_He1 小时前
桌面列表小部件不能点击的问题分析
android
工程师老罗1 小时前
Android笔试面试题AI答之Android基础(1)
android
qq_397562313 小时前
android studio更改应用图片,和应用名字。
android·ide·android studio
峥嵘life3 小时前
Android Studio版本升级那些事
android·ide·android studio
新手上路狂踩坑3 小时前
Android Studio的笔记--BusyBox相关
android·linux·笔记·android studio·busybox
TroubleMaker5 小时前
OkHttp源码学习之retryOnConnectionFailure属性
android·java·okhttp
何极光6 小时前
uniapp小程序样式穿透
前端·小程序·uni-app
叶羽西7 小时前
Android Studio IDE环境配置
android·ide·android studio
发飙的蜗牛'7 小时前
23种设计模式
android·java·设计模式
花追雨17 小时前
Android -- 双屏异显之方法一
android·双屏异显