1. 程式人生 > >教你高速高效接入SDK——Unity統一接入渠道SDK(Android篇)

教你高速高效接入SDK——Unity統一接入渠道SDK(Android篇)

方法名 nco 簡單 sdk ui主線程 unit onpause 提示 schema

U8SDK的設計之初,就是為了可以支持各種遊戲引擎開發的遊戲,而不不過Android的原生平臺。眼下一大半的手遊,都是採用Unity3D和Cocos2dx開發,那麽這裏,我們就先來一步步給大家演示,用Unity開發的遊戲,怎樣通過U8SDK來高速地完畢多家渠道SDK的接入。

Unity研發的手遊,僅僅須要調用U8SDK抽象層就可以完畢多家渠道SDK的接入。而不須要在Unity中耦合各個渠道SDK,保證遊戲層邏輯層的簡單,以及SDK部分的絕對重用。 以下,我們看看,在Unity中調用U8SDK主要須要完畢的工作: 1、建立一個Androidproject,作為U8SDK和Unity平臺通信的中間協調project 2、定義一致的通信數據類型,我們這裏採用JSON格式 3、在Unity中,通過C#完畢一套統一的SDK調用接口。給邏輯層調用。同一時候多個平臺(Android,IOS,PC等)的接口全然同樣。

這一篇。我們就先來完畢第一步和第二步。 1,新建一個Androidproject,將IsLibrary設置為true。將該project作為庫project,這樣當你編譯的時候,會在bin文件夾下產生一個jar包。而不是一個apk 2,設置依賴project為U8SDK2抽象層project,同一時候將Unity3D提供的Android的jar包,拷貝到該project的libs文件夾下 3、然後建立兩個類,一個為U8UnityContext ,這個類繼承UnityPlayerActivity 。也是遊戲的啟動Activity。

4、還有一個是IU8SDKListener 的實現類,主要實現一些SDK的回調方法 我們先來看看這兩個類的實現。之後再來解釋一些關鍵的東西:

public class U8UnityContext extends UnityPlayerActivity{
	
	public final static String CALLBACK_GAMEOBJECT_NAME = "(u8sdk_callback)";	//unity中接收回調通知的GameObject的名稱
	public final static String CALLBACK_INIT = "OnInitSuc";						//SDK初始化成功的回調方法名稱和Unity中一致
	public final static String CALLBACK_LOGIN = "OnLoginSuc";					//SDK登錄成功的回調方法名稱和Unity中一致
	public final static String CALLBACK_SWITCH_LOGIN = "OnSwitchLogin";			//SDK切換帳號的回調方法名稱和Unity中一致
	public final static String CALLBACK_LOGOUT = "OnLogout";					//SDK登出的回調方法名稱和Unity中一致
	public final static String CALLBACK_PAY = "OnPaySuc";						//SDK支付成功回調方法名稱和Unity中一致
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		initSDK();
	}
	
	//U8SDK 初始化
	public void initSDK(){
		U8SDK.getInstance().setSDKListener(new UnityU8SDKListener(this));
		U8SDK.getInstance().init(this);
		U8SDK.getInstance().onCreate();
	}
	
	//登錄接口
	public void login(){
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
			
				U8User.getInstance().login();
			}
		});
	}
	
	//自己定義登錄接口
	public void loginCustom(final String customData){
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
			
				U8User.getInstance().login(customData);
			}
		});
	}
	
	//切換帳號接口
	public void switchLogin(){
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
			
				U8User.getInstance().switchLogin();
			}
		});		
	}
	
	//顯示用戶中心接口
	public void showAccountCenter(){
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
			
				U8User.getInstance().showAccountCenter();
			}
		});			
	}
	
	//登出
	public void logout(){
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
			
				U8User.getInstance().logout();
			}
		});			
	}	
	
	//提交擴展數據
	public void submitExtraData(String data){
		final UserExtraData extraData = parseGameData(data);
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
				
				U8User.getInstance().submitExtraData(extraData);
			}
		});	
	}
	
	//SDK退出接口
	public void exit(){
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
			
				U8User.getInstance().exit();
			}
		});	
	}	
	
	//支付接口
	public void pay(String data){
		final PayParams params = parsePayParams(data);
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
			
				U8Pay.getInstance().pay(params);
			}
		});			
	}
	
	//SDK是否支持退出確認功能
	public boolean isSupportExit(){
		
		return U8User.getInstance().isSupport("exit");
	}
	
	//SDK是否支持用戶中心
	public boolean isSupportAccountCenter(){
		
		return U8User.getInstance().isSupport("showAccountCenter");
	}
	
	
	//SDK是否支持登出
	public boolean isSupportLogout(){
		
		return U8User.getInstance().isSupport("logout");
	}
	
	//向Unity中發送消息
	public void sendCallback(String name, String jsonParams){
		if(jsonParams == null){
			jsonParams = "";
		}
		UnityPlayer.UnitySendMessage(CALLBACK_GAMEOBJECT_NAME, name, jsonParams);
	}
	
	private UserExtraData parseGameData(String str){
		UserExtraData data = new UserExtraData();
		try {
			JSONObject json = new JSONObject(str);
			data.setDataType(json.getInt("dataType"));
			data.setRoleID(json.getString("roleID"));
			data.setRoleName(json.getString("roleName"));
			data.setRoleLevel(json.getString("roleLevel"));
			data.setServerID(json.getInt("serverID"));
			data.setServerName(json.getString("serverName"));
			data.setMoneyNum(json.getInt("moneyNum"));
		} catch (JSONException e) {

			e.printStackTrace();
		}
		return data;
	}
	
	private PayParams parsePayParams(String str){
		PayParams params = new PayParams();
		
		try{
			JSONObject json = new JSONObject(str);	
			params.setProductId(json.getString("productId"));
			params.setProductName(json.getString("productName"));
			params.setProductDesc(json.getString("productDesc"));
			params.setPrice(json.getInt("price"));
			params.setRatio(0);//該字段廢棄不用
			params.setBuyNum(json.getInt("buyNum"));
			params.setCoinNum(json.getInt("coinNum"));
			params.setServerId(json.getString("serverId"));
			params.setServerName(json.getString("serverName"));
			params.setRoleId(json.getString("roleId"));
			params.setRoleName(json.getString("roleName"));
			params.setRoleLevel(json.getInt("roleLevel"));
			params.setPayNotifyUrl("");//該字段廢棄不用
			params.setVip(json.getString("vip"));
			params.setOrderID(json.getString("orderID"));
			params.setExtension(json.getString("extension"));
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		return params;
	}
	
	public void onActivityResult(int requestCode, int resultCode, Intent data){
		U8SDK.getInstance().onActivityResult(requestCode, resultCode, data);
		super.onActivityResult(requestCode, resultCode, data);
	}
	
	public void onStart(){
		U8SDK.getInstance().onStart();
		super.onStart();
	}
	
	public void onPause(){
		U8SDK.getInstance().onPause();
		super.onPause();
	}
	public void onResume(){
		U8SDK.getInstance().onResume();
		super.onResume();
	}
	public void onNewIntent(Intent newIntent){
		U8SDK.getInstance().onNewIntent(newIntent);
		super.onNewIntent(newIntent);
	}
	public void onStop(){
		U8SDK.getInstance().onStop();
		super.onStop();
	}
	public void onDestroy(){
		U8SDK.getInstance().onDestroy();
		super.onDestroy();
	}
	public void onRestart(){
		U8SDK.getInstance().onRestart();
		super.onRestart();
	}
		
}

