0
点赞
收藏
分享

微信扫一扫

【Unity和Android通信】jar包 arr包 java扩展

JamFF 2022-03-25 阅读 83

Unity和安卓交互的几种形式

请添加图片描述
1.导出Jar包 + 扩展MainActivity + Java主导
复杂度 4.5★ 通用度 4.5★ 注:官方已经不再推荐这种方法。
2.导出aar包 + 扩展MainActivity + Java主导
复杂度 4★ 通用度 4.5★ 注:官方推荐
3.互调模式之提供Java扩展类
提供额外的类 + Java主导 复杂度 3★ 通用度 3.5★
4.互调模式之C#主导式调用
Unity中设置了安卓SDK路径后,可以直接调用安卓SDK中的原生方法,不用从AS中导出插件再导入Unity中。但C#中用反射的写法不能使用Java的一些高级语法。

环境配置

1.unity2017
2.Android Studio 2021.1.1
Android Studio 安装
转载:
https://blog.csdn.net/qq_33581509/article/details/116424441
3.Java SDK 1.8
javaSDK环境配置
安装JDK与JRE,目录随意,不是同一个且记住就行。

安装完成后,此电脑(Win7叫计算机),右键,属性,高级系统选项,环境变量
系统变量,新建,JAVA_HOME变量
变量值选择或填写JDK的安装目录
系统变量,找到Path变量(已经存在的),编辑
在变量值最后输入JDK安装目录下的bin目录(可以直接输入也可以写成%JAVA_HOME%\bin)与JRE安装目录下的bin目录
注意:原Path变量最后若已经有分号则不用加,否则先加一个分号再输入
系统变量,新建,CLASSPATH变量
变量值填写(可直接复制下一行内容)
.;%JAVA_HOME%\lib;%JAVA_HOME%\lib\tools.jar
运行cmd 输入 java -version与javac -version
java或javac和 -version 之间有空格
若显示版本信息 则说明安装和配置成功
在这里插入图片描述
在这里插入图片描述

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

导出Jar包 + 扩展MainActivity + Java主导

1、打开Android Studio新建一个项目,新建一个模块(Module),取名UnityAndroidLibrary。注意选择最小SDK16,因为Unity最小支持的是16。
2、在该模块(ProjectName/UnityAndroidLibrary/src/main/java/packageName/)下新建一个Empty Activity。创建时勾上Launcher Activity。
3、删除跟该界面一同生成的activity_main.xml布局文件(因为之后布局归Unity管理),同时删除该模块MainActivity中onCreate()里调用setContentView()方法。
4、进入Unity的安装目录(如D:\Unity 5.4.3f1\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes下)复制classes.jar文件,粘贴到该模块UnityAndroidLibrary/libs目录下。右键该jar选择Add as Library,选Add to Module UnityAndroidLibrary。
5、打开UnityAndroidLibrary模块的AndroidManifest.xml清单文件,该文件会覆盖掉Unity的一些设置,修改如下。(从默认的app模块中的清单文件拷贝过来,把报错的地方去掉即可。记得加后面的meta-data节点)
在这里插入图片描述
6、回到模块的MainActivity,修改该类继承自UnityPlayerActivity。在该类中添加自定义的方法,用于给Unity调用。如:

public int add(int a, int b){
    return a + b;
}

7、在AS中Project目录选中unityandroidlibrary,在Build菜单下选Make Module ‘unityandroidlibrary’单独编译这个模块。
8、在unityandroidlibrary/build/intermediates/bundles/debug目录右键Show in Explorer。删除debug/libs/classes.jar(等同于刚从Unity那边拷过来的内容),把debug/classes.jar拖到debug/libs中(这个是包含了刚新增的扩展方法的)。把libs和res这两个文件夹备份(如复制到桌面)。 
在这里插入图片描述
9、在unityandroidlibrary/build/intermediates/manifests/full/debug/AndroidManifest.xml右键Show in Explorer,也把这个清单文件复制出来(如复制到桌面)。打开在桌面的副本,修改package包名为在Unity中想要的包名,如包名最后一段改为unityandroidtest(注意包名要全部小写)。
在这里插入图片描述
10、打开Unity,创建一个工程UnityAndroidTest,Build Settings切换为安卓平台,Player Settings中修改包名,包名同上一步的一致(先调平台再调包名)。在Assets下新建文件夹Plugins/Android(名字固定的,小心别漏了s),将上两步得到的三个文件拖到该文件夹中。在这里插入图片描述
11、新建一个C#脚本,VS打开编辑如下。把该脚本挂到任一场景中的游戏对象上(如Main Camera)。

