Uniapp 引入 Android aar 包 和 Android 离线打包

news2024/12/23 23:39:32

需求:

原生安卓 apk 要求嵌入到 uniapp 中,并通过 uniapp 前端调起 app 的相关组件。
下面手把手教你,从 apk 到 aar,以及打包冲突到如何运行,期间我所遇到的问题都会 一 一 进行说明,相关版本以我文章内为例子,其他版本如果存在差异请自行解决(不过一般也不会有很大差别啦)

官方文档传送门:uni原生插件开发教程

一、uniapp(这里以新建为主演示)

直接在 HBuilder 中新建即可
新建完成后,uniapp 工作台会创建对应的项目,等会生成 appkey 会用到(没有 dcloud 账号就创建一个)

二、Android环境(离线基座项目)搭建

因为我们是 Android 开发的,所以我们只看 Android 部分就可以了,开发环境如下:
在这里插入图片描述
首先下载对应 HBuilderX 对应版本的 SDK

1. 查看我们当前 HBuilder 的版本(建议升级到最新):

在这里插入图片描述
在这里插入图片描述

2. 点击以下红框部分,跳转到查下 Android sdk 界面,选择对应的版本下载,如果HBuilder 不是最新的,就到历史版本中下载对应的即可

在这里插入图片描述
在这里插入图片描述

3. 在 Android Studio 中,新建项目(选 java,当前项目是我们离线基座的apk,不是我们的项目的),记录下包名(以下我的相关配置):

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

4. 添加相关配置:

app 下 build.gradle:
    implementation 'androidx.appcompat:appcompat:1.0.0'
    implementation 'androidx.legacy:legacy-support-v4:1.0.0'
    implementation 'com.alibaba:fastjson:1.2.83'
    implementation 'androidx.webkit:webkit:1.3.0'
    implementation 'com.facebook.fresco:fresco:2.5.0'
    implementation "com.facebook.fresco:animated-gif:2.5.0"
    implementation 'androidx.recyclerview:recyclerview:1.0.0'

    implementation 'com.squareup.okio:okio:1.15.0'
    implementation 'com.squareup.okhttp3:okhttp:3.12.12'
    implementation 'com.github.bumptech.glide:glide:4.9.0'

下载后的sdk放进来(我们自己的aar包打包后直接放进来,然后同步即可):
在这里插入图片描述
可以看到,这个基座是一个 androidX 的项目 ,如果我们要引进来的项目是 support 的也没关系(我的就是 support 的)

5. 搞一个签名,签名网上有很多教程,这里我就不贴出来了,可以自行搜索,这里我贴一下我的配置,这个签名的作用,是为后面我们打包 apk 和申请 appkey 的时候用到的(离线打包自签名,咋搞都可以,只要签名能用):

在这里插入图片描述

6. AndroidManifest.xml

注意点:
(1)application 添加:tools:replace=“android:icon,android:allowBackup”
(2)provider 的 authorities需要改成你当前的 包名…dc.fileprovider,例如:android:authorities=“com.android.myapplication2.dc.fileprovider”
(3) 增加 dcloud_appkey,value 就是等会我们要去 uniapp 工作台申请的 appkey

<meta-data
            android:name="dcloud_appkey"
            android:value="xxx" />

