欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Unity2019.3.3与Android Studio 3.6.1 交互通信

程序员文章站 2022-05-29 21:37:23
...

最近做了一项目需要用到Unity和原生安卓之间的通讯,用的是Unity2019.3.3版本的Android Studio 3.6.1版本的导出jar 在网上看了许多帖子发先都是过时了,今天趟了一天坑,不过总有搞定了

一.参考资料

https://www.cnblogs.com/imteach/p/11567481.html
https://blog.csdn.net/qq_33337811/article/details/88556927
https://blog.csdn.net/xiayiye5/article/details/79639044https://www.jianshu.com/p/16b33d3aedcd
https://www.jianshu.com/p/8256c0da444a
https://docs.unity3d.com/Manual/AndroidUnityPlayerActivity.html(没事多看看官网文档还是好的)

二.实际操作

本次开发所使用的软件版本如下:

Android Studio 3.6.1

Unity 2019.3.3f1

1.制作jar文件

1.1新建Android Studio(以下简AS) 工程

打开AS之前有工程的话点击File - New - New Project
Unity2019.3.3与Android Studio 3.6.1 交互通信
显示选择界面 点击Empty Activity - Next
Unity2019.3.3与Android Studio 3.6.1 交互通信
填写项目名称Unity2Android (这个名可以随便填后面用不到),Minimum SDK 最好和Unity的项目选择一样的
Unity2019.3.3与Android Studio 3.6.1 交互通信
做到这一步你就建成一个新的AS项目了,不过然并卵
Unity2019.3.3与Android Studio 3.6.1 交互通信

1.2添加Modules

之前看到许多帖子在project属性栏中直接添加,我发现这样做会出现嵌套问题,所有自己有摸索了一种新的添加方式

点击 File - Project Structure
Unity2019.3.3与Android Studio 3.6.1 交互通信
点击Modules - +
Unity2019.3.3与Android Studio 3.6.1 交互通信Unity2019.3.3与Android Studio 3.6.1 交互通信
选中Android Library 点击 Next
Unity2019.3.3与Android Studio 3.6.1 交互通信这里的参数比较重要,这个就是我们导出jar用的Modules,注意这个Module Name和Package Name 这里后面会用到,Minimum SDK 最好和Unity的项目选择一样的
填好name后,点击Finish 你就拥有一个可以导出的Jar的Module了
Unity2019.3.3与Android Studio 3.6.1 交互通信

添加Compile SDK Version和Build Tools Version的版本就可以点击Apple 和OK
然后 AS项目会加载一会
Unity2019.3.3与Android Studio 3.6.1 交互通信
在你的AS项目中就可以看到有一个新的u2a的文件夹这个就是刚才添加的ModulesUnity2019.3.3与Android Studio 3.6.1 交互通信

1.3添加Unity classes.jar到AS项目中

点击三角号到选中Project - 点击文件u2a - libs - 在libs上点击右键 - 打开Show in Explorer
将 classes.jar 到 u2a\libs中

classes.jar路径:Unity(Unity的安装路径下)\Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Development\Classes
据我所知classes.jar在Unity2019.2以下的版本中有UnityPlayerActivity类,在Unity2019.2以上的版本中将UnityPlayerActivity取消了不过可以在Unity(Unity的安装路径下)\Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player中找到
Unity2019.3.3与Android Studio 3.6.1 交互通信
在拷贝的classes.jar上点击右键选中Add as Library,添加到u2a moduls中
Unity2019.3.3与Android Studio 3.6.1 交互通信
Unity2019.3.3与Android Studio 3.6.1 交互通信

1.4添加Unity和安卓的通信类和添加UnityPlayerActivity.java

将Unity(Unity的安装路径下)\Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player中的UnityPlayerActivity.java拷贝到u2a\main\java\com.xiaoma.u2a(这里你是自己的包名)中
在u2a\main\java\com.xiaoma.u2a中新建一个Empty Activity,

Unity2019.3.3与Android Studio 3.6.1 交互通信
Unity2019.3.3与Android Studio 3.6.1 交互通信
此时你的文件结构应该如下图
Unity2019.3.3与Android Studio 3.6.1 交互通信
将UnityPlayerActivity.java的引入更新

//package com.unity3d.player.;
// 添加
package com.xiaoma.u2a;
import com.unity3d.player.IUnityPlayerLifecycleEvents;
import com.unity3d.player.UnityPlayer;

Unity2019.3.3与Android Studio 3.6.1 交互通信
编写MainActivity.java

package com.xiaoma.u2a;

import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.os.Bundle;
import android.widget.Toast;

import com.unity3d.player.UnityPlayer;

public class MainActivity extends UnityPlayerActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
    }
    //unity调用Android
    public void UnityCallAndroid () {

        Toast.makeText(this,"unity调用android成功", Toast.LENGTH_LONG).show();

        AndroidCallUnity();
    }

    //android调用unity
    public void AndroidCallUnity () {

        //第1个参数为Unity场景中用于接收android消息的对象名称
        //第2个参数为对象上的脚本的一个成员方法名称(脚本名称不限制)
        //第3个参数为unity方法的参数
        UnityPlayer.UnitySendMessage("receiveObj", "UnityMethod", "This is args.");
    }
}