using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using UnityEngine.UI;

public class Test : MonoBehaviour
{
    public Text text; // 用于展示调用结果

    void Start ()
    {
        // 获得位于com.unity3d.player包下的UnityPlayer类,固定写法。
        AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");   // 参数是包名+类名
        // 获得jc所代表的类里的currentActivity对象,固定写法。这是Unity提供的classes.jar中的功能,可通过currentActivity获取到安卓端代表MainActivty的对象。
        AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
        // 调用MainActivty中的自定义方法。
        text.text = jo.Call<int>("add", 1, 2).ToString();
    }

}

12、最后一步,连上真机并打开USB调试,Build & Run,路径选择桌面。此时会把APK输出到桌面并安装到真机上运行,即可看到调用结果。下图是我用AS的安卓模拟器(AVD)运行的效果。注意了,要打包发布出来用,直接在Unity编辑器点运行会报错,但打包出来安卓机运行没有问题的。

在这里插入图片描述
安卓调Unity
继续上面的工程。
1、在Unity刚才的脚本中,添加一个方法,给安卓调用。

// 交由安卓调Unity。
public void ChangeColor()
{
    text.color = Color.red;
}

2、在安卓端unityandroidlibrary模块的MainActivity类中,修改add()方法。该方法由Unity调用,方法中再由安卓调Unity中的方法,从而实现两者的互调

// Unity调安卓
public int add(int a, int b){
    // 安卓调Unity
    UnityPlayer.UnitySendMessage("Main Camera", "ChangeColor", ""); // 参数:GameObject名 + 方法名 + 参数
    return a + b;
}

3、重新把该模块编译。build菜单下选Make Module ‘unityandroidlibrary’。同样是在unityandroidlibrary/build/intermediates/bundles/debug目录右键Show in Explorer,拖拽debug/classes.jar到libs中替换掉libs/classes.jar。把libs和res文件夹拷贝到桌面。然后放到Unity中替换掉之前Assets/Plugins/Android目录下的libs和res文件夹。(AndroidManifest.xml可以不用替换)

4、Build & Run 。效果如下。可以看到Text文本颜色变红色了。
在这里插入图片描述
关于APP在手机桌面上显示的软件名称
当Assets/Plugins/Android/AndroidManifest.xml中的android:label节点指定的软件名,与Unity的Player Settings中Product Name指定的软件名不一致时,最终打出的APK包以前者为准!如下图。
在这里插入图片描述
在这里插入图片描述
如果上面两者不一致,以安卓清单中的软件名为准。

二、导出aar包 + 扩展MainActivity + Java主导

直接输入1次#,并按下space后,将生成1级标题。
输入2次#,并按下space后,将生成2级标题。
以此类推,我们支持6级标题。有助于使用TOC语法后生成一个完美的目录。

如何改变文本的样式

1、接着上面的项目继续。跟前面导出Jar包的区别是,导出Jar包时(已放到Unity中Assets/Plugins/Android/libs/classes.jar),res文件夹不能跟jar打包到一起,所以Unity2017推荐我们导出aar包(其实解压后就是jar + res)。

2、为演示aar包中包含了资源,在unityandroidlibrary模块的清单文件中加上icon(从另一个app模块的复制),把相应的res/mipmap也复制过来。Build菜单选择‘Build Module unityandroidlibrary’。

3、编译完成后,这次不需要再像上面导出jar那样去找res和libs文件夹,直接找到unityandroidlibrary/build/outputs/aar文件夹,里面就是导出的aar包。把这个aar包和清单文件(还是在unityandroidlibrary/build/intermediates/manifests/full/debug/AndroidManifest.xml)一并拷贝到桌面。

4、打开桌面的清单文件,修改为想要的包名。例如最后一段改为unityandroidtest(全小写,跟Unity中的保持一致)。

