Unity Android 交互 三 多个Module分别生成 arr 导入Unity自动合并AndroidManifest.xml

来源:互联网 发布:手机淘宝怎么修改地址 编辑:程序博客网 时间:2024/06/03 16:22

Unity Android 交互 三 多个Module分别生成 arr 导入Unity自动合并AndroidManifest.xml

系列篇三
其他篇幅
Unity Android 交互

Unity Android 交互 二

Unity Android 交互 三 多个 Module分别生成 aar 导入Unity自动合并 AndroidManifest.xml

Unity 接入 Android SDK - 讯飞SDK 实战

简单介绍了如何使用 Android Studio 生成 arr 完成 Unity Android 交互
本篇为了实现自己的一些构思,加深对 Android Studio一些特性使用

问题:假如有多个 SDK 接入,或者 使用 Android 一些原生功能支持(获取Wifi 状态、蜂窝数据、系统语言等),需要接入多种不同功能,不想把所有的 SDK 都写在一个工程中(不便于扩展、维护、和删减),而是想每个SDK 或者 功能对应一个 Module。

如何调用
方案一:创建一个主 Module,最终 主 Module 依赖 其他需要的 Module,在 主Module 中写分别调用其他Module的方法,在Unity中只需要通过 主Module 中的方法来调用其他Module中功能方法, 最终将用到的 Module 每个生成自己的 aar 统一放到Unity工程 Plugins/Android 文件夹下,供Unity 使用

方案二:将用到的Module每个生成自己的 aar 统一放到Unity工程 Plugins/Android 文件夹下,供Unity 分别使用

上述实现好处:模块化,维护方便,维护时只需要修改相应的Module,其他模块不会受到任何影响。添加新功能,也不需要担心把现有功能弄坏,需要删除一个功能时只需要把依赖和它对应的几个调用方法关闭,操作简单。
修改、删除等最头疼的就是 AndroidManifest.xml 中一些配置,如果所有功能都在一个Module中完成,每种 SDK 基本都有配置需求,最终 AndroidManifest.xml 中将会有很多各种配置,当添加、删除一个SDK 的时候需要添加、删除该SDK 的配置,坑就在这里。

我想通过上面思路实现每个 SDK 都是一个Module,每个 Module 中都有自己的AndroidManifest.xml,在自己的 AndroidManifest.xml 配置自己SDK 的权限等。最终每个Module 生成一个 .aar, .aar 中包含有自己的 AndroidManifest.xml,我将所有的 .aar 放在Unity中,打包APK 的时候让Unity帮助我去合并所有的 AndroidManifest.xml。
通过测试,上述思路可行。
1.
Plugins/Android 文件夹没有 AndroidManifest.xml, 则打包 APK 的时候 Unity 会将自己带的默认 AndroidManifest.xml 打到 APK 包中,则我们自己的 多个 AndroidManifest.xml就无法合并丢失了
2.
Plugins/Android 有 文件夹AndroidManifest.xml,并且Plugins/Android 文件夹下还有其他的 .aar , Unity 会过滤所有的 .aar 将每个 .aar 中的 AndroidManifest.xml 配置内容合并到 Plugins/Android 文件夹下的AndroidManifest.xml 打包到 APK 中,这样多个 AndroidManifest.xml 就成功合并不影响 APK 运行了。

说了一大通废话,开始实际操作
以方案一,有一个 主 Module 为例来实现

考虑到会有那么些 SDK 会用到 Android 生命周期等,所以我索性创建一个MainActivity 继承于 UnityPlayerActivity 作为 主Module,也作为 主Activity 入口
这里写图片描述

创建生成好后将无用资源、依赖、配置等都统统删除,不知道操作的请看 Unity Android 交互

只剩下核心
这里写图片描述

添加 Unity 自带 classes.jar 库等操作不知道的看前两篇,这里不说了
修改 MainActivity.java 继承 UnityPlayerActivity

package com.SDKTest.Demo;import android.os.Bundle;import com.unity3d.player.UnityPlayer;import com.unity3d.player.UnityPlayerActivity;public class MainActivity extends UnityPlayerActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);    }}

配置 AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?><manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.SDKTest.Demo">    <application        android:allowBackup="true"        android:supportsRtl="true"        >        <activity android:name="com.SDKTest.Demo.MainActivity">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>            </intent-filter>            <!--> 词句一定要加 <-->            <meta-data android:name="unityplayer.UnityActivity" android:value="true"/>        </activity>    </application></manifest>

