uni-app之android原生插件开发

news2024/11/27 0:19:35

一 插件简介

1.1 当HBuilderX中提供的能力无法满足App功能需求,需要通过使用Andorid/iOS原生开发实现时,可使用App离线SDK开发原生插件来扩展原生能力。

1.2 插件类型有两种,Module模式和Component模式

  • Module模式:能力扩展,无嵌入窗体的UI控件。大部分插件都是属于此类,比如调用计步器API。代码写法为通过js进行require,然后调用该插件对象的方法。如涉及一些弹出框、全屏ui,也仍然属于Module模式。类似于前端里的js sdk。
  • Component模式:在窗体中内嵌显示某个原生ui组件。比如窗体局部内嵌某个地图厂商的map组件,上下混排其他前端内容,就需要把这个原生地图sdk封装为Component模式。代码写法与vue组件相同,在template里写组件标签。类似于前端里的vue组件。

1.3 插件的使用:原生插件开发后,可以上插件市场,也可以不上。如内部使用,则无需上架插件市场。 如需上插件市场,则必须按指定格式压缩为zip包 

二 插件的开发

2.1 插件必须在uni-sdk的基础上进行开发,可以快速的下载离线uni-sdk,导入UniPlugin-Hello-AS示例工程,也可以自己新建一个原生android项目,拷贝不要的包和资源进行开发。

2.2 离线uni-sdk下载地址: https://nativesupport.dcloud.net.cn/AppDocs/download/android.html,里面包含必要资源和示例工程。

2.3 上一篇已经新建了一个android项目,并离线打包成功了uni资源项目,下面就在这基础上开发插件

2.4 androidStudio项目右击新建一个插件Module

 2.5 选择library,填写module名字,点击finish

2.6 然后在app的build.gradle里面依赖该module

implementation project(':mylibrary') 

2.6 module里面build.gradle配置相关依赖库

uniapp-v8-release.aar是扩展module主要依赖库,必须导入此依赖库

compileOnly fileTree(include: ['uniapp-v8-release.aar'], dir: '../app/libs')

com.alibaba:fastjson 也是必须的也依赖上,后面json通信会用到

implementation 'com.alibaba:fastjson:1.2.83'

同时为了避免和主app冲突,将全部依赖类型换为compileOnly,意思只本module有效

dependencies {
    compileOnly 'androidx.appcompat:appcompat:1.5.0'
    compileOnly 'com.google.android.material:material:1.6.1'

    compileOnly 'com.alibaba:fastjson:1.2.83'
    compileOnly fileTree(include: ['uniapp-v8-release.aar'], dir: '../app/libs')
}

2.7 创建TestModule类,必须继承 UniModule 类

  • 扩展方法必须加上@UniJSMethod (uiThread = false or true) 注解。UniApp 会根据注解来判断当前方法是否要运行在 UI 线程,和当前方法是否是扩展方法。
  • UniApp是根据反射来进行调用 Module 扩展方法,所以Module中的扩展方法必须是 public 类型。

示例:创建两个方法

public class TestModule extends UniModule {
    private static final String TAG = "TestModule";
    //run ui thread
    @UniJSMethod(uiThread = true)
    public void testAsyncFunc(JSONObject options, UniJSCallback callback) {
        Log.e(TAG, "testAsyncFunc--"+options);
        if(callback != null) {
            JSONObject data = new JSONObject();
            data.put("code", "success");
            callback.invoke(data);
        }
    }

    //run JS thread
    @UniJSMethod (uiThread = false)
    public JSONObject testSyncFunc(){
        JSONObject data = new JSONObject();
        data.put("code", "success");
        return data;
    }

}

2.8  注册插件,在androidStudio的assets里面新建dcloud_uniplugins.json,并注册插件信息

{
  "nativePlugins": [
    {
      "plugins": [
        {
          "type": "module",
          "name": "TestModule",
          "class": "com.juai.plugin_module.TestModule"
        }
      ]
    }
  ]
}

2.9 回调事件UniJSCallback:JS调用时,有的场景需要返回一些数据,比如以下例子,返回x、y坐标。

  • invoke调用javascript回调方法,此方法将在调用后被销毁。
  • invokeAndKeepAlive 调用javascript回调方法并保持回调活动以备以后使用。

三 上面简单的插件module就写好了,下面做一个简单的测试

3.1 在uni-app项目页面里面写一个按钮,调用该插件。首先加一个按钮,并设置点击事件。

<button type="primary" @click="testAsyncFunc">testAsyncFunc</button>

3.2 获取刚写好的TestModule插件 

