標籤:

Unity接入多個SDK的通用介面開發與資源管理(二)

接著上篇,本篇對SDK介面進行封裝。在開始之前,需要先了解下面知識。

(1)unity與android之間的交互

unity通過下面方式調用android中的函數:

方法一:

AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");nAndroidJavaObject _mActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");n_mActivity.Call("函數名");n

方法二:

AndroidJavaClass jc = new AndroidJavaClass ("com.unity3d.player.UnityPlayer");//括弧里可以是任意jar包的包名+類名njc.CallStatic("函數名");n

上面代碼第一種先獲得UnityPlayer類,UnityPlayer類是unity導出Android工程後生成的unity-classes.jar里的類。然後再獲取靜態變數_mActivity,_mActivity 是Activity類型,由此獲得了Android當前的Activity,然後再調用此Activity中的方法。我們可以看一下unity自動生成的classes.jar中的源碼:

第二種是通過包名+類名獲取該類,直接調用類中的靜態方法來實現的。可以是任意自定義的包名和類名。但這種就與Android的生命周期無關了。

我們可以這麼理解Android應用中一個界面是一個Activity,兩個界面的跳轉就是兩個Activity之間的跳轉(類似的iOS是UIController之間的跳轉)。其實我們unity遊戲在Android上也是一個Android應用,所以它也是運行在一個Activity上的,這個Activity叫UnityPlayerActivity,它繼承自Activity,看源碼如下,每個Activity初始化的時候會首先執行onCreate()方法,所以通常把SDK的初始化函數也放在這個函數中。它就會隨著Android的生命周期進行初始化,這是第一種做法,也是最常用的SDK初始化方法。還有一種SDK初始化的方法,就是自己新建一個jar包,在jar包中新建類,在類中寫一些SDK初始化的靜態方法,然後通過方法二在unity中調用這些方法進行初始化。我們這裡採用大多數人使用的方法一,即在onCreate()中初始化。

有了上面的了解,我們開始進行unity的通用介面的開發。我們需要一個SDKManager類來管理所有調用SDK介面的方法,代碼如下,把腳本掛在一個空物體上。