5、打开桌面的aar包(zip压缩工具可查看),注意,把包里根目录的classes.jar移动到libs里覆盖里面较大的classes.jar。(复制粘贴,然后删掉libs外面的)
在这里插入图片描述
6、观察aar包内容可知,相比导出jar包的方式(只有libs、res、清单xml)多了aidl、jni(提供安卓的高级功能)和R文件、assets(资源文件),这也是Unity推荐使用导出aar替代导出jar的原因之一。

7、把桌面的清单xml文件剪切到Unity的Assets/Plugins/Android/里,这份xml是指导Unity打包APK的总清单,它的包名需要与Unity里写的一致,相对aar包来说是外部的清单。

8、打开桌面aar包里的xml清单文件,删除android:icon和android:label这两行并保存。因为这个xml清单是该模块自己的,为了防止跟aar包外的总清单冲突。

9、最后,再把改好的aar包导入Unity的Assets/Plugins/Android中,项目结构如下。可以看到Unity把aar包识别成了一个插件。

在这里插入图片描述
10、启动安卓模拟器,Unity执行Build & Run后即可看到效果。与导出jar包的运行结果一致。

注意:可能会出现Unity能导出APK,但是不能安装到模拟器上的,Unity报错如下。

在这里插入图片描述

三、互调模式之提供Java扩展类

适用场景:在安卓中用Java执行一些操作,且不需要资源(图片等)的情况。可以把Java代码封装成jar后导入Unity中供Unity调用。由于在安卓端编写代码,可以使用安卓的各种高级语法(监听器等)。但由于Test类不能用安卓上下文Context对象,能力有限,所以通用性不高(想传入安卓上下文对象需要额外的操作)。跟上一种方法相比,不是扩展MainActivity,而是另写到一个类中(也因此失去了上下文)。

1、打开AS新建一个工程叫SimpleClass,新建一个Module(选Android Library)取名SimpleLibrary。把Unity的classes.jar包导入到该模块中(跟上面一样,这是让安卓能调用Unity的标准操作,即若只想Unity调安卓可以不导入该classes.jar)。

2、新建一个Test类。在该扩展类中编写跟Unity交互的方法。
在这里插入图片描述

public class Test {
    public int add(int a, int b){
        UnityPlayer.UnitySendMessage("Main Camera", "ChangeColor", "");
        return a + b;
    }
}

3、Build该模块后,切到Project视图,把simplelibrary/build/intermediates/bundles/debug/classes.jar文件拖到Unity中Asset/Plugins/Android目录下。
在这里插入图片描述
在这里插入图片描述
5、Unity中调用该方法。非静态方法由类的对象来调用。

void Start ()
{
    // 获得安卓中test.jar中的Test类对象
    AndroidJavaObject jo = new AndroidJavaObject("me.guxin.simplelibrary.Test"); // 参数:包名,调用空参构造函数
    // 调用类中的自定义方法。
    text.text = jo.Call<int>("add", 1, 2).ToString();

    /* 如果的静态方法
    // 获得安卓中test.jar中的Test类
    AndroidJavaClass jc = new AndroidJavaClass("me.guxin.simplelibrary.Test");
    // 调用静态方法
    text.text = jc.CallStatic<int>("add", 1, 2).ToString();
    */
}

6、打包APK后丢到安卓模拟器中运行,即可看到运算结果。

四、互调模式之C#主导式调用

对于不熟悉安卓开发的同学,可以打开Android Studio新建一个空工程,查看安卓Log()方法的签名,再在Unity中照着安卓的结构写C#代码调用安卓SDK原生方法。

手动打印的安卓错误日志,可以在AS的Log Cat中看到输出

Unity中接安卓SDK通常使用的组合:导出aar + 拓展MainActivity + Java主导 。因为第三方SDK通常是争对安卓平台做的。

简单功能可用组合: Class拓展 + C#主导 。适用于简单功能,如调用安卓土司Toast。好处是不用在AS导出项目给Unity当插件使用。

void Start ()
{
    AndroidJavaClass jc = new AndroidJavaClass("android.util.Log"); // 安卓SDK中的包名
    text.text = jc.CallStatic<int>("e", "UnityAndroidTest", "ErrorTest").ToString(); // 相当于在安卓中写 Log.e("UnityAndroidTest", "ErrorTest");
}
举报

相关推荐

0 条评论