Unity3d Android SDK接入解析(一)Unity3d 與 Android之間的互相呼叫

你的財神爺發表於2019-01-10

一、前言

論學習心態:

每當進入一個新的工作環境,處於一種新的領域時,人總是會變得急功近利,特別是當任務緊急時,人總是會想著不斷的從網上搜尋答案,不斷的去尋問他人,十足的拿來主義,竟沒有靜下來自己思考與嘗試過,回頭看來,其實很多東西並沒有當初認為的那麼複雜,只是少了自己的一些總結和深思。

論問題本身:

關於Unity和Android的互相呼叫,網上的教程太多了,大同小異,抄來抄去。這次我就嘗試著慢慢來,講講我的理解(簡單的我會一筆帶過,網上可以輕鬆找到答案,就不贅述了),希望大家看的時候並不是秉承著“拿來主義”,而是靜下心來,一起知其然,知其所以然,如果有錯誤和不足,請在我的部落格留言。

部落格地址:http://blog.csdn.net/yang8456211

內容分為三部分,分三篇寫完

前篇:Unity3d 與 Android之間的互相呼叫
中篇:Unity3d Android SDK的兩種接入方式 
http://blog.csdn.net/yang8456211/article/details/51356193
後篇:Unity3d 接入Android Libriary的理解與實現 
http://blog.csdn.net/yang8456211/article/details/51435465
二、前篇:Unity3d 與 Android之間的互相呼叫

總體來說Unity3d與Android之間的互相呼叫,是通過Unity3d提供的classes.jar來實現的(具體實現在中篇說)。
1
那麼下面假設已經按照要求建立好了Android的工程,並配置好了classes.jar,開始寫呼叫:

2.1 Unity3d呼叫Android

最常見的寫法:

1)首先在Android層寫好介面u3dCall

這個方法只列印成功的提示:

    public void u3dCall() {
        Log.i(U2ATAG, "u3dCall Android Successful");
    }

2)在Unity3d cs指令碼中呼叫Android

通過反射機制拿取物件並呼叫Android的介面u3dCall,這裡我們畫了一個Button,點選Button呼叫u3dCall介面:

        if(GUI.Button(new Rect(100,200,750,200),"U3dToAnd"))  
        {  
            AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer");
            AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity");
            jo.Call("u3dCall");  
        } 
通過列印看到,我們成功的從Unity3d呼叫到了Android的程式碼。

(沒有充滿疑問?)

這個com.unity3d.player.UnityPlayer是什麼東西?currentActivity又是什麼?
Call是個方法吧,那引數和返回值呢?是呼叫的什麼型別的方法?
只有通過實踐慢慢探索,才能知道真相

3)Unity3d呼叫Android介面的api

我們先說第二個問題,Call只是Unity3d呼叫Android所設定的api之一,還有一些常用的:
1
方法名    方法型別    說明
Call    例項    呼叫例項方法
Get    例項    獲取例項變數(非靜態)
Set    例項    設定例項變數(非靜態)
CallStatic    靜態    呼叫靜態方法
GetStatic    靜態    獲取靜態變數
SetStatic    靜態    設定靜態變數
通過這些方法,我們能夠方便的呼叫靜態方法、例項方法,還有獲取變數的值。

如果Android的方法是需要傳入引數的,則如下:

Android:

    public void u3dCallWithArgs(String str, int i) {
        Log.i(U2ATAG, "u3dCall Android Str|int is " + str + "|" + i);
    }
U3d:

            jo.Call("u3dCallWithArgs","Atany",100);  
成功呼叫: 
如果需要返回值: 
Android:

    public String u3dCallReturn() {
        return "This is the return Value of Android";
    }
1
2
3
U3d:

            string msg = jo.Call<string>("u3dCallReturn");
            print ("U3d msg is "+msg);

成功呼叫: 
其他的方法類似,可以猜到jo = jc.GetStatic(“currentActivity”);的意思,就是通過GetStatic獲取了靜態變數currentActivity的值,它的型別是AndroidJavaObject(Unity3d的JavaObject的基本型別)。

4) 那UnityPlayer是什麼?

通過反編譯Unity3d生成的apk發現,UnityPlayer是FrameLayout的一個子類,而currentActivity則是UnityPlayer類中的靜態物件。

致此,就弄明白了,這個UnityPlayer原來就是一個Unity3d生成的一個類,我們通過new(”完整類名”)的方式獲取到了這個類,然後通過getStatic獲取到了currentActivity這個靜態物件。

(那麼問題又來了,currentActivity這個類是怎麼找到我寫的方法的呢?)

5)MyActivity與currentActivity

我刻意的避開了中篇要講的內容,但如果一點不提,感覺問題始終不能講明白,所以這裡就稍微說明一下。 
在寫Android工程的時候,網上一般要求我們建立了一個新的MyActivity繼承UnityPlayerActivity,並在AndroidManifest中把MyActivity設定為啟動的Activity,然後使用currentActivity這個jo來呼叫方法。

為什麼要這麼做呢?通過觀察發現,他們的繼承關係是這樣的:

MyActivity <-- UnityPlayerActivity <--UnityPlayerNativeActivity <-- NativeActivity<-- Activity
1
(然而裡面並沒有com.unity3d.player.UnityPlayer這個class?)

繼續查詢原始碼發現,在 UnityPlayerNativeActivity 這個類中,宣告瞭一個UnityPlayer物件

在oncreate方法裡面初始化了這個物件,把UnityPlayerNativeActivity上下文作為引數傳了進去

然後在UnityPlayer類的構造方法中,把當前的上下文賦值給了currentActivity 


所以,我們使用的currentActivity 就是當前activity的上下文。寫到這裡,我還有一個疑問,就是currentActivity是拿到的UnityPlayerNativeActivity的上下文,但是是怎麼呼叫到的Myactivity裡面的方法的呢?希望知道的人告訴我。

2.2 Android呼叫Unity

如果想要非同步的傳送訊息回Unity那麼應該怎麼處理呢?就是使用Unity3d的UnitySendMessage傳送回去

Android:

    public void andToU3d() {
        UnityPlayer.UnitySendMessage(OBJNAME, "andToU3dCallback", "exit");
    }

U3d:

    void andToU3dCallback(string str){
        print ("andToU3dCallback string is "+str);
    }
--------------------- 
 

相關文章