var testModule = uni.requireNativePlugin("TestModule")

 3.3 methon里面,注册点击事件,并调用原生插件方法

testAsyncFunc() {
	// 获取 module
	var testModule = uni.requireNativePlugin("TestModule")
	// 调用异步方法
	testModule.testAsyncFunc({
			'name': 'unimp',
			'age': 1
		},
		e => {
			uni.showToast({
				title: JSON.stringify(e),
				icon:'none'
			});
		}
	)
}

3.4 完整vue示例

<template>
	<view class="content">
		<image class="logo" src="/static/logo.png"></image>
		<view class="text-area">
			<text class="title">{{title}}</text>
		</view>
		
		<button type="primary" @click="testAsyncFunc">testAsyncFunc</button>
	</view>
</template>

<script>
	export default {
		data() {
			return {
				title: 'Hello'
			}
		},
		onLoad() {

		},
		methods: {
            testAsyncFunc() {
				// 获取 module
				var testModule = uni.requireNativePlugin("TestModule")
				// 调用异步方法
				testModule.testAsyncFunc({
						'name': 'unimp',
						'age': 1
					},
					e => {
						uni.showToast({
					     	title: JSON.stringify(e),
							icon:'none'
						});
					}
				)
			}
		}
	}
</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>

3.5 打包app资源

3.7 替换androidStudio项目中的资源包

3.8 运行项目看到刚的按钮已经有了,点击android会获取uni的json数据,说明插件调用成功

3.9 同时也可以看到androidStudio控制台已经有日志打出,插件调用成功

四 插件打包

4.1  上面只是android原生离线调试可以,那怎样在uni中来使用这个原生插件呢。首先要生成插件的aar包,在androidStudio侧边栏找到Gradle工具 -> 再找到项目的Task目录 -> other目录 -> 点击assembleRelease,等待编译结束

4.2 可以看到再插件module的build下面生成了一个aar

4.3 在uni的项目根目录下创建 nativeplugins 文件夹 -> 再创建插件名目录TestModule -> 再创建android目录,把刚才的aar拷贝到android目录下面

 4.4 在插件目录下面创建一个pakage.json来配置插件信息

{
    "name": "TestModule",
    "id": "TestModule", // 插件标识
    "version": "1.0.0",
    "description": "插件描述信息",
    "_dp_type":"nativeplugin",
    "_dp_nativeplugin":{
        "android": {
			"integrateType":"aar",
            "plugins": [
                {
                    "type": "module",
                    "name": "TestModule", //id为前缀
                    "class": "com.juai.plugin_module.TestModule"
                }
                
            ]
        }
    }
}

4.5 这个示例比较简单,如果有so库,和jar包,还需要配置这些信息,完成目录结构如下

 4.6 在manifest.json中识别本地插件

4.7 可以看到有这个插件

4.8 直接标准基座运行是不行的,找不到插件。需要云打包后进行测试

4.9 选择发行 -> 云打包

配置密钥信息

4.10 打包出错,说package.json里面不能包含注释,那我们去掉再试试

4.11  重新云打包出现新错误,大概是说最小androidSDk版本太高了,让最小19

4.12 那就把minSDK调整为19,重新生成aar,替换原来的aar

或者在插件module清单文件AndroidManifest.xml里面添加库的冲突配置

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

   <uses-sdk tools:overrideLibrary="com.bun.miitmdid,com.juai.plugin_module" />

    ..............

</manifest>

4.13 可以看到打包成功

4.14 我们将该apk运行手机看下,可以正常运行

4.15 注意:云打包是有次数的,十来次今天就不能云打包了。所以为了节省次数可以选择自定义基座运行或者安心打包

五 组件Component开发

5.1 组件Component的介绍:

  • Component 扩展 实现特别功能的 Native 控件
  • Component 不支持代码中 new Component 创建对象。无法正常使用

5.2 androidStudio新建组件module 

5.3 添加必须的依赖

compileOnly 'com.alibaba:fastjson:1.2.83'
compileOnly fileTree(include: ['uniapp-v8-release.aar'], dir: '../app/libs')

5.2  创建TestComponent类,Component 扩展类必须继承 UniComponent, 父容器Component(例如ViewGroup组件)则需要继承UniVContainer

public class TestText extends UniComponent<TextView>

5.3  UniComponent的initComponentHostView回调函数。构建Component的view时会触发此回调函数。

@Override
protected TextView initComponentHostView(@NonNull Context context) {
    TextView textView = new TextView(context);
    textView.setTextSize(20);
    textView.setTextColor(Color.BLACK);
    return textView;
}

5.4 Component 对应的设置属性的方法必须添加注解 @UniComponentProp(name=value(value is attr or style of dsl))