public class UnityU8SDKListener implements IU8SDKListener{

	private U8UnityContext context;
	
	private boolean isSwitchAccount = false;		//當前是否為切換帳號
	
	public UnityU8SDKListener(U8UnityContext context){
		this.context = context;
	}
	
	@Override
	public void onResult(final int code, String msg) {
		// TODO Auto-generated method stub
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
				switch(code){
				case U8Code.CODE_INIT_SUCCESS:
					context.sendCallback(U8UnityContext.CALLBACK_INIT, null);
					break;
				case U8Code.CODE_INIT_FAIL:
					Toast.makeText(context, "SDK初始化失敗", Toast.LENGTH_SHORT).show();
					break;
				case U8Code.CODE_LOGIN_FAIL:
					//這裏不須要提示。一般SDK有提示
					//Toast.makeText(context, "SDK登錄失敗", Toast.LENGTH_SHORT).show();
					break;
				case U8Code.CODE_PAY_FAIL:
					Toast.makeText(context, "支付失敗", Toast.LENGTH_SHORT).show();
					break;
				case U8Code.CODE_PAY_SUCCESS:
					Toast.makeText(context, "支付成功,到賬時間可能稍有延遲", Toast.LENGTH_SHORT).show();
					break;
				}
			}
		});
	}

	//此接口已經廢棄
	@Override
	public void onInitResult(InitResult result) {
		// TODO Auto-generated method stub
		// 此接口已經廢棄
	}

	//SDK登錄成功的回調
	@Override
	public void onLoginResult(String data) {
		Log.d("U8SDK", "SDK 登錄成功,不用做處理,在onAuthResult中處理登錄成功, 參數例如以下:");
		Log.d("U8SDK", data);
		this.isSwitchAccount = false;
		tip("SDK登錄成功");
	}

	//切換帳號。須要回到登錄界面,並彈出SDK登錄界面
	@Override
	public void onSwitchAccount() {
		context.sendCallback(U8UnityContext.CALLBACK_SWITCH_LOGIN, null);	
		
	}

	//切換帳號,並登錄成功。到這裏和Login的回調onLoginResult一樣
	@Override
	public void onSwitchAccount(String data) {
		Log.d("U8SDK", "SDK 切換帳號並登錄成功,不用做處理。在onAuthResult中處理登錄成功, 參數例如以下:");
		Log.d("U8SDK", data);
		this.isSwitchAccount = true;		
		
		tip("切換帳號成功");		
	}

	//登出,須要回到登錄界面,並彈出SDK登錄界面
	@Override
	public void onLogout() {
		context.sendCallback(U8UnityContext.CALLBACK_LOGOUT, null);
	}

	//SDK登錄成功之後。去U8Server進行登錄認證
	@Override
	public void onAuthResult(UToken authResult) {
		
		if(!authResult.isSuc()){
			tip("SDK登錄認證失敗,確認U8Server是否配置");
			return;
		}
		
		JSONObject json = new JSONObject();
		try{
			
			json.put("isSuc", authResult.isSuc());
			json.put("isSwitchAccount", isSwitchAccount);
			
			if(authResult.isSuc()){
				json.put("userID", authResult.getUserID());
				json.put("sdkUserID", authResult.getSdkUserID());
				json.put("username", authResult.getUsername());
				json.put("sdkUsername", authResult.getSdkUsername());
				json.put("token", authResult.getToken());
			}
			
		}catch(Exception e){
			e.printStackTrace();
		}
		
		context.sendCallback(U8UnityContext.CALLBACK_LOGIN, json.toString());
	}
	
	//對於手機網遊,不須要實現這個接口,由於網遊支付是通過server回調通知加虛擬幣的。
	//這個接口主要用於單機遊戲。作為單機的支付結果回調接口
	@Override
	public void onPayResult(PayResult result) {
		//TODO
	}


	private void tip(final String tip){
		U8SDK.getInstance().runOnMainThread(new Runnable() {
			
			@Override
			public void run() {
				Toast.makeText(context, tip, Toast.LENGTH_SHORT).show();
			}
		});	
	}
}

