写给VR手游开发小白的教程:(五)Cardboard插件与Android之间的通信交互

上篇已经把BaseVRDevice这个类解析了一下,紧接着,摆在我们眼前的问题是既然已经完成了VR设备的基类,那后续的子类必然会对基类做一个相应的扩展,以实现Android和ios设备所独有的功能。事实上AndroidBaseVRDevice这个类就完成了这些事情,学过Android的人都知道一个app的运行最基本的就是Layout和Activity,一个控制前端一个控制后台,而我们本节所要介绍的这个类,就是在BaseVRDevice的基础上,增加了Android所特有的Java对象的创建和Activity的管理,这搭建了一个桥梁,允许我们将Unity和Android两个不同的平台进行通信和交互。


AndroidBaseVRDevice.cs的代码如下,大家可以参照着看看

#if UNITY_ANDROID

using UnityEngine;
using System.Collections.Generic;

public abstract class AndroidBaseVRDevice : BaseVRDevice {
  protected AndroidJavaObject cardboardActivity;

  public override bool SupportsNativeDistortionCorrection(List
  
    diagnostics) {
    bool support = base.SupportsNativeDistortionCorrection(diagnostics);
    if (cardboardActivity == null) {
      diagnostics.Add("Cannot access Activity");
    }
    return support;
  }

  public override void Destroy() {
    if (cardboardActivity != null) {
      cardboardActivity.Dispose();
      cardboardActivity = null;
    }
    base.Destroy();
  }

  protected virtual void ConnectToActivity() {
    try {
      using (AndroidJavaClass player = new AndroidJavaClass("com.unity3d.player.UnityPlayer")) {
        cardboardActivity = player.GetStatic
   
    ("currentActivity");
      }
    } catch (AndroidJavaException e) {
      cardboardActivity = null;
      Debug.LogError("Exception while connecting to the Activity: " + e);
    }
  }

  protected virtual bool CallActivityMethod(string name, params object[] args) {
    return CallObjectMethod(cardboardActivity, name, args);
  }

  protected virtual bool CallActivityMethod
    
     (ref T result, string name, params object[] args) {
    return CallObjectMethod(ref result, cardboardActivity, name, args);
  }

  protected AndroidJavaObject Create(string className, params object[] args) {
    try {
      return new AndroidJavaObject(className, args);
    } catch (AndroidJavaException e) {
      Debug.LogError("Exception creating object " + className + ": " + e);
      return null;
    }
  }

  protected static bool CallObjectMethod(AndroidJavaObject jo, string name, params object[] args) {
    if (jo == null) {
      Debug.LogError("Object is null when calling method " + name);
      return false;
    }
    try {
      jo.Call(name, args);
      return true;
    } catch (AndroidJavaException e) {
      Debug.LogError("Exception calling method " + name + ": " + e);
      return false;
    }
  }

  protected static bool CallObjectMethod
     
      (ref T result, AndroidJavaObject jo, string name,
                                            params object[] args) {
    if (jo == null) {
      Debug.LogError("Object is null when calling method " + name);
      return false;
    }
    try {
      result = jo.Call
      
       (name, args);
      return true;
    } catch (AndroidJavaException e) {
      Debug.LogError("Exception calling method " + name + ": " + e);
      return false;
    }
  }
}

#endif

      
     
    
   
  




/**************************************************************************************************************************************/

代码的第一句就给我们摆了难题,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新的对象就不再详述了,无非就是用泛型实现对象内调用其他对象方法,相信大家都能看懂

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值