上篇已经把BaseVRDevice这个类解析了一下,紧接着,摆在我们眼前的问题是既然已经完成了VR设备的基类,那后续的子类必然会对基类做一个相应的扩展,以实现Android和ios设备所独有的功能。事实上AndroidBaseVRDevice这个类就完成了这些事情,学过Android的人都知道一个app的运行最基本的就是Layout和Activity,一个控制前端一个控制后台,而我们本节所要介绍的这个类,就是在BaseVRDevice的基础上,增加了Android所特有的Java对象的创建和Activity的管理,这搭建了一个桥梁,允许我们将Unity和Android两个不同的平台进行通信和交互。
AndroidBaseVRDevice.cs的代码如下,大家可以参照着看看
/**************************************************************************************************************************************/
代码的第一句就给我们摆了难题,AndroidJavaObject这个类看着像是Android的,但事实上它是Unity库里的一个类,见圣典:
http://www.ceeger.com/Script/AndroidJavaObject/AndroidJavaObject.html
发现这个类下,有一系列函数和一个构造方法static function AndroidJavaObject (className : string, params args : object[])
这个构造方法很有趣,它有两个参数分别是1、指定的Java类名2、传递的参数
为什么说他有趣?
大家可以看一个例子
//创建一个java.lang.String对象,持有该字符串"some string"
function Start() {
var jo = new AndroidJavaObject("java.lang.String", "some string");
}
这是摘自圣典的一个例子,我们通过构造函数将AndroidJavaObject实例化了以后,生成的居然不是AndroidJavaObject的实例而是其字符串参数java.lang.String对象的一个实例。这很神奇,因为我们通常所能认识到的是构造函数构造的一定是类本身,那为什么这里不是?
事实上,我们构造出来的仍然是本身,只不过“看起来”不一样而已。什么是“看起来”不一样呢?
从这里需要引申到Java中所有对象的祖先类,Object类,这里的AndroidJavaObject就是Object类的一个泛型,关于Object类的概念,给一个链接这里不再详述
http://www.cnblogs.com/mengdd/archive/2013/01/03/2842809.html
好了,现在Object作为泛型类,把AndroidJavaObject这个类作为参数来确定具体实例化哪个对象,而实例化哪个对象的问题,就由实例化的AndroidJavaObject类来解答了,所以说,不管是最终实例化的java.lang.String类,还是我们觉得应该实例化的AndroidJavaObject类,都是产自于Object类,它们事实上来源是相同的,而我们只是通过泛型这种手段来将Object对象做了个“变形”。
理解了这一步,我们就知道AndroidJavaObject类在Unity中存在的意义了,它就像一座桥梁,将Java对象与远方的Unity中的对象联系起来。
/**************************************************************************************************************************************/
AndroidJavaClass player = new AndroidJavaClass("com.unity3d.player.UnityPlayer"
//同理AndroidJavaClass也是如此,只不过它联系了Java中的类和Unity中的类。需要说明的一点是,Class类没有公共构造方法,我们都知道类是对象的抽象,而Class是对Java中所有类的一个抽象,它保存的是一个Java类的元信息,负责类的类型标识问题而从不负责类的实例化问题。于是,我们知道AndroidJavaClass的实例得到的是指定的类型,而不是实例化的对象。附上圣典的介绍:
http://www.ceeger.com/Script/AndroidJavaClass/AndroidJavaClass.html
/**************************************************************************************************************************************/
解决了这个问题,让我们接着往下
using (AndroidJavaClass player = new AndroidJavaClass("com.unity3d.player.UnityPlayer"))
//这一步相当于在Java中引用了名为com.unity3d.player.UnityPlayer的库,而C#与Java互通上面已经说了,一句话就是C#中创建的Java对象需要用到添加到Java语言中的com.unity3d.player.UnityPlayer库中的操作,听起来有些拗口。
cardboardActivity = player.GetStatic<AndroidJavaObject>("currentActivity");
//然后我们接着调用AndroidJavaClass 类下的GetStatic.<FieldType>方法去获取当前的Activity,这句话如果在上一句之前是无法执行的,因为GetStatic.<FieldType>语句是Unity库里的语句,我们正是通过添加了com.unity3d.player.UnityPlayer库才使得该语句可用。说到这里又有人会问了,我们开头的using UnityEngine不是已经将Unity库导入进来了吗?其实using UnityEngine只是将Unity和C#联系起来,但是我们现在做的,是C#环境中,实现Android和Unity的通信,两者显然不一样。
哈哈,这就是编程的魅力:无限的扩展性+严密的逻辑性!
/**************************************************************************************************************************************/
接下去调用对象方法的一些函数和Creat新的对象就不再详述了,无非就是用泛型实现对象内调用其他对象方法,相信大家都能看懂