# 安卓游戏SDK-对接文档
# 注意
此SDK对接文档,标注必接的接口请在第一次接入时则必须接入,其余未标注说明必接的接口,可视运营情况及相关说明,再进行对接。
# 获取对接物料
开始对接时,我方会提供如下3个参数,如未获取,请联系我方运营或技术获取
参数字段 | 参数说明 | 示例 |
---|---|---|
unionPacketCode | 对接的唯一包ID | 10000 |
unionGameId | 游戏ID | 10000 |
gameKey | 登录加密Key | 1111 |
gamePayKey | 支付加密Key | 1111 |
# 集成Android客户端SDK
# SDK下载
# 拷贝资源并添加依赖库
导入资源
导入assets资源,拷贝资源文件
union_config.json
合并到您的游戏工程assets目录下
,并更改文件内的游戏参数如果不清楚如何根据参数修改,联系我方技术人员提供参数文件
{ "unionPacketCode": "20221000", #对接的唯一包ID "unionEnv": "dis", #默认 "unionLog": "dis", #默认 "unionGameId": "10011",游戏ID "unionVer": 100, #默认 "unionGameRequestPermissionList": [ "android.permission.READ_PHONE_STATE" ] #默认 }
拷贝union-core-1.0-release.aar包
资源到
app/libs`文件夹下添加依赖
aar
在Android Studio
中使用,需要在当前app的build.gradle
根目录下添加
repositories {
flatDir {
dirs 'libs'
}
}
dependencies {
implementation 'com.android.support:support-v4:28.0.0'
implementation files('libs/union-core-1.0-release.aar') // 核心插件 union_core 默认打入GSON oaid
}
androidx支持
如果使用的是AndroidX或者无法添加v4 包,
union_config.json
里面的unionGameRequestPermissionList设置为[]即可
{
"unionPacketCode": "20221000",
"unionEnv": "dis",
"unionLog": "dis",
"unionGameId": "10011",
"unionVer": 100,
"unionGameRequestPermissionList": []
}
设置
AndroidManifest.xml
,targetSdkVersion
为30
配置application
如果您的应用无自定义application
,则修改AndroidManifest.xml
的Application
如下:
<application android:name="com.union.channel.GameApplication">
如果您的应用有自定义application
,则自定义的Application
需要继承com.union.channel.GameApplication
<application android:name="自定义的Application">
配置权限
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.READ_PHONE_STATE"/>
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
配置应用支持
AndroidManifest.xml/application节点下面添加以下配置
<application
android:supportsRtl="true"
android:hardwareAccelerated="true" #支持硬件加速
android:usesCleartextTraffic="true" #支持http 请求
android:theme="@android:style/Theme.DeviceDefault.Light.NoActionBar.Fullscreen" #全面屏样式
/>
配置Activity
注意:设置启动Activity
和游戏的主activity
属性,请根据游戏的横竖屏更改screenOrientation
的属性为横屏或者竖屏,请设置configChanges
属性为:
android:configChanges="screenSize|keyboardHidden|orientation"
配置闪屏页Activity
增加闪屏页Activity
,您的闪屏页activity
必须设置继承com.union.platform.view.ui.UnionSplashActivity
,并将该Activity
设置为程序启动时的Activity
public class SplActivity extends UnionSplashActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(saveInstanceState);
}
@Override
public void startGameActivity() {
startGameActivity(String channelActivity);
}
//MainActivity 为游戏的主Activity
public void startGameActivity(String channelActivity) {
Intent intent = new Intent(this, MainActivity.class);
startActivity(intent);
overridePendingTransition(android.R.anim.fade_in, android.R.anim.fade_out);
finish();
}
}
# 接口说明
所有接口均以默认runOnMainThread
,无需再次处理
# SDK包体配置参数(登录之前可获取,需要正确配置Application)
一般游戏包会分不同的专服,不同的专服可能有不同的游戏地址
建议资源文件兼容不同的游戏地址
如果专服的地址在初始化之前需要根据特定配置走可获取 gameid 和 packetCode 作为条件判断
GamePackageConfig gamePackageConfig=UnionGameSDK.share().getGameConfig();
String gameId=gamePackageConfig.getUnionGameId();
String packetCode=gamePackageConfig.getUnionPacketCode();
UnionLog.i(gameId+":"+packetCode);
# 全面屏适配
UnionGameSDK.share().setFullScreenWithSystemUi(Activity activity);
# 显示Android Webview
常用于弹出用户协议 登录协议,分级
UnionGameSDK.share().showWebDialog(Activity activity,"标题","url");
# SDK初始化(必接)
所有其他接口均需要在初始化成功回调后使用
# 调用说明
UnionGameSDK.share().registerCallback(Activity activity,UnionGameCallback callback);
# 参数说明
参数 | 类型 | 例子 | 备注 |
---|---|---|---|
activity | Activity | this | |
callback | UnionGameCallback | SDK回调 | SDK 所有的操作做的回调信息都在这个里面 |
# 接入示例
UnionGameSDK.share().registerCallback(this, new UnionGameCallback() {
@Override
public void onInitResult(int code, String msg) {
switch (code) {
case UnionSDKStatue.CODE_INIT_SUC:
// 初始化成功处理
break;
case UnionSDKStatue.CODE_INIT_FAI:
// 初始化失败处理
break;
}
}
@Override
public void onLoginResult(int code, UnionTK token) {
}
@Override
public void onSwitchAccount(UnionTK token) {
}
@Override
public void onLogout() {
}
@Override
public void onPurchaseResult(int code, String msg) {
}
@Override
public void onReportResult(int code) {
}
@Override
public void onGameFunction(int code, String msg) {
}
@Override
public void onExit() {
}
@Override
public void onAdRewardVerify() {
}
});
# Activity 生命周期接口(必接)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
UnionGameSDK.share().onCreate(this,savedInstanceState);
}
@Override
public void onBackPressed() {
super.onBackPressed();
UnionGameSDK.share().onBackPressed();
}
@Override
protected void onStart() {
super.onStart();
UnionGameSDK.share().onStart();
}
@Override
protected void onPause() {
super.onPause();
UnionGameSDK.share().onPause();
}
@Override
protected void onResume() {
super.onResume();
UnionGameSDK.share().onResume();
}
@Override
protected void onStop() {
super.onStop();
UnionGameSDK.share().onStop();
}
@Override
protected void onRestart() {
super.onRestart();
UnionGameSDK.share().onRestart();
}
@Override
protected void onDestroy() {
super.onDestroy();
UnionGameSDK.share().onDestroy();
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
UnionGameSDK.share().onNewIntent(intent);
}
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
UnionGameSDK.share().onRestoreInstanceState(savedInstanceState);
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
UnionGameSDK.share().onSaveInstanceState(outState);
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data){
super.onActivityResult(requestCode, resultCode, data);
YUnionGameSDK.share().onActivityResult(requestCode, resultCode, data);
}
@Override
protected void attachBaseContext(Context newBase) {
super.attachBaseContext(newBase);
UnionGameSDK.share().attachBaseContext();
}
@Override
public void onConfigurationChanged(Configuration newConfig) {
super.onConfigurationChanged(newConfig);
UnionGameSDK.share().onConfigurationChanged(newConfig);
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
UnionGameSDK.share().onRequestPermissionsResult(requestCode, permissions, grantResults);
}
# 登录接口(必接)
# 调用说明
UnionGameSDK.getInstance().login(Activity activity);
# 回调示例
@Override
public void onLoginResult(int code, UnionToken token) {
switch (code) {
case UnionSDKStatue.CODE_LOGIN_SUC:
// 登录成功处理
unionToken.getGameId();
unionToken.getSign();//登录验证需要
unionToken.getTs();//登录验证需要
unionToken.getOpenId();
unionToken.getTags();//分包TAG
unionToken.getPrivacyUrl(); //隐私协议url
unionToken.getServiceUrl();//用户协议url
unionToken.getIsbn();// ISBN
unionToken.getSoftName();// 著作权人名称
unionToken.getPublishName();// 出版单位名称
unionToken.getAuthNo();// 批文号
unionToken.getOperName();// 运营单位
unionToken.getSoftNo();// 软著登记号
unionToken.getExtend();// 扩展参数
unionToken.getIcp();// Icp备案号
unionToken.getPcode();// 游戏渠道包ID
unionToken.getExtend();// 附加控制参数,json字符串,需要原样回传给研发后端,方便后续新增需求扩展
//{"age":"16 年龄分级","ageUrl":"16 年龄分级地址"}
break;
case UnionSDKStatue.CODE_LOGIN_FAI:
// 登录失败处理
break;
}
}
# 返回的 UnionTK 参数说明
方法 | 返回类型 | 例子 | 备注 |
---|---|---|---|
getOpenId() | String | u-10000-579b2fe6d188e1a82dcb06cfff96ebf | 用户唯一标识 |
getGameId() | int | 100000 | 游戏ID |
getCid() | String | 100000 | 渠道ID |
getTs() | String | 1701931432675 | 毫秒级时间戳 |
getSignVer() | int | 1 | 签名版本,当前默认1 |
getSign() | String | 642029cf0c290e38a95ef59d232b338f | 登录签名 |
getPrivacyUrl() | String | xx | 隐私协议url |
getServiceUrl() | String | xx | 用户协议url |
getIsbn() | String | xx | ISBN |
getSoftName() | String | xx | 著作权人名称 |
getPublishName() | String | xx | 出版单位名称 |
getAuthNo() | String | 10000 | 批文号 |
getOperName() | String | 10000 | 运营单位 |
getSoftNo() | String | 10000 | 软著登记号 |
getIcp() | String | 10000 | Icp备案号 |
getPcode | String | 10000 | 游戏渠道包ID |
getExtend() | String | {"age":"16 年龄分级","ageUrl":"16 年龄分级地址"} | 附加控制参数 |
# 服务端登录验证(必接)
根据登录接口返回的UnionTK
字段参数判断以下等式是否成立,成立则通过验证,务必在服务端进行
sign=md5(openId+"|"+gameId+"|"+ts+"|"+gameKey)
# 支付接口(必接)
# 调用说明
UnionGameSDK.getInstance().purchase(Activity activity,UnionPurchaseParams purchaseParams);
# 回调示例
@Override
public void onPurchaseResult(int code, String msg) {
switch (code) {
case UnionSDKStatue.CODE_PURCHASE_SUC:
// 支付成功回调
break;
case UnionSDKStatue.CODE_PURCHASE_FAI:
// 支付失败回调
break;
}
}
# 参数说明
方法传入参数UnionPurchaseParams
,其属性如下
方法 | 类型 | 例子 | 备注 |
---|---|---|---|
setOpenId() | String | u-10000-579b2fe6d188e1a82dcb06cfff96ebf | 用户唯一标识 |
setGameId() | int | 100000 | 游戏ID |
setTs() | String | 1701931432675 | 毫秒级时间戳 |
setSignVer() | int | 1 | 签名版本,当前默认1 |
setSign() | String | 642029cf0c290e38a95ef59d232b338f | 支付下单签名,看下面签名规则 |
setRoleId() | String | 147176212 | 角色ID |
setRoleName() | String | 齐天大圣 | 角色名称 |
setRoleLevel() | String | 10 | 角色等级 |
setRoleVipLevel() | String | 2 | 角色VIP等级 |
setRoleFight() | String | 12612 | 角色战力 |
setServerId() | String | 1001 | 区服ID |
setServerName() | String | 1001服 | 区服名称 |
setGameOrderCode() | String | 16253651265x17631212 | 游戏订单号 |
setGameOrderCustomInfo() | String | 16253651265x17631212 | 订单自定义字符串,支付回调时会原样返回 |
setGameProductCode() | String | 1001 | 游戏商品计费点 |
setGameProductName() | String | 100元宝 | 游戏商品名称 |
setGameProductPrice() | int | 100 | 支付金额,单位(分) |
setGameExtend() | String | 100 | json格式字符串,扩展参数 |
# sign签名规则
sign=md5(gameId+"|"+openId+"|"+roleId+"|"+serverId+"|"+gameOrderCode+"|"+gameProductCode+"|"+gameProductPrice+"|"+ts+"|"+gamePayKey);
# 服务端支付回调(必接)
游戏方需要根据下面文档对接完成后提供URL地址
给到我方进行配置,游戏在正常支付完成后,游戏方会收到我方接口调用。
# 回调通知方式
HTTP POST
# 回调通知格式
application/json
# 回调参数说明
本协议中所有字符串使用UTF8编码
参数 | 类型 | 例子 | 备注 |
---|---|---|---|
openId | String | u-10000-579b2fe6d188e1a82dcb06cfff96ebf | 用户唯一标识 |
gameId | int | 100000 | 游戏ID |
ts | String | 1701931432675 | 毫秒级时间戳 |
signVer | int | 1 | 签名版本,当前默认1 |
sign | String | 642029cf0c290e38a95ef59d232b338f | 支付下单签名,看下面签名规则 |
roleId | String | 147176212 | 角色ID |
serverId | String | 1001 | 区服ID |
orderCode | String | i-10000010000-20231109150147645-745gm | 我方订单号 |
gameOrderCode | String | 16253651265x17631212 | 游戏方调起支付时传入的游戏订单号 |
gameOrderCustomInfo | String | 16253651265x17631212 | 游戏方调起支付时传入的游戏自定义参数 |
gameProductCode | String | 1001 | 游戏商品计费点 |
gameProductPrice | int | 100 | 支付金额,单位(分) |
isSandBox | int | 0 | 是否测试订单,1-是测试订单,0-否 |
discountPrice | int | 0 | 优惠金额,单位(分) |
# 回调签名说明
sign=md5(`${gameId}|${gameOrderCode}|${orderCode}|${gameProductPrice}|${gameProductCode}|${serverId}|${roleId}|${openId}|${ts}|${gamePayKey}`);
# 回调返回说明
返回类型:字符串
- 成功返回小写字母:"ok"
- 失败返回:"失败原因"
# 回调接口其他注意事项
- 游戏接入时,必须验证订单信息跟游戏方本地下订单信息进行匹配,防止中途被人串改
- sign值必须要验证,
gamePayKey
必须由服务端保存,防止泄漏 - 订单有可能会出现多次同步,请做好幂等性,并返回“ok”
- 同步失败情况,我方会根据定义好的规则进行多次尝试
# 角色上报接口(必接)
# 调用说明
UnionGameSDK.getInstance().report(UnionAnalyticsParams analyticsParams);
# 回调示例
@Override
public void onReportResult(int code, String msg) {
switch (code) {
case EventStatus.CODE_REPORT_SUC:
// 上报角色信息成功回调
break;
case EventStatus.CODE_REPORT_FAI:
// 上报角色信息失败回调
break;
}
}
# 参数说明
方法传入参数UnionAnalyticsParams
,其属性如下
参数 | 类型 | 例子 | 备注 |
---|---|---|---|
setType() | int | 1 | 角色上报类型,1-选服,2-创角,3-登录,4-升级,5-退出 |
setOpenId() | String | u-10000-579b2fe6d188e1a82dcb06cfff96ebf | 用户唯一标识登陆之后返回 |
setGameId() | int | 100000 | 游戏ID 登陆之后返回 |
setTs() | String | 1701931432675 | 毫秒级时间戳,登陆之后返回 |
setSignVer() | int | 1 | 签名版本,当前默认1,登陆之后返回 |
setSign() | String | 642029cf0c290e38a95ef59d232b338f | 支付下单签名,看下面签名规则 |
setRoleId() | String | 147176212 | 角色ID |
setRoleName() | String | 齐天大圣 | 角色名称 |
setRoleLevel() | String | 10 | 角色等级 |
setRoleVipLeve() | String | 2 | 角色VIP等级 |
setRoleFight() | String | 12612 | 角色战力 |
setServerId() | String | 1001 | 区服ID |
setRoleServerDay() | int | 1 | 开服时间 |
setServerName() | String | 1001服 | 区服名称 |
setGameExtend() | String | "{}" | 扩展参数,json 格式字符串,后续有其他需求在此字段新增 |
# 签名规则
sign=md5(gameId+"|"+openId+"|"+roleId+"|"+serverId+"|"+ts+"|"+gameKey);
# 退出登录(必接)
当游戏内含有退出按钮或游戏发生顶号时,游戏方可主动调用退出接口
# 调用说明
UnionGameSDK.getInstance().logout();
# 回调示例
@Override
public void onLogout() {
// SDK已登出,注销相关信息, 执行后续登出操作
}
# 控制显示其他定制功能(SDK控制,渠道差异性需求)
@Override
public void onGameFunction(int i, String data) {
//此方法会根据根据事件自动触发,触发时机一般在角色登录/角色升级/支付完成或者取消
switch (i) {
case UnionSDKStatue.CODE_SHOW_QUESTION_SDK:
//显示问卷调查按钮 点击按钮调用 SDK 方法
break;
case UnionSDKStatue.CODE_SHOW_QUESTION:
//显示问卷调查按钮 点击按钮调用游戏自定义UI
break;
case UnionSDKStatue.CODE_SHOW_VIP_SDK:
//显示VIP按钮 点击按钮调用 SDK 方法
break;
case UnionSDKStatue.CODE_SHOW_VIP:
//显示VIP按钮 点击按钮调用游戏自定义UI
try {
JSONObject jsonObject = new JSONObject(data);
String qr_code = jsonObject.getString("vipQrCode");//引导的二维码
String text = jsonObject.getString("vipText");//引导的多个位置文本以|拼接,可自由切割
String ext = jsonObject.getString("vipExt");//拓展JSON参数,后续可能需要
} catch (JSONException e) {
e.printStackTrace();
}
break;
case UnionSDKStatue.CODE_HIDE_QUESTION:
// 隐藏问卷调查按钮
break;
case UnionSDKStatue.CODE_HIDE_VIP:
// 隐藏VIP按钮
break;
default:
break;
}
}
# 调用显示其他定制功能(研发后端控制)
// 1-打开外部商城,2-打开客服,3-打开问卷,4-打开VIP客服,5-显示激励视频
UnionAnalyticsParams unionAnalyticsParams = new UnionAnalyticsParams();
unionAnalyticsParams.setType(3);
unionAnalyticsParams.setOpenId(unionToken.getOpenId());
unionAnalyticsParams.setRoleId("123456");
unionAnalyticsParams.setRoleName("123456");
unionAnalyticsParams.setRoleLevel("1");
unionAnalyticsParams.setRoleVipLevel("1");
unionAnalyticsParams.setRoleServerDay(5);
unionAnalyticsParams.setRoleFight("1"); //无传0
unionAnalyticsParams.setServerId("1");
unionAnalyticsParams.setServerName("神明一区");
unionAnalyticsParams.setGameExtend("{}");// json 格式字符串
UnionGameSDK.share().showDynamicFunction(unionAnalyticsParams);
# 关闭游戏
调用此接口,APP会被杀掉进程退出到桌面
# 调用说明
UnionGameSDK.getInstance().exit();
# 回调示例
@Override
public void onExit() {
// 已登出
}
# 状态码对照表
状态码 | 说明 |
---|---|
CODE_INIT_SUC | 初始化成功 |
CODE_INIT_FAI | 初始化失败 |
CODE_LOGIN_SUC | 登录成功 |
CODE_LOGIN_FAI | 登录失败 |
CODE_PURCHASE_SUC | 支付成功 |
CODE_PURCHASE_FAI | 支付失败 |
CODE_PURCHASE_CANCEL | 取消支付 |
CODE_REPORT_SUC | 上报角色信息成功 |
CODE_REPORT_FAI | 上报角色信息失败 |