当前位置: 首页 > news >正文

记一次uni-app Android原生插件开发

背景

项目使用到了RFID射频手持设备(PDA),用于读取羊只耳标功能。 原来有写过一个插件 https://ext.dcloud.net.cn/plugin?id=5246,新的设备与原来的不一样,所以需要重新写一遍。

之前没有记录,这次重新记录下过程。

使用的硬件设备Demo 为: uhfg_v2.2.10;

资料

1.原生插件开发资料官方:

nativesupport.dcloud.net.cn/NativePlugi…

步骤

1.下载App离线SDK及demo导入

nativesupport.dcloud.net.cn/AppDocs/dow… 下载后有对应的工程文件,需要使用Android Studio导入。

我下载的是 3.5.0,目录结构是:

导入后目录结构是这样的:

我做的项目是使用原生的扫描耳标的能力,不需要界面,所以插件是 扩展 Module 的形式。

2.新建module uhfg模块

3.导入uhf的库及配置build.gradle

uhfg模块 的build.gradle

 plugins {id 'com.android.library'
}

android {signingConfigs {release {}}compileSdkVersion 30defaultConfig {minSdkVersion 21targetSdkVersion 30versionCode 1versionName "1.0"testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"consumerProguardFiles "consumer-rules.pro"}buildTypes {release {minifyEnabled falseproguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'}}
}
repositories {flatDir {dirs 'libs'}
}

dependencies {
// implementation 与 compileOnly在编译时候有区别compileOnly fileTree(dir: 'libs', include: ['*.jar'])compileOnly fileTree(dir: '../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;//uhfpublic 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() {@Overridepublic void run() {
//tagInventoryByTimerList<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() {@Overridepublic void run() {
//tagInventoryByTimerList<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() {@Overridepublic 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 将插件包放在该目录下,插件结构参考前问。

配置完成后,需要打包为自定义基座才能使用。

云端插件

将插件发布到云市场,然后就可以通过使用云端插件的方式使用。同样,测试时候需要打包自定义基座。

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 打包库

解决方案:blog.csdn.net/shulianghan…

  • 2.出现Duplicate class 的报错

多半是有重复的类,或者说是不同jar包定义了相同的类导致。去掉非必要的jar包。

我出现问题的原因是,在引入第三方包的时候采用了 implementation 的方式,该方式会将第三方包编译到 aar文件当中,而uniapp的插件规范是有 libs库的,所以出现两份,报 Duplicate class 的错误.

编译时的区别

  • 3.[JS Framework] 当前运行的基座不包含原生插件[Taric-UHFG],请在manifest中配置该插件,重新制作包括该原生插件的自定义运行基座

参考package.json 标准:nativesupport.dcloud.net.cn/NativePlugi…

我出错的问题是 package.json 中 id与plugins里的name不一致的问题

小结

整体上来将,简单的集成第三方库,不太需要过多的了解android原生的知识,但需要对gradle这套有一定的理解。

本任务耗时1.5天;如果要测试就得打包到基座,我把uni-app都打毛了,说次数太多明天再来。

相关文章:

  • 从汇编深刻理解前置++与后置++
  • 前端笔试题记录(一)
  • 深度学习——(8)回归问题
  • java毕业设计蜗牛兼职网mybatis+源码+调试部署+系统+数据库+lw
  • 2022年8月31日:面向初学者的 web 开发--使用 JavaScript 中的函数创建模块化代码(没看懂)
  • 【玩转Editplus】一个文本编辑器editplus运行Java、js、html、css
  • 【云原生 | Docker】部署 Django Nginx Gunicorn
  • 【STM32】FSMC——扩展外部SRAM
  • 猿创征文|【数据结构】二叉树相关接口的实现及对应OJ题
  • 【操作系统笔记 】进程(1):前驱图和程序执行
  • LeetCode 306周赛 (补记)
  • vue集成海康h5player实现播放
  • Endnote引用文献时期刊名称不缩写问题-论文投稿经验总结-第1期
  • CREO图文教程:三维设计案例之油缸顶物体的骨架模型设计图文教程之详细攻略
  • 表单与表格练习
  • 【技术性】Search知识
  • Angular js 常用指令ng-if、ng-class、ng-option、ng-value、ng-click是如何使用的?
  • download使用浅析
  • JavaScript标准库系列——Math对象和Date对象(二)
  • JavaScript设计模式与开发实践系列之策略模式
  • JavaWeb(学习笔记二)
  • Java到底能干嘛?
  • Java读取Properties文件的六种方法
  • k个最大的数及变种小结
  • node和express搭建代理服务器(源码)
  • Puppeteer:浏览器控制器
  • Web标准制定过程
  • 百度小程序遇到的问题
  • 从PHP迁移至Golang - 基础篇
  • 等保2.0 | 几维安全发布等保检测、等保加固专版 加速企业等保合规
  • 对超线程几个不同角度的解释
  • 多线程事务回滚
  • 聊聊directory traversal attack
  • 使用Tinker来调试Laravel应用程序的数据以及使用Tinker一些总结
  • 数据结构java版之冒泡排序及优化
  • 思维导图—你不知道的JavaScript中卷
  • 【运维趟坑回忆录】vpc迁移 - 吃螃蟹之路
  • ​ 全球云科技基础设施:亚马逊云科技的海外服务器网络如何演进
  • # 达梦数据库知识点
  • #我与Java虚拟机的故事#连载01:人在JVM,身不由己
  • (1)bark-ml
  • (C语言)逆序输出字符串
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (阿里巴巴 dubbo,有数据库,可执行 )dubbo zookeeper spring demo
  • (附程序)AD采集中的10种经典软件滤波程序优缺点分析
  • (附源码)springboot家庭装修管理系统 毕业设计 613205
  • (论文阅读40-45)图像描述1
  • (三)centos7案例实战—vmware虚拟机硬盘挂载与卸载
  • (算法)N皇后问题
  • (一)python发送HTTP 请求的两种方式(get和post )
  • **PyTorch月学习计划 - 第一周;第6-7天: 自动梯度(Autograd)**
  • .net framework profiles /.net framework 配置
  • .NET MVC之AOP
  • .net Signalr 使用笔记
  • .net6解除文件上传限制。Multipart body length limit 16384 exceeded