前言
上周刚完成uniapp原生插件的开发调试,正兴冲冲地去上架,结果竟告知官方不再接收原生插件了!TNND,我搞了几天,到最后发现做的都是无用功 /(ㄒoㄒ)/~~
莫得办法,谁让人家是官方呢,研究uts插件吧!不看不知道,一看都是坑,人家是摸着石头过河,我简直是摸着河床过河!这UTS语法简直了!!!
技术前提:
首先你要了解安卓的AIDL ,其次要了解Kotlin 语言,因为UTS 和Kotlin很像,学起来不至于你崩溃😆
参考文章:
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