安卓原生写uniapp插件手把手教学调试、打包、发布。

前言

大家好呀,作为一个前端工程师,对于使用uniapp来写app大家应该并不陌生,但是对于封装第三方提供的安卓原生sdk给到uniapp当中去使用,并没有做过,前段时间刚好有这么需求,做了一个uniapp链接蓝牙设备,并且调用安卓原生sdk的能力的这么一个需求,想着写一个笔记,都不敢叫做教程的一个文章,有什么问题希望大家可以指教。


前期准备

  1. java的sdk,由于是涉及到安卓的原生开发,所以这个是安卓的开发环境还是要搭建的,教程一搜一大把,我就不赘述了
  2. Android studio,安卓原生的IDE编码工具
  3. 下载uniapp官网中的示例包,后来用于调试原生安卓代码时需要用的到,nativesupport.dcloud.net.cn/NativePlugi...

官方示例

前期准备做好,我们使用android_studio打开UniPlugin-Hello-AS这个项目,等待依赖包安装完成。

安装依赖包会比较慢,建议使用科学上网,然后在Android-studio上设置一下代理,速度会快很多

设置代理

官方示例代码结构

蓝牙扫描插件

接下来,我们要做一个蓝牙扫描器的插件,提供给uniapp的项目使用。分析一下需求

  1. 功能包括,连接蓝牙扫描器、开始扫描、获取扫描到的数据、停止扫描。
  2. 综上所述的功能要求,我们不需要安卓原生这边写界面,只需要提供调用sdk的能力。所以我们参考官方的uniplugin_module这个插件

新建一个蓝牙扫描器的安卓原生模块

我们在官方示例的项目上,新建一个blue_scan的模块

选择Android Library,填写模块名称

新建之后,等待依赖包安装完成。

在模块的build.gradle 依赖文件上加上插件编写必要的依赖包,我们可以选择直接从uniplugin_module 下的build.gradle 中的dependencies 依赖项拷贝过来,所以我们模块的build.gradle 下的dependencies就应该变成下面的样子。

javascript 复制代码
dependencies {

    compileOnly fileTree(dir: 'libs', include: ['*.jar'])
    compileOnly fileTree(dir: '../app/libs', include: ['uniapp-v8-release.aar'])
    compileOnly 'androidx.recyclerview:recyclerview:1.0.0'
    compileOnly 'androidx.legacy:legacy-support-v4:1.0.0'
    compileOnly 'androidx.appcompat:appcompat:1.0.0'
    implementation 'com.alibaba:fastjson:1.2.83'
    implementation 'com.facebook.fresco:fresco:1.13.0'


    implementation 'androidx.core:core-ktx:1.17.0'
    implementation 'androidx.appcompat:appcompat:1.7.1'
    implementation 'com.google.android.material:material:1.13.0'
    testImplementation 'junit:junit:4.13.2'
    androidTestImplementation 'androidx.test.ext:junit:1.3.0'
    androidTestImplementation 'androidx.test.espresso:espresso-core:3.7.0'
}

然后同步一下依赖,就会自动安装。

插件代码编写

到这里,我们的插件项目已经新建好了,接下来我们可以着手写对应的代码了

新建一个BlueScan类

在我们项目根目录下的 /blue_scan/src/main/java/com.example.blue_scan 下新建一个名为BlueScan的java的class类

插件类必须继承UniModule,所有我们将代码修改成下面的样子。

java 复制代码
package com.example.blue_scan;
import io.dcloud.feature.uniapp.common.UniModule;

public class BlueScan extends UniModule {

}

连接蓝牙扫描拍,与断开蓝牙扫描拍函数

有几个注意点:

  1. 函数必须是public
  2. 需要使用@UniJSMethod(uiThread = true)装饰器
  3. 安卓原生给uniapp传参需要通过UniJSCallback
java 复制代码
package com.example.blue_scan;
import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.bridge.UniJSCallback;
import io.dcloud.feature.uniapp.common.UniModule;

public class BlueScan extends UniModule {
    @UniJSMethod(uiThread = true)
    public void connectBlueScan(UniJSCallback callback){
    // 连接蓝牙扫描拍成功,这里的true可以在uniapp代码中拿到,所以通过这种方式传递数据
        callback.invoke(true);
    }

    @UniJSMethod(uiThread = true)
    public void disconnectBlueScan(UniJSCallback callback){
        // 断开蓝牙扫描器
        callback.invoke(true);
    }
}

获取蓝牙扫描拍的数据

这里跟上面的函数会有一点不一样,因为蓝牙扫描拍的数据传递是需要多次传递的,也可以简单理解需要一个类似于'长链接的概念 ',这里有一个需要注意的点!!!,在uniapp的代码中需要通过对象嵌套函数的方式传这个回调函数。否则只有第一次会调用成功,这个应该跟安卓的垃圾回收机制有关。

java 复制代码
@UniJSMethod(uiThread = true)
public void getBlueScanData(UniJSCallback callback){
    // 传递蓝牙扫描拍的数据,需要多次传递的话,就使用invokeAndKeepAlive的方式
    callback.invokeAndKeepAlive(1);
}

uniapp 调用时(这里是伪代码 ),看下面代码的方式才能保证invokeAndKeepAlive的方式正常生效。

javascript 复制代码
const callBackObj = {
    // 需要使用对象嵌套函数的方式传递,才能保证正常传递数据
    fn:function(data){
        
    }
}

blueScan.getBlueScanData(callBackObj.fn)

安卓项目中注册插件模块

插件调试

