Unity与Android通信交互

版本

Unity2019.3以上 Android 3.4以上

前言

UnityPlayerActivity找不到!UnityPlayerActivity找不到!UnityPlayerActivity找不到!
换了2019.4版本 ,导出android发现很多错误.例如UnityPlayerActivity找不到,资源重复等等问题.原因在于Unity做了更改.好像是2019.2之后的版本做了升级(具体那个版本不知)
更新2022/1/19 发现之前的有些误人子弟 重新写

直接导出导出Java类文件到Unity中

创建一个类库

在这里插入图片描述

Android Studio中的配置和代码示例

首先导入classes.jar,这一步都是没有变化,根据自己andriod项目mono/IL2Cpp,找到对应的jar包,例如我的项目

ctrl+c,然后在AS Libs文件夹中ctrl+v,然后再点击Add as library

然后新建一个类MainActivity,发现继承不了UnityplayerActivity

插件unity的Classes.jar包中是没有这个类存在的,这个时候我们需要在Untiy中找到UnityPlayerActivity,例如我的路径

直接把这个包拷贝过来
在这里插入图片描述
然后我们在MainActivity中写代码

package com.tantrum.md;
import android.os.Bundle;
import android.util.Log;
import android.widget.Toast;
import com.unity3d.player.UnityPlayerActivity;

public class MainActivity extends UnityPlayerActivity {

    public static MainActivity Ins=null;  //单例模式
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        Ins=this;
        Log.i(AndroidUnityConnecter.UnityTag,"启动");
    }

    public void GetString(String args)
    {
        String a= "Unity:"+args;
        Log.i(AndroidUnityConnecter.UnityTag,a);
        AndroidUnityConnecter.SendMsgToUnity(a);
    }
    public void SayToast(final String msg)
    {
        runOnUiThread(new Runnable() {
            @Override
            public void run() {
                Toast.makeText(getApplicationContext(),msg,Toast.LENGTH_LONG).show();
            }
        });
    }

    @Override
    protected void onStart() {
        super.onStart();
        Log.i(AndroidUnityConnecter.UnityTag,"开始Start");
    }
}

AndroidUnityConnecter

package com.tantrum.md;
import com.unity3d.player.UnityPlayer;
public  class AndroidUnityConnecter {

    private static final String connecterName = "UnityAndroidConnecter"; //通信物体
    private static final String defaultMethodName = "ReceiveAndroidMsg"; //方法

    public static final String UnityTag="Unity";
    
    //发送消息到Unity
    public static void SendMsgToUnity(String args)
    {
        UnityPlayer.UnitySendMessage(connecterName, defaultMethodName,args);
    }

    //发送消息到Unity
    public static void SendMsgToUnity(String methodName,String args)
    {
        UnityPlayer.UnitySendMessage(connecterName,methodName,args);
    }

    /*接收到Unity发来的消息*/
    public static void ReceiveUnityMsg(String key,String args)
    {
        //根据接受到的消息处理
        switch (key)
        {
            case "getstring":
                MainActivity.Ins.GetString(args);
                break;
            case "toast":
                MainActivity.Ins.SayToast(args);
                break;
        }
    }
}

Unity中操作

在PlayerSetting中,勾选之后会自动生成一个Androidmainfest.xml
在这里插入图片描述
修改AndroidManifest.xml
在这里插入图片描述

https://blog.csdn.net/wu_wenhuan/article/details/44941545/
Android.intent.action.MAIN决定应用程序最先启动的
ctivity android.intent.category.LAUNCHER决定应用程序是否显示在程序列表里
通过实验后,发现有问题?
MAIN 与 LAUNCHER 并不是单纯的各管各的事情;
我测试的结果是,如果一个应用没有LAUNCHER则该apk仍能安装到设备上,但是在桌面中图标中看不到。如果给那个Activity 设定了LAUNCHER,且同时设定了Main,则这个Activity就可出现在程序图标中;如果没有Main,则不知启动哪个Activity,故也不会有图标出现。可见,Main指的是,点击图标后启动哪个Activity。当然,Main可以给多个Activity设定,但只设定Main不设定LAUNCHER,仍然无法进入activity。
可见,Main和LAUNCHER同时设定才有意义,如果多个activity同时设定,则会出现两个图标,分别先进入不同的activity.如下图