@UniComponentProp(name = "tel")
public void setTel(String telNumber) {
    getHostView().setText("tel: " + telNumber);
}

5.5 在app的build.gradle里面添加该组件依赖

implementation project(':ModuleComponent')

5.6 在app的assets的dcloud_uniplugins.json文件里面注册组件

{
  "plugins": [
	{
	  "type": "component",
	  "name": "myText",
	  "class": "com.juai.modulecomponent.TestText"
	}
  ]
}

5.7 在uni项目里面添加TestText组件

<template>
    <myText ref="telText" tel="12305" style="width:200;height:100" @onTel="onTel" @click="myTextClick"></myText>
</template>

5.8 在uni项目的methods里面添加点击事件

methods: {		
	myTextClick(e) {
		this.$refs.telText.clearTel();
	}
}

5.9 完整uni示例

<template>
	<div>
		<myText ref="telText" tel="12305" style="width:200;height:100" @onTel="onTel" @click="myTextClick"></myText>
	</div>
</template>
<script>  
    export default {  
        methods: {  
			myTextClick(e) {
				this.$refs.telText.clearTel();
			}
        }  
    } 
</script>  

5.10 uni打包app资源

5.11 复制资源包到androidStudio项目的assets里面

5.12  运行出现该组件说明成功,同样打包aar,复制到uni项目里面的nativeplugins目录,并配置pakage.json

5.13 云打包就可以安装真机上运行了 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/969247.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

S32K324芯片学习笔记

文章目录 Core and architectureDMASystem and power managementMemory and memory interfacesClocksSecurity and integrity安全与完整性Safety ISO26262Analog、Timers功能框图内存mapflash Signal MultiplexingPort和MSCR寄存器的mapping Core and architecture 两个Arm Co…

数学建模:Yalmip求解线性与非线性优化问题

&#x1f506; 文章首发于我的个人博客&#xff1a;欢迎大佬们来逛逛 线性优化 使用 Yalmip 求解线性规划最优值&#xff1a; m i n { − x 1 − 2 x 2 3 x 3 } x 1 x 2 ⩾ 3 x 2 x 3 ⩾ 3 x 1 x 3 4 0 ≤ x 1 , x 2 , x 3 ≤ 2 \begin{gathered}min\{-x_1-2x_23x_3\} \…

networkX-01-基础

文章目录 创建一个图1. 节点方式1 &#xff1a;一次添加一个节点方式2&#xff1a;从list中添加节点方式3&#xff1a;添加节点时附加节点属性字典方式4&#xff1a;将一个图中的节点合并到另外一个图中 2. 边方式1&#xff1a;一次添加一条边方式2&#xff1a;列表&#xff08…

23062网络编程day2

1. TCP的服务器 客户端的代码 服务器 #include <myhead.h>#define ERR_MSG(msg) do{\fprintf(stderr,"__%d__:",__LINE__);\perror(msg);\ }while(0)#define PORT 8888#define IP "192.168.114.104"int main(int argc, const char *argv[]) {//创建…

大数据技术原理与应用学习笔记第1章

黄金组合访问地址&#xff1a;http://dblab.xmu.edu.cn/post/7553/ 1.《大数据技术原理与应用》教材 官网&#xff1a;http://dblab.xmu.edu.cn/post/bigdata/ 2.大数据软件安装和编程实践指南 官网林子雨编著《大数据技术原理与应用》教材配套大数据软件安装和编程实践指…

Windows 操作系统下 Python 及其模块的管理

Python 是一款解释型语言&#xff0c;理论上一个.py文件可以当成一个稍微复杂一些的字符串指令集本文不涉及jupyter,VS,VScode,Pycharm 等集成开发环境&#xff0c;这不是我们这篇文章所关心的东西 这篇文章面向的是Python 的初学者 最近没有写太多长文章&#xff0c;多写几篇&…

8、暴力递归

前缀树 一个字符串类型的数组arr1,另一个字符串类型的数组arr2。arr2中有哪些字符,是arr1中出现的?请打印。arr2中有哪些字符,是作为arr1中某个字符串前缀出现的?请打印。arr2中有哪些字符,是作为arr1中某个字符串前缀出现的?请打印 arr2中出现次数最大的前缀 public…

LabVIEW开发超导体电流特性的测量系统

LabVIEW开发超导体电流特性的测量系统 超导体的临界电流密度Jc不断增加&#xff0c;目前超导线已达到150MA/cm2因此&#xff0c;由于电流能力增强&#xff0c;超导体被认为应用于电力系统&#xff0c;例如传输电缆、超导磁体和超导磁储能。由于Jc是此类应用的重要值&#xff0…

