Unity调用Android 这么做方便,但是对于一般人而言,不太会写,而且容易拼写错误
所有还是使用AS导出jar包或者aar包,亦或者直接把写好的java代码放在unity/plugins/android
目录下面
新建AS工程然后导入unity下路的classes.jar包, 2019版本及以上版本中classes.jar包中可能没有UnityPlayerActivity
,需要单独重新导入
classes.jar路径:xx/Editor\Data\PlaybackEngines\AndroidPlayer\Variations\mono\Release\Classes
UnityPlayerActivity:xx/Editor\Data\PlaybackEngines\AndroidPlayer\Source\com\unity3d\player
新建一个Activity继承UnityPlayerActivity,然后在里面写一些逻辑代码
如果只是工具类 不想继承UnityPlayerActivity,那么自己规定好包名使用静态方法调用即可
如新建了Activity继承UnityPlayerActivity,需要在Unity中创建AndroidManifest.xml,指向启动的activity
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.
最后把写好的java代码放到Unity/Plugins/Android 目录下
编写C#代码
AndroidJavaClass
: 是java.lang.Class 类
主要用于获取静态字段或调用静态方法 C#中静态类.方法 或类.静态方法
AndroidJavaObject
:是java.lang.Object 实例对象
调用对象方法: Call 方法,需要new
直接找到包名下对应的类,是一个类 只能调用一些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 中的一个类
调用android方法最好是在ui线程中 即: runOnUiThread
我的csdn文章有具体操作:(Unity与Android通信交互_Zero_LJ的博客-CSDN博客_unity android 交互
Android调用Unity Android中调用Unity代码,就是给Unity发消息,Unity针对不同的消息处理逻辑
在Java代码中使用UnityPlayer.UnitySendMessage(string str1,string str2,string arg)
方法
该方法有三个参数:
参数1是Unity场景GameObject名称
参数2是该GameObject上面的方法
第三个是该方法的参数 可以为null
使用AndroidJavaProxy进行交互 UnityPlayer.UnitySendMessage(string str1,string str2,string arg)
性能及其不好,采用AndroidJavaProxy
AndroidJavaProxy需要在java和C#建立桥接
java代码
1 2 3 4 5 6 7 8 package com.zeroultra.connecter;public interface NativeAndroidProxy { public void SendToUnity (String cmd,String msg) ; }
C#代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 using System;using UnityEngine;public class NativeAndroidProxy : AndroidJavaProxy { public event Action<string , string > OnReceiveMsg; public NativeAndroidProxy (string proxyName ) : base (proxyName ) { } void SendToUnity (string cmd, string msg ) { OnReceiveMsg?.Invoke(cmd, msg); } }
然后C#层声明代理传入Java层
java
1 2 3 4 5 6 7 8 9 10 11 12 package com.zeroultra.connecter;import android.util.Log;public class TestAndroid { public void SendToUnity (NativeAndroidProxy proxy) { bridge.SendToUnity("android" ,"hello窝窝窝" ); } }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 public class Test :Monobehaviour { void Start () { NativeAndroidProxy proxy=new NativeAndroidProxy(); proxy.OnReceiveMsg+=(cmd,msg)=>{}; using (AndroidJavaObject jo = new AndroidJavaObject("com.zeroultra.connecter.TestAndroid" )) { jo.Call("SendToUnity" ,proxy); } } }
Unity直接调用android代码记录 Toast 1 2 3 4 5 6 7 8 9 10 11 12 13 private void ToastText (string str ){ AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer" ); AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity" ); AndroidJavaClass Toast = new AndroidJavaClass("android.widget.Toast" ); AndroidJavaObject context = currentActivity.Call<AndroidJavaObject>("getApplicationContext" ); currentActivity.Call("runOnUiThread" , new AndroidJavaRunnable(() => { AndroidJavaObject javaString = new AndroidJavaObject("java.lang.String" , str.ToString()); Toast.CallStatic<AndroidJavaObject>("makeText" , context, javaString, Toast.GetStatic < int ("LENGTH_SHORT" )).Call("show" ); } )); }
Intent 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 private void openAPPinMarket (string appid ) { #if UNITY_ANDROID AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer" );; AndroidJavaClass Intent = new AndroidJavaClass ("android.content.Intent" ); AndroidJavaClass Uri = new AndroidJavaClass ("android.net.Uri" ); AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity" ); AndroidJavaObject jstr_content=new AndroidJavaObject("java.lang.String" ,"market://details?id=" +appid); AndroidJavaObject intent = new AndroidJavaObject ("android.content.Intent" ,Intent.GetStatic<AndroidJavaObject>("ACTION_VIEW" ),Uri.CallStatic<AndroidJavaObject>("parse" ,jstr_content)); currentActivity.Call ("startActivity" ,intent); #endif }
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 AndroidJavaClass UnityPlayer = new AndroidJavaClass("com.unity3d.player.UnityPlayer" ); AndroidJavaObject currentActivity = UnityPlayer.GetStatic<AndroidJavaObject>("currentActivity" ); AndroidJavaClass Uri = new AndroidJavaClass("android.net.Uri" ); var newuri = Uri.CallStatic<AndroidJavaObject>("parse" , uri); AndroidJavaClass intentClass = new AndroidJavaClass("android.content.Intent" ); AndroidJavaObject intentObject = new AndroidJavaObject("android.content.Intent" ); intentObject.Call<AndroidJavaObject>("setAction" , intentClass.GetStatic<string >("ACTION_VIEW" )); intentObject.Call<AndroidJavaObject>("setData" , newuri); try { currentActivity.Call("startActivity" , intentObject); } catch (Exception e){ Debug.LogError("未安装 " + e.ToString()); }
遇到的问题 Unity2021.2以上版本Android不能放res文件夹 描述
Unity - Manual: Upgrading to Unity 2021.2 (unity3d.com)
解决方案
用AndroidStudio打包成arr,然后导入 参考:AndroidStudio打包AAR供Unity使用流程
直接把文件命名成xxxx.androidlib,然后添加两个文件,一个AndroidManifest.xml
和project.properties
Unity2021.2版本打包报错
AndroidManifest.xml
1 2 3 4 5 6 <?xml version="1.0" encoding="utf-8" ?> <manifest xmlns:android ="http://schemas.android.com/apk/res/android" package ="custom.android.res" <--这里随便命名-- > android:versionCode="1" android:versionName="1.0"> </manifest >
project.properties
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 android.library =true
然后把res文件和这两个放在一起就可以了