概述鏈接:https://www.cnblogs.com/wang-jin-fu/p/10975660.html
之前概述有說過SDK的大概功能如下:
1.賬號類:創建、登錄、切換
2.充值
3.外部分享如微信、朋友圈、FB等
4.打開外部鏈接,如論壇、社區、反饋等
5.功能類:語音、頭像、埋點
這些功能都是sdk提供的,而我們要做的就是調用sdk的接口(ios的OC接口,android的java接口)
一、android和c#交互
1.c#調用android方法,如下,使用 AndroidJavaClass獲取AndroidJavaObject對象,在通過AndroidJavaObject調用java方法。最常用的是AndroidJavaObject的Call方法,unity文檔:http://docs.unity3d.com/ScriptReference/AndroidJavaObject.html
這個Call是支持多參數的,第一個參數必須是方法名,第二個開始則是各種參數。如果有返回值則需要使用泛型版本Call<Type>。
using UnityEngine; /// <summary> /// Android幫助庫 /// 提供unity對android端的調用,屬性的get和set麻煩封裝成方法 /// </summary> public class AndroidHelper { const string AndroidMainActivity = "com.unity3d.player.UnityPlayer";
static AndroidJavaObject ms_MainActivity; public static AndroidJavaObject MainActivity { get { if (ms_MainActivity == null) { AndroidJavaClass jc = new AndroidJavaClass (AndroidMainActivity); if (jc != null) { ms_MainActivity = jc.GetStatic<AndroidJavaObject> ("currentActivity"); } } return ms_MainActivity; } } #region MainActivity的非靜態方法 public static void Call(string method) { MainActivity.Call(method); } public static void Call(string method, object[] args) { MainActivity.Call(method, args); } public static void Call(string method, bool val) { MainActivity.Call(method, new object[] { val }); } public static void Call(string method, string val) { MainActivity.Call(method, new object[] { val }); } public static string CallWithReturn(string method) { string result = ""; AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); result = jo.Call<string>(method); return result; } #endregion #region MainActivity的靜態方法 public static void CallStatic(string method) { MainActivity.CallStatic(method); } public static void CallStatic(string method, string val) { MainActivity.CallStatic(method, new object[] { val }); } public static string CallStaticWithReturn(string val) { string result = ""; AndroidJavaClass jc = new AndroidJavaClass("com.unity3d.player.UnityPlayer"); AndroidJavaObject jo = jc.GetStatic<AndroidJavaObject>("currentActivity"); result = jo.CallStatic<string>(val); return result; } #endregion }
2.Java回調unity,public static void UnitySendMessage(String var0, String var1, String var2) ,第一個參數為unity中的一個gameobject名稱,第二個參數為這個gameobject身上捆綁的腳本中的一個方法,而第三參數是這個對應方法上的參數
public static final String UNITY_HANDLER = "SDKMsgHandler"; ** * 向Unity傳送 * @param arg1 函數名 * @param arg2 參數 */ public static void UnitySendMessage(String arg1, String arg2) { UnityPlayer.UnitySendMessage(UNITY_HANDLER, arg1, arg2); }
二、ios和c#的交互,可以參照官網:https://docs.unity3d.com/Manual/PluginsForIOS.html,你需要把你的oc代碼放在Plugins/iOS文件夾下才能正確調用到OC的代碼
c#調用ios:c#端
[DllImport("__Internal")] private static extern string U3dGetAvailableDiskSize(); /// <summary> /// 獲取磁盤空間 /// </summary> public long GetAvailableDiskSize() { string size = U3dGetAvailableDiskSize(); return long.Parse(size); }
OC端
char* _MakeStringCopy( const char* string) { if (NULL == string) { return NULL; } char* res = (char*)malloc(strlen(string)+1); strcpy(res, string); return res; } const char* U3dGetAvailableDiskSize() { struct statfs buf; long long freespace = -1; if(statfs("/var", &buf) >= 0) { freespace = (long long)(buf.f_bsize * buf.f_bfree); } NSString *_msg = [NSString stringWithFormat:@"%lld", freespace]; return _MakeStringCopy([_msg UTF8String]); }
2.OC回調unity:
UnitySendMessage("GameObjectName1", "MethodName1", "Message to send");
參數1:gameobject名字;參數2:回調函數的名字;參數3:參數。同android開發中java回調c#一樣,三個參數都是字符串類型!
三、好了。我們知道unity跟ios\android怎么交互了,可以開始設計我們的接口了,首先在c#端,我們需要區分三種平台,ios\android\unity editor三種平台,我們不可能像下面這么寫,幾十個接口如果都這么寫,會原地爆炸的,所以我們需要用的接口來規范我們的代碼
if(platform == ios) { //xxxx }else if(paltform == android) { //xxxx }else if(platform == editor){ //xxxx }
1.首先我們需要有一個接口類:
public interface SDKInterface { /** 登錄 **/ void Login(); /** 打開SDK用戶中心界 **/ void ShowUserCenter(); }
2.我們需要有每個平台的具體實現類(其實就是ios調用OC,android調用Java,editor平台啥也不做),如下所示,U3dLogin\ShowUserCenter是Ios、android兩端的實現代碼,這里就不上了
#if UNITY_ANDROID public class AndroidSDK : SDKInterface { /// <summary> /// 登錄 /// </summary> public void Login() { Call("U3dLogin"); } /// <summary> /// 打開SDK用戶中心界 /// </summary> public void ShowUserCenter() { Call("U3dShowUserCenter"); } } #endif
#if UNITY_IOS public class IOSSDK : SDKInterface { [DllImport("__Internal")] private static extern void U3dLogin(); [DllImport("__Internal")] private static extern void U3dShowUserCenter(); /// <summary> /// 登錄 /// </summary> public void Login() { U3dLogin(); } /// <summary> /// 打開SDK用戶中心界 /// </summary> public void ShowUserCenter() { U3dShowUserCenter(); } } #endif
public class EmptySDK : SDKInterface { public void Login() { } public void ShowUserCenter() { } }
3.一個接受兩端回調消息的類,ios\android共用一個就好了,該類會在管理類里面初始化
public class SDKMsgHandler : MonoBehaviour { /// <summary> /// 登錄回調 /// </summary> /// <param name="msg">msg</param> public void LoginNotification(string msg) { Debug.Log("登錄回調:" + msg); } }
4.我們需要一個管理類,來確定具體是調用哪一個接口
public class SDKModule : ModuleBase { public SDKModule () { #if UNITY_EDITOR || GUIDE _sdk = new EmptySDK (); #elif UNITY_IOS _sdk = new IOSSDK(); #elif UNITY_ANDROID _sdk = new AndroidSDK(); #else _sdk = new EmptySDK(); #endif GameObject go = new GameObject ("SDKMsgHandler"); GameObject.DontDestroyOnLoad (go); go.AddComponent<SDKMsgHandler> (); } /// <summary> /// 登錄 /// </summary> public void Login () { Debug.Log("Login c"); _sdk.Login (); } /// <summary> /// 打開SDK用戶中心界 /// </summary> public void ShowUserCenter () { Debug.Log("ShowUserCenter c"); _sdk.ShowUserCenter (); } }
至此,c#端就完成了,然后后兩端的代碼
四、android端:android端渠道眾多,很有必要跟c#端一樣,每個渠道的接口都實現一個自己的實現類,再用具體的SFMainActivity去管理
android端接sdk有兩種方式,兩種方式的區別可參考:https://blog.csdn.net/yang8456211/article/details/51356193,個人傾向於使用第二種方式,因為很多系統功能在unity不好實現,但在android端卻很好實現,如推送、谷歌支付等
1.將sdk的代碼打成jar\aar的包導入到unity.
android studio(as)導出aar可參考:https://www.jianshu.com/p/b059e84e85d1
android studio(as)導出jar可參考:https://www.jianshu.com/p/8256c0da444a
2.將unity導出到android studio,在使用as打apk
(1)將unity導出的項目,刪除其中的src/main文件夾下的assets\jinLibs\res三個文件夾,拷貝該工程作為我們的as工程
(2)新建一個java類SFMainActivity,該類繼承自UnityPlayerActivity,該類的職責類似於前面的SDKModule,負責sdk的初始化(例如語言、版本等需要通知渠道方的)和unity接口的封裝,前面AndroidSDK即調用的是這個類的方法
(3)新建一個sdk的接口類,該類和SDKInterface接口一致,新建不同渠道的實現類,實現類繼承自接口類,完成具體的sdk功能
(4)打包的時候只需要把第一步刪除的內容拷貝到我們的備份as工程就好了
五、ios端,ios端相對android端沒有這么多渠道,相對會簡單一些,我們只需要把OC的代碼放在Plugins/iOS文件夾就好了(需要注意OC語法的參數類型轉換)