Unity2019.3.3与Android Studio 3.6.1 交互通信

最近做了一项目需要用到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
在这里插入图片描述
显示选择界面 点击Empty Activity - Next
在这里插入图片描述
填写项目名称Unity2Android (这个名可以随便填后面用不到),Minimum SDK 最好和Unity的项目选择一样的
在这里插入图片描述
做到这一步你就建成一个新的AS项目了,不过然并卵
在这里插入图片描述

1.2添加Modules

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

点击 File - Project Structure
在这里插入图片描述
点击Modules - +
在这里插入图片描述在这里插入图片描述
选中Android Library 点击 Next
在这里插入图片描述这里的参数比较重要,这个就是我们导出jar用的Modules,注意这个Module Name和Package Name 这里后面会用到,Minimum SDK 最好和Unity的项目选择一样的
填好name后,点击Finish 你就拥有一个可以导出的Jar的Module了
在这里插入图片描述

添加Compile SDK Version和Build Tools Version的版本就可以点击Apple 和OK
然后 AS项目会加载一会
在这里插入图片描述
在你的AS项目中就可以看到有一个新的u2a的文件夹这个就是刚才添加的Modules在这里插入图片描述

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中找到
在这里插入图片描述
在拷贝的classes.jar上点击右键选中Add as Library,添加到u2a moduls中
在这里插入图片描述
在这里插入图片描述

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,

在这里插入图片描述
在这里插入图片描述
此时你的文件结构应该如下图
在这里插入图片描述
将UnityPlayerActivity.java的引入更新

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

在这里插入图片描述
编写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>

在这里插入图片描述

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版本的不同

如果执行上面的导出命令后,没有导出AndroidPlugin.jar文件,可以尝试将:from(‘build/intermediates/aar_main_jar/release/’)
替换成
from(‘build/intermediates/packaged-classes/release/’)

这个路径查看方法就是在u2a下的build文件夹中找classes.jar文件位置

在这里插入图片描述

刷新Gradle
在这里插入图片描述
点击u2a - other - exportJar 会在u2a\release中生成AndroidPlugin.jar
就是我们刚才在配置的u2a modules 然后将AndroidPlugin.jar复制到unity项目中Assets\Plugins\Android中
在这里插入图片描述
在这里插入图片描述

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.将第三步生成的AndroidPlugin.jar文件拷贝到Assets/Plugins/Android/bin目录下

完成之后文件结构图如下:
在这里插入图片描述
libs目录用于存放其它android插件的jar文件,没有也可以不用创建。

2.2、制作一个UI界面

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

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

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

在这里插入图片描述

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

在这里插入图片描述

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

在这里插入图片描述

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通信成功。

演示见下图:

调用 前:在这里插入图片描述,调用后: 在这里插入图片描述

3总结

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

  • 6
    点赞
  • 33
    收藏
    觉得还不错? 一键收藏
  • 20
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 20
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值