然后把我们写的MainActivity.java AndroidUnityConnecter.java放到Unity->Plugins->Android文件夹下面
在这里插入图片描述
然后建立一个简单界面,写交互代码
在这里插入图片描述
新建一个GameObject名字是Java代码设定的名字,比如我的就是UnityAndroidConnecter, 关于UnityPlayer.UnitySendMessage,第二个方法名字,可以是private 也可以是public
在这里插入图片描述

using System.Collections;
using System.Collections.Generic;
using System.Text;
using UnityEngine;

public class UnityAndroidConnecter : MonoBehaviour
{
    [Header("默认交互 包.静态类名(AndroidJavaClass)")]
    [SerializeField] string defaultAndroidPackageClass= "com.tantrum.md.AndroidUnityConnecter";
    [Header("默认 静态类.接收消息方法名")]
    [SerializeField] string defaultReceiveMethodName= "ReceiveUnityMsg";

    
    public UnityEngine.UI.Button btnToast, btnMsg;
    public UnityEngine.UI.Text text;
    private void Start()
    {
        btnToast.onClick.AddListener(Toast);
        btnMsg.onClick.AddListener(CallAndroid);
    }

    public void Toast()
    {
        SendMsgToAndroid("toast", "Hello Android");
    }

    public void CallAndroid()
    {
        SendMsgToAndroid("getstring", "Hello Android");
    }

    /// <summary>
    /// 发送消息到Android
    /// </summary>
    /// <param name="key">key</param>
    /// <param name="args">参数</param>
    public void SendMsgToAndroid(string key, string args)
    {
        using (AndroidJavaClass jc = new AndroidJavaClass(defaultAndroidPackageClass))
        {
            jc.CallStatic(defaultReceiveMethodName, key, args);
        }
    }



    /// <summary>
    /// 接收来自Android的消息 (ReceiveAndroidMsg方法名要和java代码中保持一致)
    /// </summary>
    /// <param name="args">参数</param>
    public void ReceiveAndroidMsg(string args)
    {
        //根据接收到的消息自定义处理
        text.text = $"来自Android的消息:{args}";
    }
}

然后直接Unity中打包
在这里插入图片描述

遇到的问题

  1. 不能使用下面代码调用Toast
     using (AndroidJavaObject jo = new AndroidJavaObject("com.tantrum.md.MainActivity"))
        {
            jo.Call("SayToast", "Hello Android");
        }
    
    但是可以调用
     using (AndroidJavaObject jo = new AndroidJavaObject("com.tantrum.md.MainActivity"))
        {
            jo.Call("GetString", "Hello Android");
        }
    
    这个问题暂时不知道,应该跟Toast有关系

导出Jar包,ARR包

略了,直接到处java最方便

总结一些知识

  1. AndroidJavaClass : 是java.lang.Class 类 主要用于获取静态字段或调用静态方法 C#中静态类.方法 类.静态方法
    AndroidJavaObject:是java.lang.Object 实例对象 调用对象方法: Call 方法,有泛型与非泛型的两个版本。 这就是一个实例对象.例如Unity 你 获取一个GameObject然后调用他的方法.

    这个是直接找到包名下对应的类,是一个类 不是一个对象,所以只能调用一些static 方法
    AndroidJavaClass androidJC = new AndroidJavaClass(com.xxx.xx.xxxClass);

    获取一个对象也可以直接 用
    AndroidJavaObject androidJO = new AndroidJavaObject(com.xxx.xx.xxxClass); 表示new一个该包名下的类
    这个也可以直接找到对象 然后调用对象上面的普通方法

    我们常用的
    AndroidJavaClass androidJC = new AndroidJavaClass(com.unity3d.player.UnityPlayer);
    AndroidJavaObject jo=androidJC.GetStatic<AndroidObject>("currentActivity");
    其实就是在或者获取 UnityPlayerActivity 单例
    com.unity3d.player.UnityPlayer 是classes.jar 中的一个类
    在这里插入图片描述
    在这里插入图片描述

  2. 调用android方法最好是在ui线程中 即: runOnUiThread

  3. 附加几个文章链接
    https://www.jianshu.com/p/b5e3cfcdf081
    https://blog.csdn.net/osuckseed/article/details/84940618

  4. 最后大家可以看看这个系列视频哈 讲的很明白https://www.bilibili.com/video/BV1Qt4y1a7aW?p=6&t=392

感谢一下文章

  1. Unity2019安卓环境配置
  2. 最新Unity 与Android 交互通信(基于Unity 2019.4 和 Android Studio 4.1.1)
  3. Unity3D与Android平台通信
  4. Unity2019.4.4与AndroidStudio3.5.2交互
  5. android:属性大全
评论 37
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值