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)

上一篇:13.vue-axios


下一篇:abp Application层获取请求的Header内容