解決游戲接入渠道SDK的繁瑣工作。做到一次接入,通過打包工具生成不同的渠道安裝包。
SDK接入框架
閃屏接入
定義一個Activity繼承TSplashActivity
public class TestSplashActivity extends TSplashActivity {
@Override
protected void onCreate(Bundle savedInstance) {
//設置SDK的橫豎屏
setLandScape(true);
super.onCreate(savedInstance);
}
public int getBackgroundColor() {
//當閃屏PNG圖片無法鋪滿部分機型的屏幕時,設置與閃屏顏色配合的背景色會給用戶更好的體驗
return Color.WHITE;
}
@Override
public void onSplashStop() {
//閃屏結束后,啟動游戲的Activity
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
this.finish();
}
}
AndroidManifest.xml 配置修改
<!-- 設置閃屏為啟動的Activity start -->
<activity
android:name="packname +.TestSplashActivity"<!-- 建議填完整路徑 -->
android:configChanges="orientation|keyboardHidden|screenSize"
android:screenOrientation="portrait" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<!-- 設置閃屏為啟動的Activity end -->
<!-- 配置對應的參數 start-->
<meta-data
android:name="T_C_ID"
android:value="100000" >
</meta-data>
<meta-data
android:name="T_G_ID"
android:value="100000" >
</meta-data>
<meta-data
android:name="T_SUPPLIER_KEY"
android:value="123456" >
</meta-data>
<!-- 配置對應的參數 end-->
接入函數調用
方法 | 描述 |
---|---|
login | TSDK的登陸入口 |
logout | TSDK的登陸注銷 |
pay | TSDK的支付入口 |
quit | 游戲退出調用 |
submitExtendData | 上傳擴展數據 |
onResume | SDK生命周期函數,在activity的onResume 中調用 |
onPause | SDK生命周期函數,在activity的onPause中調用 |
onDestroy | SDK生命周期函數,在activity的onPause中調用 |
TSDK入口類為TSDKUserCenter,主要函數如下:
方法 | 描述 |
---|---|
login | TSDK的登陸入口 |
logout | TSDK的登陸注銷 |
pay | TSDK的支付入口 |
quit | 游戲退出調用 |
submitExtendData | 上傳擴展數據 |
onResume | SDK生命周期函數,在activity的onResume 中調用 |
onPause | SDK生命周期函數,在activity的onPause中調用 |
onDestroy | SDK生命周期函數,在activity的onPause中調用 |
函數介紹
-
登錄介紹
調用TSDK的login登錄,會調起相對應的SDK登錄流程public static void login(Context context, GameParams params, ILoginCallback callback)
用于登錄融合SDK。登錄成功或取消登錄ILoginCallback 均能監聽到。
| 參數 | 描述 |能否為空|
| :------ | :------------------------------------------| -- |
| context | 當前Activity的context | 否 |
| params | 用于傳遞游戲登錄的參數 | 否 |
| callback | 監聽登錄成功或取消登錄的回調 | 否 |
| GameParams 屬性| 描述 |
| :------ | :------------------------------------------ |
| frm | 來源 |
| fdata | 來源描述 |
LoginResponse 包含下列字段
public int code; //登陸狀態CODE_SUCCESS = 1; CODE_FAIL = -1;
public String msg; //code=CODE_FAIL ,是msg會有相關的內容
public String uid; // 我方給出的不沖突用戶id
public String channel; //渠道標識,用來區分用戶來自哪個渠道
public String access_token;//令牌
public String c_uid; //渠道返回的uid,TSDK內部使用,請勿使用,一般情況為空;
public int adult; //成年-1未成年, 0未知, 1成年
-
注銷登錄介紹
調起融合SDK的logout注銷,會調起相應的SDK注銷流程public static void logout(Context context, GameParams params,ILogoutCallback callback)
用于注銷登錄。參數 描述 能否為空 context 當前Activity的context 否 params 用于傳遞游戲注銷登錄的參數 否 callback 監聽注銷登錄的回調 否 GameParams 屬性 描述 暫無
LogoutResponse 包含下列字段
public int code; //登出狀態CODE_SUCCESS = 1; CODE_FAIL = -1;
public String msg; //code=CODE_FAIL ,是msg會有相關的內容
-
支付接口介紹
調起融合SDK的pay支付,會調起相應的SDK支付流程public static void pay(Context context, GameParams params, IPayCallback callback)
用于支付的方法。參數 描述 能否為空 context 當前Activity的context 否 params 用于傳遞游戲支付的參數 否 callback 監聽支付的回調 否 GameParams 屬性 描述 uid 用戶id access_token 令牌 productId 商品id productName 商品名 price 金額(元) serverId 服務器id roleId 角色id roleName 角色名 roleLevel 角色等級 gold 游戲幣,如鉆石 extension 擴展字段 PayResponse 包含下列字段
public int code; //支付返回狀態CODE_SUCCESS = 1; CODE_FAIL = -1; public String msg; //code=CODE_FAIL ,是msg會有相關的內容
-
游戲退出
調起融合SDK的quit退出,會調起相應的SDK退出流程public static void quit(Context context, GameParams params, IQuitCallback callback)
用于調起SDK的退出框的方法。參數 描述 能否為空 context 當前Activity的context 否 params 用于傳游戲退出的參數 否 callback 監聽退出的回調 否 GameParams 屬性 描述 暫無 回調說明
//渠道帶有退出框 @Override public void quitCallback(QuitResponse quitResponse) { Toast.makeText(this, "退出回調", Toast.LENGTH_SHORT).show(); if (quitResponse != null) { LogUtils.d(quitResponse.toString()); } finish(); } //渠道不帶退出框 @Override public void onNo3rdQuitCallback(QuitResponse quitResponse) { quitDialog(); } private void quitDialog() { AlertDialog.Builder builder = new Builder(this); builder.setMessage("確定要退出嗎?"); builder.setTitle("提示"); builder.setPositiveButton("確認", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); finish(); } }); builder.setNegativeButton("取消", new android.content.DialogInterface.OnClickListener() { @Override public void onClick(DialogInterface dialog, int which) { dialog.dismiss(); } }); builder.create().show(); }
QuitResponse 包含下列字段
public int code; //支付返回狀態CODE_SUCCESS = 1; CODE_FAIL = -1; public String msg; //code=CODE_FAIL ,是msg會有相關的內容
-
上傳擴展數據
調起融合SDK的上傳擴展數據接口,請在用戶選擇角色以及服務器后調用,否則無法正常支付public static void submitExtendData(Context context, GameParams params)
參數 描述 能否為空 context 當前Activity的context 否 params 用于傳擴展字段 否 GameParams 屬性 描述 score 分數 topnid 可選參數,排行榜標識,使用該參數需要確認對應ID的排行榜已經開通 roleId 角色id roleName 角色名 roleLevel 角色等級 zoneId 當前登錄的游戲區服ID,必須為數字,且不能為0,若無,傳入1 zoneName 當前登錄的游戲區服名稱,不能為空,不能為null,若無,傳入游戲名稱+”1區”,如”刀塔傳奇1區” balance balance 當前用戶游戲幣余額,必須為數字,若無,傳入0 vip vip 當前用戶VIP等級,必須為數字,若無,傳入1 partyName partyName 當前用戶所屬幫派,不能為空,不能為null,若無,傳入”無幫派 上傳數據接口需在三處調用,分別為進入服務器、玩家創建用戶角色、玩家升級,有如下二點需注意:
a)若游戲中無對應接口功能,如游戲中無需創建角色,則可根據自身情況在合適位置進行調用,如登錄成功后;
b)在上傳游戲數據時,若存在無對應字段值的情況,可傳入默認值,具體參見數據組成部分; -
生命周期函數調用
public static void onResume(Context context) public static void onPause(Context context) public static void onDestroy(Context context) SDK的生命周期函數,在程序的主Activity的生命周期相應函數中調用
抽象工廠
定義一個抽象工廠,規范需要實現的接入函數
public interface IChannel {
public void init(Context context, boolean isLandScape, IChannelInitCallback callback);
public void login(GameParams params);
public void pay(GameParams params);
public void logout(GameParams params);
public void quit(GameParams params);
public void onResume(Context context);
public void onPause(Context context);
public void onStop(Context context);
public void onDestroy(Context context);
public void submitExtendData(Context context, GameParams params);
}
調用對應的工廠實例
根據配置在 manifest 文件中的 CHANNEL_KEY 調用對應的工廠實例
public class DispatchChannel {
private static IChannel channel;
private static final String CHANNEL_KEY = "CHANNEL_KEY";
public static IChannel getChannel(Context context){
if(channel == null) {
ChannelFactory cf = new ChannelFactory();
String channelString = ChannelUtil.getChannel(context, SDKTools.getMetaData(context, CHANNEL_KEY));
channel = cf.createChannel(channelString);
}
return channel;
}
}
各渠道接入實現
AndroidManifest.xml中配置要調用的渠道以及對應渠道設置的代理Application
<!-- 渠道key start -->
<meta-data
android:name="CHANNEL_KEY"
android:value="" >
</meta-data>
<!-- 渠道key end-->
<!-- 代理Application start-->
<meta-data
android:name="T_APPLICATION_PROXY_NAME"
android:value="" >
</meta-data>
<!-- 代理Application end-->
<!-- 設置 application 標簽的 name 屬性-->
<application
android:name="com.tongbulv.sdk.TApplication"
定義一個具體的渠道類實現 抽象工廠接口
public class Channel360 extends BaseChannel implements IChannel
調用渠道登陸成功后和服務端做一次用戶綁定,返回用戶信息
支付前請求一次服務端的支付參數信息,再調起渠道SDK支付
打包工具
1. 解母包(copy 到對應的工作目錄)
apktool d -f -o $game_path $game_path${apk_suffix}
2. 資源處理
2.1 準備對應渠道的資源文件
assets(copy 到對應的工作目錄)
t_splash_images //閃屏文件夾,不存在或為空則沒有配閃屏
... //渠道此文件夾下的資源
libs (copy 到對應的工作目錄 lib 下)
... //渠道的非 .jar 文件
res (copy 到對應的工作目錄)
...
如碰到 strings.xml, styles.xml, colors.xml, dimens.xml, ids.xml, attrs.xml ... 則合并其內容
帶有對應渠道角標的 ic_launcher 對應的文件夾
classes.dex (具體接入渠道的 .dex 文件) 后面會用到
具體命令如下
cp -R -f $game_path/* $channel_name/
cp -R -f $config_name/AndroidManifest.xml $channel_name/
cp -R -f $config_name/assets/* $channel_name/assets/
cp -R -f $config_name/libs/* $channel_name/lib/
cp -R -f $config_name/res/* $channel_name/res/
# 合并strings.xml ...
$tool/xml -f $game_path/res/values/ -s $channel_name/res/values/ -t $config_name/res/values/
if [ -d "$config_name/channel_icon" ];then
# 合成icon
$tool/icon -f $channel_name/res/drawable-ldpi/$icon_name.png -s $channel_name/res/drawable-ldpi/$icon_name.png -t $config_name/channel_icon/ldpi.png -x 0 -y 0
$tool/icon -f $channel_name/res/drawable-mdpi/$icon_name.png -s $channel_name/res/drawable-mdpi/$icon_name.png -t $config_name/channel_icon/mdpi.png -x 0 -y 0
$tool/icon -f $channel_name/res/drawable-hdpi/$icon_name.png -s $channel_name/res/drawable-hdpi/$icon_name.png -t $config_name/channel_icon/hdpi.png -x 0 -y 0
$tool/icon -f $channel_name/res/drawable-xhdpi/$icon_name.png -s $channel_name/res/drawable-xhdpi/$icon_name.png -t $config_name/channel_icon/xhdpi.png -x 0 -y 0
$tool/icon -f $channel_name/res/drawable-xxhdpi/$icon_name.png -s $channel_name/res/drawable-xxhdpi/$icon_name.png -t $config_name/channel_icon/xxhdpi.png -x 0 -y 0
$tool/icon -f $channel_name/res/drawable-xxxhdpi/$icon_name.png -s $channel_name/res/drawable-xxxhdpi/$icon_name.png -t $config_name/channel_icon/xxxhdpi.png -x 0 -y 0
fi
3. 處理 AndroidManifest.xml文件, 并覆蓋到對應的工作目錄
3.1 渠道權限添加
3.2 包名修改
3.3 activity name屬性為全路徑
3.4 渠道 activity 等內容合并
3.5 渠道參數在 meta-data
3.6自有的參數 meta-data
3.7具體對應的 CHANNEL_KEY meta-data
3.8 具體對應的 T_APPLICATION_PROXY_NAME meta-data
4. 生成 R.java 文件
4.1 建一個gen文件夾
mkdir -p $channel_name/gen
4.2 執行 aapt p ... 命令
aapt p -f -m -J $channel_name/gen -S $channel_name/res -I $tool/android.jar -M $channel_name/AndroidManifest.xml
5. 將 R.java 編譯成對應的 .class 文件
javac -encoding UTF-8 $channel_name/gen/${package}${package_suffixs[$index]}/R.java
6. 將生成的 .class 文件生成 .dex 文件
$tool/dx --no-strict --dex --output=$channel_name/Rclasses.dex $channel_name/gen/$package/${package_suffixs[$index]}
7. 將生成的 .dex 文件 編譯成 smali格式的文件合并到 (1)中復制的對應工作目錄下的 smali 文件夾
java -jar $tool/baksmali.jar $channel_name/Rclasses.dex -o $channel_name/smali/
8. 將 (2)中準備好的 classes.dex 編譯成 smali 格式的文件合并到 (1)中復制的對應工作目錄下的 smali 文件夾
java -jar $tool/baksmali.jar $config_name/classes.dex -o $channel_name/smali/
9. 使用 apktool b ... 命令打包
apktool b -b ${channel_name}/
10. 使用 jarsinger 簽名
jarsigner -keystore $tool/${keystore} -storepass ${keypass} -signedjar ${channel_name}/dist/${game_name}_signed.apk ${channel_name}/dist/${game_name}.apk "${keyalias}"
11. zipalign 命令進行 4 字節對齊優化產生最終的 apk 文件
$tool/zipalign -f 4 ${channel_name}/dist/${game_name}_signed.apk $dir/apk/${game_name}/${channel}.apk