unity与android交互相关资料整理(U2A)
Posted guaike01
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了unity与android交互相关资料整理(U2A)相关的知识,希望对你有一定的参考价值。
一、关于Unity和android交互的那些坑(引自:https://blog.csdn.net/qq_24189773/article/details/89188048)
1.交互包
例如:AndroidJavaClass jc = new AndroidJavaClass("xxx.xxx.xxx.具体类"); 其中,xxx.xxx.xxx 是包名。获取到这个类之后,我们可以调用该类的静态方法。
包名通常用的是com.unity3d.player,这个最好不要改变,也就是说,在android封包时,将目录结构统一为“com/unity3d/player/具体类”格式。
2.具体类:普通类与继承类(extends or not)
在网上给的方案里,大多数具体类都是需要继承于UnityPlayerActivity,然而,并不是非要继承于UnityPlayerActivity才可以起交互作用的。仅仅是写一个普通类,也是可以进行交互的,不过普通类没有UnityPlayerActivity的继承特性,优点是更加灵活。
3.unity与android沟通的桥梁——UnityPlayer具体类
我们称它为“桥梁类”。它可以方便的调试看你的具体类与unity是否连接通畅。这是官方给你预置好的一个范例类。UnitySendMessage是它的神器。
在android中,通过import com.unity3d.player.UnityPlayer将它引用到自己的具体类中,这样就可以通过UnityPlayer.UnitySendMessage方法与Unity中特定的方法沟通。
在Unity中,通过AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer")和AndroidJavaObject jo=jc.GetStatic<AndroidJavaObject>("currentActivity")建立起UnityPlayer实例,通过jo.call()的方法与android中预置的非静态方法进行沟通。当然你也可以在你的具体类中声明静态方法,通过jc直接调用,不过吃内存的。
你可以建立一个TestU2A的非静态方法,用神器向unity的指定对象指定方法发送消息,用Canvas---Text的方式检验你的具体类是否畅通连接了U2A。
4.AndroidJavaObject与AndroidJavaClass
①AndroidJavaClass负责获取java类,然后可以调用该类的静态方法,例如 jc.GetStatic("xxxx");, 就是调用静态方法xxx。jo=jc.GetStatic<AndroidJavaObject>("currentActivity"); 则是获取该类的一个静态变量,变量名为currentActivity。jc不可以调用实例方法,因为该类没有被创建。而jo是实例化的变量,可以直接调用非静态方法。以下可参考帮助理解:
静态方法是使用公共内存空间的,就是说所有对象都可以直接引用,不需要创建对象再使用该方法。 (引自:https://wenda.so.com/q/1378288347062339?src=140&q=%E9%9D%99%E6%80%81%E6%96%B9%E6%B3%95)
例如,我创建一个类,里面有一个静态方法:
class Test{
public static int z(int xx,int yy){
return xx+yy;
}
public int zz(int xx,int yy){
return xx+yy;
}
}
然后在含有main方法的类中使用这个类时,对与以上非静态和静态方法的引用方式是不同的,如下:
import Test;
public class mainClass{
int sum;
public static void main(String args[]){
sum=Test.z(1,2); //直接用 类.方法或者属性就可以使用该方法或属性。
System.out.println(sum);
Test t=new Test();
sum=t.zz(1,2); //因为zz不是静态方法,所以只能只能用Test类创建一个t对象,然后调用该对象的方法。
System.out.println(sum);
}
}
PS:静态方法只能被静态方法调用,优点是方便,缺点是吃内存。非静态方法只有将class实例化后再调用,优点是省内存,缺点是费事。
②AndroidJavaObject 它有两种方法实例化java类。一种是new方法:jo=new AndroidJavaObject("xxx.xxx.xxx.xxx",arg[]),这个是官方给出的。还有一种是GetStatic方法:jo=jc.GetStatic<AndroidJavaObject>("xxx"),直接获取该类内的某个静态方法并实例化。
二、获取Activity及调用Android原生方法(引自https://blog.csdn.net/asd237241291/article/details/41358867)
1.获取Activity
1 //获取当前App的Activity 2 public static AndroidJavaObject Current() 3 { 4 if (Application.platform == RuntimePlatform.Android) 5 return new AndroidJavaClass("com.unity3d.player.UnityPlayer").GetStatic<AndroidJavaObject>("currentActivity"); 6 else 7 return null; 8 } 9 10 //获取指定包名的Activity 11 public static AndroidJavaObject GetActivity(string package_name,string activity_name) 12 { 13 return new AndroidJavaClass(package_name).GetStatic<AndroidJavaObject>(activity_name); 14 }
2.调用Android原生方法
1 // UI线程中运行 2 public static void RunOnUIThread(AndroidJavaRunnable r) 3 { 4 Current().Call("runOnUiThread", r); 5 } 6 7 //获取包名 8 public static string getPackageName() 9 { 10 return Current().Call<string>("getPackageName"); 11 } 12 //讲解:call<返回值类型>("方法名"); 13 14 //设置 不自动锁屏 15 public static void DisableScreenLock() 16 { 17 Current().Call<AndroidJavaObject>("getWindow") 18 .Call("addFlags",128); 19 } 20 //讲解:call("方法名",参数1); 21 22 // 获取内置SD卡路径 23 public static string GetStoragePath() 24 { 25 if (Application.platform == RuntimePlatform.Android) 26 return new AndroidJavaClass("android.os.Environment").CallStatic<AndroidJavaObject>("getExternalStorageDirectory").Call<string>("getPath"); 27 else 28 return "d:/movie"; 29 } 30 //讲解:new AndroidJavaClass("全类名") ---new一个Android原生类 31 //讲解:CallStatic<返回类型>("方法名") ---静态方法获取一个Android原生类型
三、so文件、classes.jar、armeabi和armeabi-v7a
1.so文件(引自:https://wenda.so.com/q/1534462693218862)
SO文件是Linux下共享库文件,它的文件格式被称为ELF文件格式。由于Android操作系统的底层基于Linux系统,所以SO文件可以运行在Android平台上。
Android系统也同样开放了C/C++接口供开发者开发Native程序。由于基于虚拟机的编程语言JAVA更容易被人反编译,因此越来越多的应用将其中的核心代码以C/C++为编程语言,并且以SO文件的形式供上层JAVA代码调用,以保证安全性。
so文件使用方法:
(1)动态库的编译。这里有一个头文件:so_test.h,三个.c文件:test_a.c、test_b.c、test_c.c,我们将这几个文件编译成一个动态库:libtest.so。
命令:$ gcc test_a.c test_b.c test_c.c -fPIC -shared -o libtest.so 不用该标志外部程序无法连接。相当于一个可执行文件。
(2)动态库的链接这里有个程序源文件 test.c 与动态库 libtest.so 链接生成执行文件 test:命令:$ gcc test.c -L. -ltest -o test命令:$ ldd test执行test,可以看到它是如何调用动态库中的函数的。
参考资料来源:百度百科—SO(软件编程)
2.关于 classes.jar
Unity 发布 Android 的 APK 时,会使用 Android 的 SDK 进行构建,发布出来的 APK 只包含一个 Activity,俗称MainAcitivity,在发布过程中,Unity 会引入内置的 Jar 库(classes.jar),里面包含了 Unity 需要的库类,关键类 UnityPlayerActivity 就是 Android 程序的主要入口类,也就是 MainActivity。
————————————————
版权声明:本文为CSDN博主「TravelerTD」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/SGamble/article/details/101376652
3.armeabi和armeabi-v7a(引自:https://www.cnblogs.com/weiqiangwaideshijie/p/9412211.html)
①、手机cpu架构。
讲到armeabi就不得不讲手机cpu了。电脑有电脑的cpu,手机也有手机的cpu。cpu有厂商属性,也有架构属性,架构的话自己简单地理解就是它的内部模块的组成结构。
其中arm架构的手机cpu占市场的大部分,这也是今天的重点。但arm架构的发展历史悠久,也有很多不同的版本。
②、前面讲了cpu架构,为下面的讲述做了一个技术背景的铺垫。
我们在开发Android项目的时候,比如使用高德地图导航或者3d地图的时候就会使用到.so库文件,它们保存在armeabi和armeabi-v7a或arm64-v8a等目录下,这有什么作用呢?
其实这是给app运行时读取的几个目录,但会根据手机cpu架构类型只从其中一个文件夹读取,有点类似values和values-21的作用,但是与它们又有点不同。
后者的规则是:如果手机是21以上的会首先在values-21文件里面查找样式等,如果查找不到才去values文件找;如果手机是21以下的就直接在values文件下找。
前者的规则是:根据cpu架构类型去app的libs里面匹配到对应的目录比如armeabi或者armeabi-v7a,然后就加载这个目录下的.so库;
如果在匹配到的目录下没有对应的库也不会去别的目录下加载;
但是armeabi目录可以匹配所有的arm架构的cpu,意思是指所有的arm架构的cpu的安卓手机如果没有找到最优的对应的目录,则会去匹配armeabi目录。
我的推测是arm架构的cpu是向下兼容的,即保留之前版本的功能,而armeabi目录是匹配低版本armv5的,所以高版本的arm架构的cpu可以读取armeabi目录下的.so库文件;查过资料会发现低版本的arm架构cpu支持软浮点运算而高版本的支持硬件浮点运算,这是他们的区别之一。
待续……
以上是关于unity与android交互相关资料整理(U2A)的主要内容,如果未能解决你的问题,请参考以下文章