STM32F4X RNG随机数发生器

STM32F4X RNG随机数发生器 随机数的作用STM32F4X 随机数发生器RNG控制寄存器RNG状态寄存器RNG数据寄存器RNG数据步骤RNG例程 随机数的作用 随机数顾名思义就是随机产生的数字&#xff0c;这种数字最大的特点就是其不确定性&#xff0c;你不知道它下一次产生的数字是什么。随机…

差分数组/前缀和

文章目录 1094. 拼车1109. 航班预定统计303. 区域和检索 - 数组不可变560. 和为K的子数组523. 连续的子数组的和 1094. 拼车 class Solution {public boolean carPooling(int[][] trips, int capacity) {int[] diff new int[1001]; // 记录每个站点改变的人数&#xff0c;比如…

c语言---指针

指针 前言 记录一个数据对象在内存中的存储位置&#xff0c;需要两个信息&#xff1a; 1、数据对象的首地址。 2、数据对象占用存储空间大小 基础数据类型所占内存空间大小&#xff08;字节&#xff09;&#xff0c;一个字节代表8个二进制位 char 1 short 2 int 4 lon…

Java中的网络编程------基于Socket的TCP编程和基于UDP的网络编程,netstat指令

Socket 在Java中&#xff0c;Socket是一种用于网络通信的编程接口&#xff0c;它允许不同计算机之间的程序进行数据交换和通信。Socket使得网络应用程序能够通过TCP或UDP协议在不同主机之间建立连接、发送数据和接收数据。以下是Socket的基本介绍&#xff1a; Socket类型&…

机器学习:可解释学习

文章目录 可解释学习为什么需要可解释机器学习可解释还是强模型可解释学习的目标可解释机器学习Local ExplanationGlobal Explanation 可解释学习 神马汉斯&#xff0c;只有在有人看的时候能够答对。 为什么需要可解释机器学习 贷款&#xff0c;医疗需要给出理由&#xff0c;让…

学生宿舍水电费自动缴费系统/基于javaweb的水电缴费系统

摘 要 “互联网”的战略实施后&#xff0c;很多行业的信息化水平都有了很大的提升。但是目前很多学校日常工作仍是通过人工管理的方式进行&#xff0c;需要在各个岗位投入大量的人力进行很多重复性工作&#xff0c;这样就浪费了许多的人力物力&#xff0c;工作效率较低&#x…

职场中的道德与伦理:如何在工作中坚守原则?

引言 在快节奏的职场环境中&#xff0c;道德与伦理问题时常出现&#xff0c;但却往往被忽视。面对各种压力和诱惑&#xff0c;如何在工作中坚守原则&#xff0c;不仅是个人修养的体现&#xff0c;也是职业成功的关键。本文将探讨职场中的道德与伦理问题&#xff0c;以及如何在…

Orangepi安装外设库 wiringPi

注意&#xff1a;mobaXterm传送文件要在SSH登陆环境下才可以。 同时电脑和orangepi都在同一个wifi下。

docker 笔记6:高级篇 DockerFile解析

目录 1.是什么&#xff1f; 2.构建三步骤 3.DockerFile构建过程解析 3.1 Dockerfile内容基础知识 3.2Docker执行Dockerfile的大致流程 总结 4.DockerFile常用保留字指令 5.案例&#xff1a;自定义镜像 5.1 要求&#xff1a; Centos7镜像具备vimifconfigjdk8 5.2编写 5…

deque容器

1 deque容器基本概念 功能&#xff1a; 双端数组&#xff0c;可以对头端进行插入删除操作 deque与vector区别&#xff1a; vector对于头部的插入删除效率低&#xff0c;数据量越大&#xff0c;效率越低deque相对而言&#xff0c;对头部的插入删除速度回比vector快vector访问…

如何在java中做基准测试

最近公司在搞新项目&#xff0c;由于是实验性质&#xff0c;且不会直接面对客户的项目&#xff0c;这次的技术选型非常激进&#xff0c;如&#xff0c;直接使用了Java 17。 作为公司里练习两年半的个人练习生&#xff0c;我自然也是深度的参与到了技术选型的工作中。不知道大家…

Gitea--私有git服务器搭建详细教程

一.官方文档 https://docs.gitea.com/zh-cn/说明 gitea 是一个自己托管的Git服务程序。他和GitHub, Gitlab等比较类似。他是从 Gogs 发展而来&#xff0c;gitea的创作团队重新fork了代码&#xff0c;并命名为giteagitea 功能特性多&#xff0c;能够满足我们所有的的代码管理需…