完整示例如下

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

    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_PHONE_STATE" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>
    <uses-permission android:name="zy.permission.OUT_ENTER" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/icon"
        android:label="@string/app_name"
        android:supportsRtl="true"
        tools:replace="android:icon,android:allowBackup">

        <activity
            android:name="io.dcloud.PandoraEntry"
            android:configChanges="orientation|keyboardHidden|keyboard|navigation"
            android:label="@string/app_name"
            android:launchMode="singleTask"
            android:hardwareAccelerated="true"
            android:theme="@style/TranslucentTheme"
            android:screenOrientation="user"
            android:windowSoftInputMode="adjustResize" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <intent-filter>
                <category android:name="android.intent.category.DEFAULT" />
                <category android:name="android.intent.category.BROWSABLE" />
                <action android:name="android.intent.action.VIEW" />
                <data android:scheme=" " />
            </intent-filter>
        </activity>
        <activity
            android:name="io.dcloud.PandoraEntryActivity"
            android:launchMode="singleTask"
            android:configChanges="orientation|keyboardHidden|screenSize|mcc|mnc|fontScale|keyboard|smallestScreenSize|screenLayout|screenSize|uiMode"
            android:hardwareAccelerated="true"
            android:permission="com.miui.securitycenter.permission.AppPermissionsEditor"
            android:screenOrientation="user"
            android:theme="@style/DCloudTheme"
            android:windowSoftInputMode="adjustResize">
        </activity>

        <provider
            android:name="io.dcloud.common.util.DCloud_FileProvider"
            android:authorities="com.android.myapplication2.dc.fileprovider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/dcloud_file_provider" />
        </provider>

        <meta-data
            android:name="dcloud_appkey"
            android:value="xxx" />
    </application>

</manifest>

三、申请离线打包的 appkey

1. 登录 dcloud 后,进入工作台,在“应用管理——我的应用”中,找到我们在 HBuilder 中创建的项目

在这里插入图片描述

2. 点击 “应用名称” 后,跳转到应用信息,选择 “各平台信息”,点击 “新增” 按钮

在这里插入图片描述
在这里插入图片描述

3. 将我们刚才创建的基座 Android 项目的包名,输入到 “包名” 文本框中,对于 SHA1 和 SHA256 获取,回到我们的 Android Studio,右键我们的签名,然后选择 Terminal 打开

在这里插入图片描述
输入命令:keytool -list -v -keystore 签名文件(注意后缀也需要) -storepass 密码
在这里插入图片描述
这样就得到了我们的 sha1 和 sha256
最终平台信息如下
在这里插入图片描述

4. 上面平台信息填写完成后,点击提交,平台信息就会变化了

在这里插入图片描述

5. 这里我已经创建了离线打包 key,没有创建显示的是创建按钮,点击创建生成我们的 appkey,至此,appkey 创建完成

在这里插入图片描述

6. 将 appkey,配置到我们刚才 AndroidManifest.xml 中的 dcloud_appkey

在这里插入图片描述

四、基座 Android 项目的完善

1. 回到 HBuilder,打开我们的项目,在项目根下,创建以下目录结构(dir1看package.json 的配置):

