记一次uni-app Android原生插件开发
背景
项目使用到了RFID射频手持设备(PDA),用于读取羊只耳标功能。原来有写过一个插件
https://
ext.dcloud.net.cn/plugi
n?id=5246
之前没有记录,这次重新记录下过程。
使用的硬件设备Demo 为:uhfg_v2.2.10;
资料
原生插件开发资料官方:
https://
nativesupport.dcloud.net.cn
/NativePlugin/README
步骤
1.下载App离线SDK及demo导入
https://
nativesupport.dcloud.net.cn
/AppDocs/download/android
下载后有对应的工程文件,需要使用Android Studio导入。
我下载的是 3.5.0,目录结构是:
我们将UniPlugin-Hello-AS导入到Android Studio 中。
导入后目录结构是这样的:
我做的项目是使用原生的扫描耳标的能力,不需要界面,所以插件是 扩展 Module 的形式。
2.新建module uhfg模块
3.导入uhf的库及配置build.gradle
uhfg模块 的build.gradle
plugins {
id 'com.android.library'
}
android {
signingConfigs {
release {
}
}
compileSdkVersion 30
defaultConfig {
minSdkVersion 21
targetSdkVersion 30
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
consumerProguardFiles "consumer-rules.pro"
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
}
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
// implementation 与 compileOnly在编译时候有区别
compileOnly fileTree(dir: 'libs', include: ['*.jar'])
compileOnly fileTree(dir: 'https://zhuanlan.zhihu.com/app/libs', include: ['uniapp-v8-release.aar'])
compileOnly 'androidx.recyclerview:recyclerview:1.1.0'
compileOnly 'androidx.legacy:legacy-support-v4:1.0.0'
compileOnly 'androidx.appcompat:appcompat:1.2.0'
implementation 'com.alibaba:fastjson:1.1.46.android'
implementation 'com.facebook.fresco:fresco:1.13.0'
// implementation files('libs/reader.jar')
// implementation files('libs/ModuleAPI_J.jar')
// implementation files('libs/UHF67_v1.0.3.jar')
// implementation files('libs/App_Demo_API.jar')
// implementation files('libs/DeviceAPIver20150204.jar')
// implementation files('libs/logutil-1.5.1.1.jar')
}
复制代码
4.编写工具类
UHFGUtil.java
package com.nmbaiyun.yangrong.uhfg;
import android.os.Handler;
import android.util.Log;
import com.handheld.uhfr.UHFRManager;
import com.uhf.api.cls.Reader;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import cn.pda.serialport.Tools;
// 单例模式,确保不多次初始化manager
public class UHFGUtil {
private static UHFGUtil instance = new UHFGUtil();
//唯一可用的对象
public static UHFGUtil getInstance(){
return instance;
}
private UHFGUtil(){
initManager();
}
public UHFRManager manager;//uhf
public void initManager(){
if(manager == null){
manager = UHFRManager.getInstance();
}else{
Log.e("UHFRUntil","UHFRManager 已经被初始化了!");
}
}
public void close(){
manager.close();
}
// 3次汇总统计
public void count(UHFGUtilListenner listenner, int delys){
Log.e("UHFRUntil","开始计数");
if (delys == 0){
delys = 1000;
}
int times = 0;
Set<String> allDevices = new HashSet<String>();
while (times <3){
times +=1;
manager.asyncStartReading();
try {
int finalTimes = times;
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// tagInventoryByTimer
List<Reader.TAGINFO> list = manager.tagInventoryRealTime();
// Log.i("scan", list.size()+"__"+list1.size()+"__"+list2.size());
manager.asyncStopReading();
if(list.size()>0){
Log.i("scan", list.get(0).toString());
for (Reader.TAGINFO tfs : list) {
byte[] epcdata = tfs.EpcId;
String data = Tools.Bytes2HexString(epcdata, epcdata.length);
allDevices.add(data);
// int rssi = tfs.RSSI;
// Message msg = new Message();
// msg.what = 1;
// Bundle b = new Bundle();
// b.putString("data", data);
// b.putString("rssi", rssi + "");
// msg.setData(b);
//
// datas += k + ".设备数据是:"+data+" "+rssi+"\r\n";
// k++;
}
}
if (finalTimes >= 3 && listenner != null){
listenner.callBackResult(allDevices.size(),allDevices);
}
}
},delys);
}catch (Exception e){
manager.asyncStopReading();
}
}
}
// 一组耳标
public void getRFIDs(UHFGUtilListenner listenner){
manager.asyncStartReading();
Set<String> allDevices = new HashSet<String>();
try {
new Handler().postDelayed(new Runnable() {
@Override
public void run() {
// tagInventoryByTimer
List<Reader.TAGINFO> list = manager.tagInventoryRealTime();
// Log.i("scan", list.size()+"__"+list1.size()+"__"+list2.size());
manager.asyncStopReading();
if(list.size()>0){
Log.i("scan", list.get(0).toString());
for (Reader.TAGINFO tfs : list) {
byte[] epcdata = tfs.EpcId;
String data = Tools.Bytes2HexString(epcdata, epcdata.length);
allDevices.add(data);
// int rssi = tfs.RSSI;
// Message msg = new Message();
// msg.what = 1;
// Bundle b = new Bundle();
// b.putString("data", data);
// b.putString("rssi", rssi + "");
// msg.setData(b);
//
// datas += k + ".设备数据是:"+data+" "+rssi+"\r\n";
// k++;
}
}
if ( listenner != null){
listenner.callBackResult(allDevices.size(),allDevices);
}
}
},500);
}catch (Exception e){
manager.asyncStopReading();
}
}
/**
*
* @return
* @throws InterruptedException
*/
public String getSyncRFID() {
String data = "";
try{
manager.asyncStartReading();
Thread.sleep(300);
List<Reader.TAGINFO> list = manager.tagInventoryRealTime();
if(list.size()>0) {
Log.i("getSyncRFID", list.get(0).toString());
for (Reader.TAGINFO tfs : list) {
byte[] epcdata = tfs.EpcId;
data = Tools.Bytes2HexString(epcdata, epcdata.length);
}
}
manager.asyncStopReading();
return data;
}catch (Exception e){
Log.e("getSyncRFID",e.getMessage());
return data;
}
}
// 设备读写功率
/**
* 设备读写功率,功率越大越费电,可监测范围越远
* @return
*/
public String getPower(){
int [] result = manager.getPower();
if(result != null){
return "读功率:"+result[0]+" 写功率:"+result[1];
}
return "失败";
}
/**
* 设置设备读写功率
* @param readPower 5~30
* @param writePower 5~30
* @return
*/
public Boolean setPower(int readPower, int writePower){
Reader.READER_ERR err = manager.setPower(readPower,writePower);
return err == Reader.READER_ERR.MT_OK_ERR;
}
}
复制代码
UHFGUtilListenner.java
package com.nmbaiyun.yangrong.uhfg;
import java.util.Set;
public interface UHFGUtilListenner {
public void callBackResult(int num, Set<String> list);
}
复制代码
5.编写model类
package com.nmbaiyun.yangrong.uhfg;
import android.util.Log;
import com.alibaba.fastjson.JSONObject;
import java.util.Set;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;
public class UHFGUtilModule extends UniModule {
String TAG = "UHFGUnitModule";
public static int REQUEST_CODE = 1000;
// 计数中
boolean isCounting = false;
@UniJSMethod(uiThread = false)
public void getSyncRFID(UniJSCallback callback) {
if(callback != null) {
String rfid = "";
JSONObject data = new JSONObject();
try {
UHFGUtil until = UHFGUtil.getInstance();
rfid = until.getSyncRFID();
data.put("code", "200");
data.put("data",rfid);
callback.invoke(data);
}catch (Exception e){
data.put("code", "400");
data.put("msg","异常"+e.getMessage());
callback.invoke(data);
}
}else {
Log.i(TAG,"未传回调函数");
}
}
@UniJSMethod(uiThread = false)
public void asyncCount(UniJSCallback callback){
if(callback != null) {
String rfid = "";
JSONObject data = new JSONObject();
try {
if(isCounting) {
return;
}
UHFGUtil until = UHFGUtil.getInstance();
until.count(new UHFGUtilListenner() {
@Override
public void callBackResult(int num, Set<String> list) {
Log.i(TAG+"toGetAllDevices",num+""+list.toString());
isCounting = false;
data.put("code", "200");
data.put("msg","数据成功");
data.put("total",num);
data.put("data",list);
callback.invoke(data);
}
},500);
}catch (Exception e){
data.put("code", "400");
data.put("msg","异常"+e.getMessage());
callback.invoke(data);
}
}else {
Log.i(TAG,"未传回调函数");
}
}
@UniJSMethod(uiThread = false)
public JSONObject getPower(){
UHFGUtil until = UHFGUtil.getInstance();
String res = until.getPower();
JSONObject data = new JSONObject();
data.put("code", "200");
data.put("data",res);
return data;
}
}
复制代码
6.打包插件
选择Android studio上的gradle工具,使用assembleRelease 的方式进行编译,构建。最后会在当前库下生成 build文件夹,在outputs/aar 生成 arr文件。
然后将 arr文件+libs+.os文件重新放在一起,构建成uni-app所需的原生插件。到此,原生插件开发完成。
目录结构:
7.引入项目
本地引入
在项目下创建目录 nativeplugins 将插件包放在该目录下,插件结构参考前文。
在manifest 中配置本地插件;
配置完成后,需要打包为自定义基座才能使用。
云端插件
将插件发布到云市场,然后就可以通过使用云端插件的方式使用。同样,测试时候需要打包自定义基座。
8.web端调用代码
var modal = uni.requireNativePlugin('Taric-UHFG');
modal.getSyncRFID(function(res) {
that.animals = Array.from(new Set(that.animals.concat(res.data)))
that.amount = that.animals.length;
that.nodocAnimals = that.animals;
});
复制代码
其他的坑及参考
- 1.Android studio gradle 无法用Tasks assembleRelease 打包库
解决方案:
https://blog.csdn.net/shulianghan/article/details/124489398
- 2.出现Duplicate class 的报错
多半是有重复的类,或者说是不同jar包定义了相同的类导致。去掉非必要的jar包。
我出现问题的原因是,在引入第三方包的时候采用了 implementation 的方式,该方式会将第三方包编译到 aar文件当中,而uniapp的插件规范是有 libs库的,所以出现两份,报 Duplicate class 的错误.
编译时的区别
- 3.[JS Framework] 当前运行的基座不包含原生插件[Taric-UHFG],请在manifest中配置该插件,重新制作包括该原生插件的自定义运行基座
参考package.json 标准:
https://nativesupport.dcloud.net.cn/NativePlugin/course/package
我出错的问题是 package.json 中 id与plugins里的name不一致的问题
小结
整体上来讲,简单的集成第三方库,不太需要过多的了解android原生的知识,但需要对gradle这套有一定的理解。
本任务耗时1.5天。
附件
源码:
https://gitee.com/dream-as-horse/uni-app-rfid-plug-in.git
2024最新激活全家桶教程,稳定运行到2099年,请移步至置顶文章:https://sigusoft.com/99576.html
版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请联系我们举报,一经查实,本站将立刻删除。 文章由激活谷谷主-小谷整理,转载请注明出处:https://sigusoft.com/9060.html