主 Module 就写好了。

创建一个新 Module
新Module 有两个功能,加法计算、减法计算,就按照功能下面就叫 Calculation Module 了
new -> Module
这里写图片描述

创建一个 Android Library
这里写图片描述

同样将无用资源、依赖、配置统统删除

然后 选择 包文件夹,new -> JavaClass 创建一个Java 类

这里写图片描述

如下
这里写图片描述

CalculationClass.java 代码如下
package com.calculation.demo;public class CalculationClass {    private static CalculationClass Instance = null;    public static  CalculationClass GetInstance()    {        if (Instance == null)        {            Instance = new CalculationClass();        }        return Instance;    }    // 计算两个数相加    public int add(final int number1, final int number2)    {        return number1 + number2;    }    // 计算两个数相减    public int sub(final int number1, final int number2)    {        return  number1 - number2;    }}

上面提到了要合并多个 AndroidManifest.xml, 现在Calculation Module 中的 AndroidManifest.xml 中只是一个最简配置,到时候合并没有也看不出来

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.calculation.demo"></manifest>

随便向 Calculation Module 的 AndroidManifest.xml 加一些权限申请

<manifest xmlns:android="http://schemas.android.com/apk/res/android"    package="com.calculation.demo">    <!--> 下面都是随便加的用来测试的 <-->    <uses-permission android:name="android.permission.RECORD_AUDIO" />    <uses-permission android:name="android.permission.INTERNET" />    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />    <uses-permission android:name="android.permission.READ_PHONE_STATE" />    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />    <uses-permission android:name="android.permission.READ_CONTACTS" />    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.WRITE_SETTINGS" />    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" /></manifest>

Calculation Module 准备就绪,在主 Module 中 MainActivity.java 中添加对 Calculation Module 的引用
修改 如下

package com.SDKTest.Demo;import android.os.Bundle;import com.unity3d.player.UnityPlayer;import com.unity3d.player.UnityPlayerActivity;import com.calculation.demo.CalculationClass;//import com.xunfen.demo.*;public class MainActivity extends UnityPlayerActivity {    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);    }    public int add(final int number1, final int number2)    {        return  number1 + number2;    }    public int calculationAdd(final int number1, final int number2)    {        //调用 Calculation Module 中 CalculationClass 类        CalculationClass calculationClass = CalculationClass.GetInstance();        return  calculationClass.add(number1, number2);    }}

现在可以执行生成 aar 了, Build -> Build APK 或者 Build -> Rebuild Project
这里写图片描述

这里写图片描述

这里写图片描述

在文件夹中找到 app-debug.aar, calculation-debug.aar
删除 app-debug.aar 中的 Unity classes.jar
这里写图片描述

将 app-debug.aar 中的 AndroidManifest.xml 复制出来
这里写图片描述

将 app-debug.aar、 AndroidManifest.xml 和 calculation-debug.aar 放到Unity工程 Plugins/Android 下

这里写图片描述

现在 Plugins/Android 下的 AndroidManifest.xml 为从 app-debug.aar 中复制出来的

创建 C#测试代码

using System.Collections;using System.Collections.Generic;using UnityEngine;using UnityEngine.UI;public class TestXunFei : MonoBehaviour {    public Text text;    public Button buttonA;    public Button buttonB;    // Use this for initialization    void Start () {        buttonA.onClick.AddListener(StartSpeaking);        buttonB.onClick.AddListener(AddNumber);    }    private void StartSpeaking()    {        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) // Android 的 Java 接口        {            using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))            {                int result = jo.Call<int>("add", 100, 200);                ShowText(result.ToString());            }        }    }    private void AddNumber()    {        using (AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) // Android 的 Java 接口        {            using (AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"))            {                int result = jo.Call<int>("calculationAdd", 1003, 200);                ShowText(result.ToString());            }        }    }    private void ShowText(string _str)    {        text.text = _str;    }}

Unity 打包 APK,将APK 安装到模拟器上测试
这里写图片描述

点击 Add 按钮,显示 300 测试成功
这里写图片描述

点击 AddNumber 按钮,显示 1203 测试成功
这里写图片描述

下面开始验证 AndroidManifest.xml 是否合并了
直接解压 APK 发现 打开 AndroidManifest.xml 是乱码,没办法只能找一个反编译工具了
这里写图片描述

反编译成功
这里写图片描述

目录如下
这里写图片描述

打开 AndroidManifest.xml
这里写图片描述

源码附上

<?xml version="1.0" encoding="utf-8" standalone="no"?><manifest xmlns:android="http://schemas.android.com/apk/res/android" android:installLocation="preferExternal" package="com.SDKTest.Demo" platformBuildVersionCode="27" platformBuildVersionName="8.1.0">    <application android:allowBackup="true" android:banner="@drawable/app_banner" android:debuggable="false" android:isGame="true" android:supportsRtl="true">        <activity android:configChanges="locale|fontScale|keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode" android:launchMode="singleTask" android:name="com.SDKTest.Demo.MainActivity" android:screenOrientation="landscape">            <intent-filter>                <action android:name="android.intent.action.MAIN"/>                <category android:name="android.intent.category.LAUNCHER"/>                <category android:name="android.intent.category.LEANBACK_LAUNCHER"/>            </intent-filter>            <meta-data android:name="unityplayer.UnityActivity" android:value="true"/>        </activity>    </application>    <uses-permission android:name="android.permission.RECORD_AUDIO"/>    <uses-permission android:name="android.permission.INTERNET"/>    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE"/>    <uses-permission android:name="android.permission.READ_PHONE_STATE"/>    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>    <uses-permission android:name="android.permission.READ_CONTACTS"/>    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.WRITE_SETTINGS"/>    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>    <uses-feature android:glEsVersion="0x00020000"/>    <uses-feature android:name="android.hardware.touchscreen" android:required="false"/>    <uses-feature android:name="android.hardware.touchscreen.multitouch" android:required="false"/>    <uses-feature android:name="android.hardware.touchscreen.multitouch.distinct" android:required="false"/></manifest>

两个 AndroidManifest.xml 中不相同的内容已经合并到 APK 中的 AndroidManifest.xml 了,并且游泳的部分都被保留了,运行测试成功

发现 <activity 中还多了很多配置

<activity android:configChanges="locale|fontScale|keyboard|keyboardHidden|mcc|mnc|navigation|orientation|screenLayout|screenSize|smallestScreenSize|touchscreen|uiMode" android:launchMode="singleTask" android:name="com.SDKTest.Demo.MainActivity" android:screenOrientation="landscape">

这是Unity自己加入的

坑很多,经过测试 把所有的 aar 都放在 Plugins/Android 下就行了,如果多个 aar 有相对路径的问题,则会有找不到依赖的 aar, 导致执行失败。测试不多,如果谁有更多测试和结果请告知

遇到的一些 BUG
1.APK 打包成功,运行直接闪退,建议查看 AndroidManifest.xml 配置是否有错误, AndroidManifest.xml 不会自己检查错误(坑)

2.测试不将 app-debug.aar 中的 AndroidManifest.xml 放在 Plugins/Android 下,可以正常打出 APK 包,安装到模拟器上蛋疼的出现了两个同名的应用程序
这里写图片描述
更蛋疼的是测试了一下,两个都能启动,一个调用 Android SDK 失败,要给调用成功

  1. AndroidStudio 中Module 生成 aar 的时候不会将该 Module 依赖的 aar 或者 依赖的其他 Module一起打包,AndroidStudio 的机制如此不是BUG,所以如果 aar 有依赖其他的等等吧,一定要将依赖的库复制到 Unity中一份,否则就会出现无法找到依赖库各种蛋疼崩溃

4.Unity 的坑,每次添加替换 aar 或者 AndroidManifest.xml 的时候最好 执行以下 Reimport 一下
这里写图片描述

我替换了 aar 在 Unity 中是显示替换了,但是实际上Unity 并没有执行更新,然后打包 APK 结果其实是将上次更新的 aar 或者 AndroidManifest.xml 来打包的。结果就是,如果有一次是错误、闪退等,后边不管怎么改都会有连续 N 次同样的错误,有时候上次还是错误的 APK 包,但是下次什么都不改直接打 APK ,竟然没有错误了 (Unity 不知道什么时候偷偷的 更新了一下资源)

原创粉丝点击