using System.Collections;nusing System.Collections.Generic;nusing UnityEngine;nusing System;nnpublic class SDKManager : MonoBehaviour {nn private static SDKManager _instance = null;n public static SDKManager Instancen {n getn {n return _instance;n }n }nn private void Awake()n {n if (_instance != null)n {n GameObject.Destroy(this.gameObject);n }n _instance = this;nn InitSDKManager();nn DontDestroyOnLoad(this);n }nn private void OnDestroy()n {n if (_instance == this) {n _instance = null;n }n }nn#if UNITY_ANDROID && !UNITY_EDITORn private static string UNITY_CLASS = "com.unity3d.player.UnityPlayer";n private AndroidJavaObject _mActivity;n#endifn public void InitSDKManager()n {n#if UNITY_ANDROID && !UNITY_EDITORn AndroidJavaClass jc = new AndroidJavaClass (UNITY_CLASS);n _mActivity = jc.GetStatic<AndroidJavaObject>("currentActivity");n#endifn }nn //信鴿SDK介面n public void GetPushToken()n {n#if UNITY_ANDROID && !UNITY_EDITORn _pushToken = _mActivity.Call<string>("GetXGPushTokenNew");n#endifn }nn public void SetXGPushTag(string tag)n {n#if UNITY_ANDROID && !UNITY_EDITORn _mActivity.Call("SetXGPushTag",tag);n#endifn }nn public void AddLocalPushNotificationAndroid(string content, DateTime date, bool isRepeatEveryday = false)n {n#if UNITY_ANDROID && !UNITY_EDITORn int isRepeat = 0;n if (isRepeatEveryday == true)n {n isRepeat = 1;n }nn _mActivity.Call("AddLocalNotification","SDK集合",content, date.ToString("yyyyMMdd"), date.ToString("HH"), date.ToString("mm"),isRepeat);n#endifn }nn public void ClearAllLocalNotificationAndroid()n {n#if UNITY_ANDROID && !UNITY_EDITORn _mActivity.Call("ClearAllLocalNotification");n#endifn }nn //buglySDK介面n //啟動c#異常捕獲上報功能n public void buglyCatch()n {n Debug.Log("start Bugly report");n BuglyAgent.EnableExceptionHandler();nn }nn}n

然後新建一個Test腳本掛在攝像機上,調用這些介面:

using System.Collections;nusing System.Collections.Generic;nusing UnityEngine;nusing System;nnpublic class Test : MonoBehaviourn{nn void OnGUI()n {n if (GUILayout.Button("信鴿推送", GUILayout.Width(100.0f), GUILayout.Height(50.0f)))n {n DateTime noticeTime = new DateTime(2017, 11, 24, 21, 30, 30);n SDKManager.Instance.AddLocalPushNotificationAndroid("信鴿給你的推送", noticeTime);n }n if (GUILayout.Button("清除本地推送", GUILayout.Width(100.0f), GUILayout.Height(50.0f)))n {nn SDKManager.Instance.ClearAllLocalNotificationAndroid();n }n if (GUILayout.Button("開啟Bugly異常上報", GUILayout.Width(100.0f), GUILayout.Height(50.0f)))n {n SDKManager.Instance.buglyCatch();n }n }n}n

上面代碼,我們新建一個SDKManaget單例類,把每個SDK的介面封裝成一個函數。像信鴿這種原生的jar包中的方法,我們就用_mActivity.Call()去調用,像bugly這種提供了介面的,我們直接調用提供的介面。通用介面類就介紹到這裡,下面我們來實現_mActivity.Call()中調用的Android工程里的方法。使用Android Studio(2.3.3)新建一個工程。我們的目的是做一個jar包,這個jar包作用有兩點:(1)用來對接unity調用jar包里的方法。(2)對接unity導出的Android工程的生命周期。這是我們為什麼選擇上面第一種接入方法的原因。上面說過unity運行的Activity是UnityPlayerActivity,我們新建一個類MainActivity,繼承com.unity3d.player.UnityPlayerNativeActivity,而UnityPlayerNativeActivity繼承UnityPlayerActivity。然後在AndroidManifest.xml里設置MainActivity為啟動的Activity,所以MainActivity就是當前unity運行的Activity。我們通過_mActivity = jc.GetStatic<AndroidJavaObject>("currentActivity")獲取到的就是MainActivity,然後我們在MainActivity中實現被unity調用的函數。代碼:

public class MainActivity extends com.unity3d.player.UnityPlayerNativeActivity {nn private static boolean _isXGRegisterSuccess = false;n private static String _pushToken = "";nn @Overriden protected void onCreate(Bundle savedInstanceState)n {n if (savedInstanceState == null)n {n savedInstanceState = new Bundle();n }n super.onCreate(savedInstanceState);n Log.d("myGame", "MainActivity onCreate Called");nn InitBugly();n InitXG();n }nnvoid InitBugly()n{n CrashReport.initCrashReport(getApplicationContext(),"aaaaaaaa",false);n}nnvoid InitXG(){n XGPushConfig.enableDebug(this,false);n MsgReceiver testReceiver = new MsgReceiver();n IntentFilter intentFilter = new IntentFilter();n intentFilter.addAction("com.abc.def.receiveintent");n registerReceiver(testReceiver,intentFilter);n XGPushManager.registerPush(this, new XGIOperateCallback() {n @Overriden public void onSuccess(Object o, int i) {n Log.w("XGPush","XGsuccess:"+o);n _isXGRegisterSuccess = true;n _pushToken = o.toString();n }nn @Overriden public void onFail(Object o, int i, String s) {n _isXGRegisterSuccess = false;n Log.w("XGPush","failed:"+i+", msg:"+s);n }n });n}nnpublic void AddLocalNotification(String title, String content, String date, String hour, String min, int isRepeatEveryday)n{n if (_isXGRegisterSuccess)n {n XGLocalMessage msg = new XGLocalMessage();n msg.setTitle(title);n msg.setContent(content);n msg.setDate(date);n msg.setHour(hour);n msg.setMin(min);nn int notifyIconId = getResources().getIdentifier("notify_icon", "drawable", getPackageName());n Log.e("notify icon id",notifyIconId+"");n msg.setSmall_icon(Integer.toString(notifyIconId));nn int _hour = Integer.parseInt(hour);n int _min = Integer.parseInt(min);n msg.setRing(1);nn XGPushManager.addLocalNotification(MainActivity.this,msg);n }n}npublic void ClearAllLocalNotification()n{n Log.w("ClearAllLocalNotice","success");n if (_isXGRegisterSuccess)n {n XGPushManager.clearLocalNotifications(MainActivity.this);n }n}n}n

如果需要在啟動unity的Activity(即MainActivity)前做一些處理,你可以新建一個類SplashActivity繼承Activity,設置SplashActivity為啟動Activity,然後跳轉到MainActivity。就可以在SplashActivity中做一些啟動遊戲前的處理。我們把上述工作做完後,就可以將這些類打包成一個jar包(AS如何打jar包,再說),導入unity導出的Android工程中就可以了。到這裡通用介面的開發就完了。還剩下一項工作就是我們之前從unity中提取出來的SDK資源,我們需要添加到Android工程中,下面就介紹如何進行資源管理,把資源添加到unity導出的Android工程中。

註:

AS打jar包,在build.gradle最後加這些代碼:

task makeJar(type: Jar, dependsOn:[build]){n archiveName = QuicksdkDemo.jar //包名n from(build/intermediates/classes/debug/)n destinationDir = file(build/libs) //導出路徑n exclude(com/taiyouxi/a3k/BuildConfig.class) //不打進包的文件n exclude(com/taiyouxi/a3k/BuildConfig$*.class) //不打進包的文件n exclude(**/R.class) //不打進包的文件n exclude(**/R$*.class) //不打進包的文件n include(com/taiyouxi/a3k/*.class) //需要打進包的文件n include(com/quicksdk/unity/*.class) //需要打進包的文件n include(com/weibo/*.class) //需要打進包的文件n include(com/wxapi/*.class) //需要打進包的文件n}nmakeJar.dependsOn(build)n

然後打開Terminal窗口,輸入gradlew makeJar然後回車:

gradlew makeJarn

打出的包在build>libs文件夾下如圖:


推薦閱讀:

使用頂點投射的方法製作實時陰影
一個簡單的探照燈shader
Unity中的單例模式、回調函數、消息分發的使用區別?

TAG:unity | SDK |