在U8UnityContext 中,我們定義了一系列的接口。這些接口就是給Unity中調用的。

比方Login,switchLogin,logout等。而這些方法本身不過對U8SDK抽象層提供的方法進行了一個簡單的包裹。通過,U8SDK.getInstance().runOnMainThread()來讓全部的接口都在UI主線程中完畢。

關於U8SDK的初始化,有兩部分。第一部分是U8SDK本身的初始化,包含參數的讀取和解析等,這個須要將AndroidManifest.xml中application接口的android:name設置為”com.u8.sdk.U8Application”。註意,這裏一定要設置,否則U8SDK無法初始化。假設,遊戲有自己的某些業務須要在Application中完畢,能夠通過實現U8SDK提供的IApplicationListener接口來完畢。 第二部分須要在Activity的onCreate中完畢(依據遊戲不同,也能夠在Unity中合適的地方調用初始化接口),包含,設置U8SDK的回調監聽,初始化載入插件,以及調用onCreate回調。表現為下面三步: U8SDK. getInstance().setSDKListener (new UnityU8SDKListener(this)); U8SDK. getInstance().init(this); U8SDK. getInstance().onCreate(); UnityU8SDKListener 是U8SDK的回調簡體接口的實現類。全部SDK相關的回調都是通過這些接口完畢的。

onLoginResult: SDK登錄成功的回調 onSwitchAccount: SDK中切換帳號的回調 onLogout: SDK登出的回調 onAuthResult: U8Server登錄驗證的回調 onResult: 全部SDK操作成功或者失敗的狀態回調 當我們收到部分回調的時候,我們須要通知到Unity中,包含之前。我們寫的那些接口,比方Pay和submitExtraData都是含有參數的。 這裏就來解決Unity和Android中通信的數據結構問題。盡管Unity和Android通信也能夠使用復雜的結構,可是我還是推薦採用簡單統一的數據協議比較好。這裏我們選擇JSON。簡單高效。僅僅要保證。兩邊數據的key一致就能夠了。 Unity調用Android的接口,比方Pay和submitExtraData都通過一個JSON字符串傳遞過來,然後這邊解析一下。

對於Android中須要通知Unity中的也是一樣,使用JSON格式的字符串,然後通過 UnityPlayer.UnitySendMessage(gameObject, methodName, jsonParams)接口來完畢通信。 好了,完畢這個,Android中的部分,就完畢了。再提醒一次,不要忘記配置AndroidManifest.xml哦,這裏附上AndroidManifest.xml文件:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.u8.sdk"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="21" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" 
        android:name="com.u8.sdk.U8Application">
        
        <activity
            android:name="com.u8.sdk.U8UnityContext"
            android:label="@string/app_name" 
            android:screenOrientation="landscape"
            android:launchMode="singleTask"
            android:configChanges="orientation|keyboardHidden|screenSize">
            
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>            
            
        </activity>        
        
    </application>

</manifest>

接下來。我們就須要在Unity中來完畢接下來的工作,能夠看訪問這裏查看:Unity手遊接入渠道SDK(Unity篇)


教你高速高效接入SDK——Unity統一接入渠道SDK(Android篇)