修改u2a中的AndroidManifest.xml

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

    <application>

        <!-- 这个android:name的值必须为包名+类名-->
        <activity android:name="com.xiaoma.u2a.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <!-- 这一行不能少,否则会闪退-->
            <meta-data android:name="unityplayer.UnityActivity" android:value="true" />
        </activity>
    </application>

</manifest>

Unity2019.3.3与Android Studio 3.6.1 交互通信

1.5添加build.gradle文件

注意这个build.gradle是u2a moduls的build.gradle文件不是项目的build.gradle
u2a moduls的build.gradle位置在u2a\build.gradle
在build.gradle文件尾部添加

//----------------这是一组将module导出为jar的gradle命令-------------------
task deleteOldJar(type: Delete) {
    delete 'release/AndroidPlugin.jar'
}

//task to export contents as jar
task exportJar(type: Copy) {
    from('build/intermediates/aar_main_jar/release/') 
    into('release/')
    include('classes.jar')
    ///Rename the jar
    rename('classes.jar', 'AndroidPlugin.jar')
}

exportJar.dependsOn(deleteOldJar, build)
//------------命令结束------------------------------

其中在这里插入代码片from('build/intermediates/aar_main_jar/release/')的路径和AS版本有关每个不同的AS版本的不同
Unity2019.3.3与Android Studio 3.6.1 交互通信

刷新Gradle
Unity2019.3.3与Android Studio 3.6.1 交互通信
点击u2a - other - exportJar 会在u2a\release中生成AndroidPlugin.jar
就是我们刚才在配置的u2a modules 然后将AndroidPlugin.jar复制到unity项目中Assets\Plugins\Android中
Unity2019.3.3与Android Studio 3.6.1 交互通信
Unity2019.3.3与Android Studio 3.6.1 交互通信

2.Unity工程

参考:https://www.cnblogs.com/imteach/p/11567481.html

2.1、新建一个Unity工程。

a.新建一个Unity工程,在Assets目录下新建Plugins/Android/bin目录。

b.将第三步修改的AndroidManifest.xml文件拷贝到Assets/Plugins/Android目录下

c.将第三步生成的mysdk.jar文件拷贝到Assets/Plugins/Android/bin目录下

完成之后文件结构图如下:
Unity2019.3.3与Android Studio 3.6.1 交互通信
libs目录用于存放其它android插件的jar文件,没有也可以不用创建。

2.2、制作一个UI界面

a.在SampleScene场景中创建一个Canvas,并创建一个名为"receiveObj"的对象,在receiveObj之下再放一个按钮和一个Text。

按钮用于触发调用Android方法。

Text用于显示Android调用Unity方法传递来的参数。如下图:

Unity2019.3.3与Android Studio 3.6.1 交互通信

这里要注意,receiveObj的名称必须与SDKMainActivity类的AndroidCallUnity方法中的UnityPlayer.UnitySendMessage方法的第一个参数保持一致。

Unity2019.3.3与Android Studio 3.6.1 交互通信

b.创建一个SDKTest.cs文件,将脚本挂在receiveObj对象上。如下:

Unity2019.3.3与Android Studio 3.6.1 交互通信

SDKTest脚本的内容如下:

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

public class SDKTest : MonoBehaviour
{
    private AndroidJavaClass jc;
    private AndroidJavaObject jo;

    private Button btn;
    private Text text;

    private void Awake()
    {
        btn = transform.Find("Button").GetComponent<Button>();
        text = transform.Find("Text").GetComponent<Text>();

        //这两行是固定写法
        jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
        jo = jc.GetStatic<AndroidJavaObject>("currentActivity");

        btn.onClick.AddListener(OnBtnClickHandler);
    }

    private void OnBtnClickHandler ()
    {
        //调用Android中的方法UnityCallAndroid
        jo.Call("UnityCallAndroid");
    }

    /// <summary>
    ///  被Android中AndroidCallUnity调用
    /// </summary>
    /// <param name="str"></param>
    public void UnityMethod(string str)
    {
        Debug.Log("UnityMethod被调用,参数:" + str);
        text.text = str;
    }
}

其中必须要有UnityMethod方法,因为它在AndroidCallUnity方法中的UnityPlayer.UnitySendMessage的第二个参数已经指定了。如果不存在的话,调用就会出错。

jc = new AndroidJavaClass(“com.unity3d.player.UnityPlayer”);
jo = jc.GetStatic(“currentActivity”);

这两句,一个是获取到UnityPlayer类,一个是获取到类的实例。
到于为什么这样能取到我创建的模块的SDKMainActivity的实例,还有待探究。反正目前这么写了就行了。

2.3、打包并测试。

在unity中设置Bundle Identifier和Company等信息之后,打一个apk包。

安装后运行,能正常显示UI。

点击按钮后,显示了一个Toast,提示“Unity调用Android成功”,说明jar包中的UnityCallAndroid方法被调用。

Unity->Android通信成功。

同时屏幕上方的NewText被变更为“This is args”,"This is args"是 AndroidCallUnity方法中传递给UnityMethod方法的参数。

这表示Android->Unity通信成功。

演示见下图:

调用 前:在这里插入图片描述,调用后: Unity2019.3.3与Android Studio 3.6.1 交互通信

3总结

1.注意classes.jar的版本
2.注意AS的版本和from(‘build/intermediates/aar_main_jar/release/’) `的路径
3.主要AndroidManifest的配置