安卓原生的代码调试,最方便的方式就是官方示例中的方式,通过打包uniapp的本地资源放到安卓项目中进行调试,因为uniapp是无法看到安卓原生插件打印的一些输出的,并且uniapp是需要打包自定义基座才能使用安卓原生插件,每次改动插件都需要重新打包自定义基座,效率非常慢。所以我们下面使用官方示例中的方式

uniapp项目代码中,引用插件,并且调用。

uniapp中写如下代码。

javascript 复制代码
<template>
	<view class="content">
		<button @tap="connectBlueScan">连接蓝牙</button>
		<button @tap="disconnectBlueScan">断开蓝牙</button>
		<button @tap="getBlueScan">获取蓝牙数据</button>
	</view>
</template>

<script>
	// 蓝牙原生插件,这里的名称就是在安卓项目中dcloud_uniplugins.json中写的name
	const blueScanNativePlugin = uni.requireNativePlugin('BlueScan');
	export default {
		data() {
			return {
				title: 'Hello'
			}
		},
		onLoad() {

		},
		methods: {
			connectBlueScan(){
				blueScanNativePlugin.connectBlueScan((data)=>{
					console.log('connectBlueScan---',data)
				})
			},
			disconnectBlueScan(){
				blueScanNativePlugin.disconnectBlueScan((data)=>{
					console.log('disconnectBlueScan-----',data)
				})
			},
			getBlueScan(){
				
				const callBack = {
					fn:function(data){
						console.log('getBlueScan----',data)
					}
				}
				
				blueScanNativePlugin.getBlueScanData(callBack.fn)
			},
		}
	}
</script>

<style>
	.content {
		display: flex;
		flex-direction: column;
		align-items: center;
		justify-content: center;
	}

	.logo {
		height: 200rpx;
		width: 200rpx;
		margin-top: 200rpx;
		margin-left: auto;
		margin-right: auto;
		margin-bottom: 50rpx;
	}

	.text-area {
		display: flex;
		justify-content: center;
	}

	.title {
		font-size: 36rpx;
		color: #8f8f94;
	}
</style>

到uniapp开发者后台创建android的离线key

这个时候会需要用到安卓的签名信息,我们生成一个安卓的签名,我们通过keytool命令行的形式来生成,下面只是示例,具体的信息可以根据自己的要求来填写。

vbnet 复制代码
keytool -genkey -v -keystore my-release-key.jks -keyalg RSA -keysize 2048 -validity 10000 -alias my-alias

查看签名中的信息,到后台中进入填入。

perl 复制代码
# 查看签名信息
keytool -list -v -keystore my-release-key.jks

保存好之后,就可以生成的离线key,填写到安卓项目中

把安卓的签名文件放到安卓项目中的app文件夹的根目录上,并填写对应的签名配置

在uniapp项目中新建一个nativeplugins的文件夹,这个名称是固定的,存放安卓插件内容。在这个目录下新建一个目录插件的名称,我们就叫BlueScan,在下面新建一个package.json。

json 复制代码
{
  "name": "BlueScan", 
  "id": "BlueScan", // ID必须唯一
  "version": "1.0.0",
  "_dp_type": "nativeplugin",
  "_dp_nativeplugin": {
    "android": {
      "hooksClass": "",
      "integrateType": "aar",
	  "plugins": [{
	  	"type": "module",
	  	"name": "BlueScan", // 在uniapp这边调用的时候插件的名称
	  	"class": "com.example.blue_scan.BlueScan" // 安卓原生项目上的包名
	  }]
    }
  }
}
Z

填写好内容之后,我们在uniapp项目中的mainfest.json配置上勾选这个安卓原生插件。

勾选完之后,我们就可以将uniapp代码打包本地资源。

打包出来的资源放到安卓项目下app/src/main/assets/apps

修改dcloud_control.xml文件中的appid,为uniapp资源包的文件名

如果需要显示出uniapp这边的打印日志到安卓这边的控制台上的话,就修改一下dcloud_control.xml文件,加上下面的代码,需要注意加上了这个代码的话,最好每次都删除App重新安装,否则会出现代码缓存的问题,并且在生产发布的时候需要去掉这段代码

运行到真机

前面所有的工作都算做完了,没有问题的话,我们连接上手机,然后直接运行到真机,当当当~能正常看到打印的日志

打包插件到uniapp项目中使用

安卓打包插件

拷贝打包出的插件

放到uniapp项目的nativeplugins目录下对应的插件文件夹下,新建一个android的文件夹,把拷贝的插件包放进去

然后运行自定义基座 或者直接打包就可以直接使用了,uniapp标准基座是不支持自定义插件的

相关推荐
颜酱2 小时前
SourceMap 深度解析:从映射原理到线上监控落地
前端·javascript
LYOBOYI1232 小时前
qt的事件传播机制
java·前端·qt
IT_陈寒2 小时前
Python 3.12 性能优化:5 个鲜为人知但提升显著的技巧让你的代码快如闪电
前端·人工智能·后端
军军君012 小时前
Three.js基础功能学习二:场景图与材质
前端·javascript·学习·3d·材质·three·三维
Komorebi゛2 小时前
【Vue3 + Element Plus】Form表单按下Enter键导致页面刷新问题
前端·javascript·vue.js
踢球的打工仔2 小时前
typescript-基本类型
前端·javascript·typescript
dly_blog2 小时前
Vue 组件通信方式大全(第7节)
前端·javascript·vue.js
枫叶丹42 小时前
ModelEngine应用编排创新实践:通过可视化编排构建大模型应用工作流
开发语言·前端·人工智能·modelengine
郭小铭2 小时前
将 Markdown 文件导入为 React 组件 - 写作文档,即时获取交互式演示
前端·react.js·markdown