在这里插入图片描述
其中,package.json 配置结构如下,建议红框中的三个部分和dir1都填写一样(插件名称),避免出错,而 class 部分,是用于暴露给 uniapp 调用的类路径,该路径是你 aar 下的,不是签名的基座的(关于 aar 文件,参考后面 aar 打包部分

{
    "id": "插件名称",
	"name": "插件名称",
    "version": "1.0.0",
    "description": "",
	"_dp_type": "nativeplugin",
	"_dp_nativeplugin": {
		"android": {
			"plugins": [{
				"type": "module",
				"name": "插件名称",
				"class": "aar中提供的类路径"
			}],
			"integrateType": "aar"
		}
	}
}

在这里插入图片描述

2. 这里配置正确后,打开 manifest.json,找到 App 原生插件配置,选择本地插件

在这里插入图片描述
前面配置正确的话,弹出框就能看到我们的插件了
在这里插入图片描述
在这里插入图片描述

3. 添加调起我们 aar 的方法(需要和 Android 端约定方法名和参数)

在这里插入图片描述
插件名称,参考前面 package.json 的配置,里面 dir1 部分,这里 startActivity(obj),是调起 pageckage.json 中配置的 class 对应类的方法,具体可以看后面打包部分,关于该类的创建和方法定义

4. 在 HBuilder 中,将我们的 uniapp 项目打包成静态资源出来

在这里插入图片描述
打包完成后,会在项目根下生成 unpackage下,生成 resources 目录,resources 目录下的目录,存放的就是我们需要的静态资源,该目录名称就是我们项目的应用标识,复制该目录,粘贴到基座 app 的 assets/app 下,该资源目录不存在就创建一个 在这里插入图片描述

5. 在 assets 资源目录下,创建 data 目录,然后将 sdk 中提供的三个 dcloud_ 文件放进来,打开 dcloud_control.xml,将其改下面的样子,其中,appid 就是你 uniapp 项目的应用标识,注意要给 hbuilder 添加 debug 和 syncDebug

<hbuilder debug="true" syncDebug="true">
    <apps>
        <app appid="__UNI__XXXX" appver="1.0.0"/>
    </apps>
</hbuilder>

在这里插入图片描述

6. 将我们的的目标 aar 放到基座项目的 libs 下,

前面我们依赖已经配置了 implementation fileTree(dir: ‘libs’, include: [‘.aar’, '.jar’]) ,所以手动同步一下
在这里插入图片描述

7. 接下来就可以直接运行到手机了,而安装在手机的,就是离线基座了,或者打包成 apk,放在 uniapp unpackage/debug 目录下,基座apk名称修改成 android_debug.apk (一定要这个名字),Hbuilder 选择运行到设备的时候,选择自定义基座也是可以的

在这里插入图片描述

五、AAR 打包

PS:以下打包的过程,都是你自己项目的,跟基座项目没关系

PPS:我的项目是 kotlin ,且是 support,可以正常打包和调起的

1、添加打包工具

在项目的 build.gradle 中添加 fat-aar 打包工具:
classpath ‘com.github.kezong:fat-aar:1.3.8’

2、修改应用 build.gradle配置

将 ‘com.android.application’ 修改成 ‘com.android.library’
添加 apply plugin: ‘com.kezong.fat-aar’
将所有依赖改成 embed 方式,例如:
在这里插入图片描述

如果项目有依赖内部的其他 module 模块,那么也是需要修改成 embed,但是,该模块内的依赖的是不会被打包进去的,为了更好的调整,建议将该模块下的所有依赖,搬到当前应用的依赖下,然后修改成 embed,方便后面修改,也不用去修改所依赖内部模块的内容

引入 uniapp 依赖包,用 compileOnly,该模块用于创建我们前面 package.json 中的 class,该 class 依赖 uniapp 包中的类:
在这里插入图片描述

以下是我的项目的部分依赖例子(关于我遇到的包冲突部分,在后面):
在这里插入图片描述

3、添加 dcloud_uniplugins.json 配置

在 assets 中,创建 dcloud_uniplugins.json,添加如下配置:
其中,name和class 和前面 package.json 中的保持一致,类名可以自己定义

{
  "nativePlugins": [
    {
      "plugins": [
        {
          "type": "module",
          "name": "插件名称",
          "class": "包名.ZyModule"
        }
      ]
    }
  ]
}

4、创建我们的入口类 ZyModule

这里我只暴露了一个方法 startActivity,且可以传入一个参数,具体根据自己需求修改,我这里方法用于调起我的 MyActivity,这里定义好后,就可以将方法名和 uniapp 的 package.json 中进行配置和调用了

import io.dcloud.feature.uniapp.annotation.UniJSMethod;
import io.dcloud.feature.uniapp.common.UniDestroyableModule;

public class ZyModule extends UniDestroyableModule {

    private static final String TAG = "ZyModule";

    @UniJSMethod(uiThread = true)
    public void startActivity(Object data) {
        Log.e(TAG, "传递参数:" + (JSONObject) data);
        Context context = mUniSDKInstance.getContext();
        try {
            Intent intent = new Intent(context, MyActivity.class);
            intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent);
            Log.d(TAG, "启动成功");
        } catch (Exception e) {
            Log.e(TAG, "启动失败: " + e.getMessage());
        }
    }

    @Override
    public void destroy() {

    }
}

5、AndroidManifest.xml 的修改

  1. 去掉 application 中的 name
  2. 去掉 mian 入口的配置
  3. FileProvider 一定要写完整的包名,不能用 ${applicationId},否则会调起不起我们的类
    在这里插入图片描述
  4. 点击 Android Studio 的 gradle(一般在右边),然后找到我们的项目,在 Tasks/ build 或者 other 或者某个目录下,找到 assembleDebug 或者 assembleRelease,双击运行即可生成 aar 包
    在这里插入图片描述
  5. 将 aar 复制到两个地方(aar包名名称不用管,但最好修改成统一的格式)
    (1)uniapp插件中:nativeplugins\插件名称\android
    在这里插入图片描述
    (2)直接放在基座的libs目录下,然后同步一下即可

六、问题

1、appkey或者配置无效问题

在申请 appkey 时,其实就是新增平台信息的时候,填错包名或者 SHA1、SHA256,然后重新回来修改成正确的,接着如果去重新生成 appkey,但是发现 appkey 没有改变(如果有改变就用这个新的试试看,我遇到的是没有改变),就重新创建一条平台,原先这条就可以删掉了。
我是一开始包名写错,然后修改成正确的包名后,发现 appkey 没有变化,使用该 appkey 总是包标题错误,就删掉了重新生成才可以的。

2、基座打包冲突和缺包处理

首先,建议直接离线打包,在线打包每个账号每天有次数限制,且需要排队,很慢
其次,包冲突可以在本地快速处理
在打包过程中,有几个包是需要我们自己过滤的,我们的 aar 项目需要改成 compileOnly:

  • fastjson
  • zip4j
  • glide
  • com.squareup.okio:okio:1.15.0 和 com.squareup.okhttp3:okhttp:3.12.12

这几个包在在线打包的时候都会出现包冲突报错的,所以我们不能打包进我们的 aar 中,当然,离线下我们需要引入,具体看一看前面基座项目应用的依赖配置
zip4j在基座的libs下aar中有
fastjson需要基座申明依赖
glide 需要的版本是 4.9.0,如果是其他版本,请将自己的项目配置成该版本,然后自行修改代码

缺包和部分冲突
关于缺包,是因为 embed 的依赖方式,是不会将第三方依赖中的依赖打包进去的,这个需要自己在 External Libraries 中找到相关的包添加到你 aar 应用的依赖中,例如,我这里用到的 rx:
在这里插入图片描述
或者我项目本身 kotlin 部分:
在这里插入图片描述
当然,在线打包,如果我们的是 kotlin 项目,那么我们需要去掉以下三个包:
在这里插入图片描述

其他包冲突和缺包都可以按照上面的方式来处理,建议先离线来处理,一般会把所有冲突先罗列出来,运行的时候才会报缺包,缺包就缺啥补啥即可

3、aar 已经放在 uniapp 项目下,为啥运行的时候,会报插件 undefined

原因是没有制作基座!!!
一定要有基座,基座其实就是将 aar 打包进 apk,运行的时候才会被调用到,基座 apk 路径可以参考前面

七、测试

uniapp 要调起 aar,无论是在线打包还是离线打包,都是生成自定义基座:项目/unpackage/debug/android_debug.apk,然后运行的时候选择自定义基座的,如果没有这个基座,而是默认标准基座,那么 aar 是掉不起来的

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

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

相关文章

你可以通过以下步骤找到并打开 **Visual Studio 开发者命令提示符**:

你可以通过以下步骤找到并打开 Visual Studio 开发者命令提示符&#xff1a; 1. 通过开始菜单查找 打开 开始菜单&#xff08;点击屏幕左下角的 Windows 图标&#xff09;。在搜索框中输入 Developer Command Prompt。你应该看到以下几种选项&#xff08;具体取决于你的 Visu…

北京大学c++程序设计听课笔记101

基本概念 程序运行期间&#xff0c;每个函数都会占用一段连续的内存空间。而函数名就是该函数所占内存区域的起始地址&#xff08;也称“入口地址”&#xff09;。我们可以将函数的入口地址赋给一个指针变量&#xff0c;使该指针变量指向该函数。然后通过指针变量就可以调用这个…

(时序论文阅读)TimeMixer: Decomposable Multiscale Mixing for Time Series Forecasting

来源论文iclr2024 论文地址&#xff1a;https://arxiv.org/abs/2405.14616 源码地址&#xff1a; https://github.com/kwuking/TimeMixer 背景 数据是有连续性&#xff0c;周期性&#xff0c;趋势性的。我们这篇文章主要围绕的是用MLP结构来预测数据的周期性具体为&#xff…

Springboot 使用EasyExcel导出含图片并设置样式的Excel文件

Springboot 使用EasyExcel导出含图片并设置样式的Excel文件 Excel导出系列目录&#xff1a;★★★★尤其注意&#xff1a;引入依赖创建导出模板类逻辑处理controllerservice 导出效果总结 Excel导出系列目录&#xff1a; 【Springboot 使用EasyExcel导出Excel文件】 【Springb…

【论文分享】基于街景图像识别和深度学习的针对不同移动能力老年人的街道步行可达性研究——以南京成贤街社区为例

全球老龄化趋势加剧, 许多城市中老年人数量不断增加&#xff0c;而现有街道和社区基础设施往往未能满足其步行安全和便利需求。本次我们给大家带来一篇SCI论文的全文翻译&#xff0c;该论文通过探讨不同步行能力的老年人对城市步行环境的需求&#xff0c;提供了关于如何改善城市…

LM2 : A Simple Society of Language Models Solves Complex Reasoning

文章目录 题目摘要简介相关工作方法论实验结果结论局限性 题目 LM2&#xff1a;简单的语言模型社会解决复杂推理问题 论文地址&#xff1a;https://aclanthology.org/2024.emnlp-main.920/ 项目地址&#xff1a; https://github.com/LCS2-IIITD/Language_Model_Multiplex 摘要…

【因果分析方法】MATLAB计算Liang-Kleeman信息流

【因果分析方法】MATLAB计算Liang-Kleeman信息流 1 Liang-Kleeman信息流2 MATLAB代码2.1 函数代码2.2 案例参考Liang-Kleeman 信息流(Liang-Kleeman Information Flow)是由 Liang 和 Kleeman 提出的基于信息论的因果分析方法。该方法用于量化变量之间的因果关系,通过计算信息…

[含文档+PPT+源码等]精品基于springboot实现的原生Andriod手机使用管理软件

软件开发环境及开发工具&#xff1a; 数据库管理工具&#xff1a;phpstudy/Navicat或者phpstudy/sqlyog 开发工具&#xff1a;Android Studio 后台管理系统涉及技术&#xff1a; 后台使用框架&#xff1a;Springboot 前端使用技术&#xff1a;Vue,HTML5,CSS3、JavaScript等…

(三十三)队列(queue)

文章目录 1. 队列&#xff08;queue&#xff09;1.1 定义1.2 函数1.3 习题1.3.1 例题&#xff08;周末舞会&#xff09; 2. 双向队列&#xff08;deque&#xff09;2.1 定义2.2 函数2.3 题目2.3.1 例题&#xff08;打BOSS&#xff09; 1. 队列&#xff08;queue&#xff09; 队…

常用数据类型

1.数值类型 分为整型和浮点型 double(3,1)&#xff1b;长度是3&#xff0c;小数点后是1&#xff0c;比如99.5&#xff0c;10.0&#xff0c;20.8 这里的float和double与java中的类似&#xff0c;都是IEEE 754标准的浮点数&#xff0c;精度会丢失&#xff0c;存在一定误差&#…

Vue3 -- 集成sass【项目集成5】

集成sass&#xff1a; 看过博主的 配置styleLint工具应该已经安装过 sass sass-loader 了&#xff0c;所以我们只需要加上我们的 lang"scss"即可。 <style scoped lang"scss"></style>给项目添加全局样式文件&#xff1a; 在src文件夹下创建…

【云原生系列--Longhorn的部署】

Longhorn部署手册 1.部署longhorn longhorn架构图&#xff1a; 1.1部署环境要求 kubernetes版本要大于v1.21 每个节点都必须装open-iscsi &#xff0c;Longhorn依赖于 iscsiadm主机为 Kubernetes 提供持久卷。 apt-get install -y open-iscsiRWX 支持要求每个节点都安装 N…

Springboot集成ElasticSearch实现minio文件内容全文检索

一、docker安装Elasticsearch &#xff08;1&#xff09;springboot和Elasticsearch的版本对应关系如下&#xff0c;请看版本对应&#xff1a; 注意安装对应版本&#xff0c;否则可能会出现一些未知的错误。 &#xff08;2&#xff09;拉取镜像 docker pull elasticsearch:7…

Diff 算法的误判

起源&#xff1a; 设想一下&#xff0c;假如你桌面上的文件都没有文件名&#xff0c;取而代之的是&#xff0c;你使用通过文件的位置顺序即index来区分它们———第一个文件&#xff0c;第二个文件&#xff0c;以此类推。也许这种方式可行&#xff0c;可是一旦你删除了其中的一…

D69【 python 接口自动化学习】- python 基础之数据库

day69 Python 执行 SQL 语句 学习日期&#xff1a;20241115 学习目标&#xff1a; MySQL 数据库&#xfe63;- Python连接redis 学习笔记&#xff1a; redis数据库的用途 使用Python访问redis数据库 使用Python对redis数据库进行读写操作 总结 1. redis是一款高性能的键…

飞书文档只读限制复制

飞书文档只读限制复制 场景描述解决方式插件安装测试 场景描述 当使用飞书时&#xff0c;可能会存在无对方文档编辑/管理权限&#xff0c;对方只给自己开放只读权限的时候&#xff0c;此时如果文档较重要&#xff0c;需要本地保存一份&#xff0c;但是又无法复制文档或直接屏蔽…

[每周一更]-(第123期):模拟面试|消息队列面试思路解析

文章目录 22|消息队列:消息队列可以用来解决什么问题?1. 你用过消息队列吗?主要用来解决什么问题?异步、削峰和解耦你能各举一个例子吗?2. 你用的是哪个消息队列?为什么使用它而不用别的消息队列?3. 为什么你一定要用消息队列?不用行不行?不用有什么缺点?4. 在对接多…

npm list @types/node 命令用于列出当前项目中 @types/node 包及其依赖关系

文章目录 作用示例常用选项示例命令注意事项 1、实战举例**解决方法**1. **锁定唯一的 types/node 版本**2. **清理依赖并重新安装**3. **设置 tsconfig.json 的 types**4. **验证 Promise 类型支持** **总结** npm list types/node 命令用于列出当前项目中 types/node 包及其…

使用 DBSCAN(基于密度的聚类算法) 对二维数据进行聚类分析

代码功能 生成数据&#xff1a; 使用 make_moons 方法生成一个非线性分布的二维数据集&#xff0c;模拟月亮形状的两个半环形分布&#xff0c;同时添加一定的噪声。 数据标准化&#xff1a; 使用 StandardScaler 对数据进行标准化处理&#xff0c;使不同特征的值具有相同的…

【苍穹外卖】学习日志-day1

目录 nginx 反向代理介绍 nginx 的优势 提高访问速度 负载均衡 保证后端服务安全 高并发静态资源 Swagger 生成 API 文档 Swagger 的使用方式 导入knife4j的maven坐标 在配置类中加入knife4j相关配置 设置静态资源映射 通过注解控制生成的接口文档 项目技术点 Token 模式 MD5 加…