游戏SDK对接文档

SDK对接文档


【悦声】Android SDK对接文档

一、工程配置

  • 引入工程

      AndroidStudio用户将lib目录下的aar文件拷贝到自己的项目lib下,加以引用即可!
      Eclipse用户请自行百度,添加对应的依赖
  • 其他資源添加(如果有则按以下目录规则添加即可)

    assets的资源直接复制即可;

  • SDK下载地址

    AndroidSDK 资源以及DEMO下载地址

1.权限配置

    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" ></uses>
    <uses-permission android:name="android.permission.WRITE_SETTINGS" ></uses>
    <uses-permission android:name="android.permission.VIBRATE" ></uses>
    <uses-permission android:name="android.webkit.permission.PLUGIN" ></uses>
    <uses-permission android:name="android.permission.INTERNET" ></uses>
    <uses-permission android:name="android.permission.SEND_SMS" ></uses>
    <uses-permission android:name="android.permission.READ_SMS" ></uses>
    <uses-permission android:name="android.permission.RECEIVE_WAP_PUSH" ></uses>
    <uses-permission android:name="android.permission.RECEIVE_MMS" ></uses>
    <uses-permission android:name="android.permission.RECEIVE_SMS" ></uses>
    <uses-permission android:name="android.permission.READ_PHONE_STATE" ></uses>
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" ></uses>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" ></uses>
    <uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" ></uses>
    <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS" ></uses>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" ></uses>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" ></uses>
    <uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" ></uses>
    <uses-permission android:name="android.permission.RESTART_PACKAGES" ></uses>
    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" ></uses>
    <uses-permission android:name="android.permission.GET_TASKS" ></uses>
    <uses-permission android:name="android.permission.RECORD_AUDIO" ></uses>
    <uses-permission android:name="android.permission.REQUEST_INSTALL_PACKAGES" ></uses>

4、Application接入(注意:请务必接入)

游戏方自身的Application对应的方法中实现以下四个方法:

  1. onCreate 方法:onApplicationCreate(Application application)
  2. attachBaseContext 方法onApplicationAttachBaseContextInApplication(Application application, Context base)
  3. onConfigurationChanged 方法onApplicationConfigurationChanged(Application application, Configuration newConfig)
  4. onTerminate 方法onApplicationTerminate(Application application)

示例如下:

/**
 * 必须要自定义一个application 并且要在manifest中声明,  其中所有方法要在super后面调用
 */
public class MyApplication extends Application {

    @Override
    public void onCreate() {
        super.onCreate();
        YsUnionSdk.getInstance().onApplicationCreate(this);
    }

    @Override
    protected void attachBaseContext(Context base) {
        super.attachBaseContext(base);
        YsUnionSdk.getInstance().onApplicationAttachBaseContextInApplication(this, base);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        YsUnionSdk.getInstance().onApplicationConfigurationChanged(this, newConfig);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        YsUnionSdk.getInstance().onApplicationTerminate(this);
    }
}

注意:记得在manifest中声明自定义的Application

二、SDK接口调用

1.AndroidManifest.xml文件的配置(必接)

<menifest>
<application>
...
<!-- 聚合sdk -->
<!-- 请务必接入 我方SDK闪屏Activity -->
<activity
   android:name="com.yssdk.base.communal.element.SplashScreenActivity"
   android:theme="@android:style/Theme.NoTitleBar.Fullscreen"
   android:screenOrientation="portrait">
   <intent-filter>
      <action android:name="android.intent.action.MAIN" />
      <category android:name="android.intent.category.LAUNCHER" />
   </intent-filter>
</activity>

<!-- 是否有闪屏图片 固定-->
<meta-data
   android:name="sdk_ys_splash_pic"
   android:value="false" />
<!-- cp的启动Activity -->
<meta-data
   android:name="sdk_ys_entryactivity"
   android:value="cp的启动Activity" />

<!-- sdk对接类 固定-->
<meta-data
   android:name="sdk_ys_userimp"
   android:value="com.yssdk.sdk.channel.YsChannel" />

<!--游戏名称 我方运营提供-->
<meta-data
   android:name="sdk_ys_game_name"
   android:value="SDK测试" />

<!--游戏ID,我方运营提供-->
<meta-data
   android:name="sdk_ys_main_game_id"
   android:value="90" />

<!-- 自己渠道sdk的appid 我方运营提供-->
<meta-data
   android:name="sdk_ys_sub_game_id"
   android:value="576" />

<!-- 自己渠道sdk的appkey 我方运营提供-->
<meta-data
   android:name="sdk_ys_app_key"
   android:value="%167%173%217%102%105%158%172%194%210%144%153%167%216%221%168%145%101%157%218%196%160%97%152%158%219%221%167%146%148%164%168%147" />

<!--打包ID,固定-->
<meta-data
   android:name="sdk_ys_package_id"
   android:value="1" />

<!--现网填true 测试网填false-->
<meta-data
   android:name="sdk_ys_online"
   android:value="true" />

<!--投放系统->监测链接->广告包ID-->
<meta-data
   android:name="sdk_ys_site_id"
   android:value="1001" />
<!--投放系统->监测链接->投放标签-->
<meta-data
   android:name="sdk_ys_pfname"
   android:value="yuesheng" />

<!--我方SDK组件-->
<activity
   android:name="com.yssdk.sdk.LoginActivity"
   android:configChanges="keyboard|keyboardHidden|screenLayout|screenSize|orientation"
   android:launchMode="singleTask"
   android:hardwareAccelerated="true"
   android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen"
   android:windowSoftInputMode="adjustPan" />

<service android:name="com.yssdk.sdk.CallbackResultService" />

<service
   android:name="com.yssdk.sdk.ui.floatView.FloatBallService"
   android:exported="false" />

<activity
   android:name="com.yssdk.sdk.CommonWebviewActivity"
   android:configChanges="orientation|screenSize|keyboardHidden" />
<activity
   android:name="com.yssdk.base.communal.element.YsChaActivity"
   android:configChanges="keyboardHidden|orientation|screenSize"
   android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity
   android:name="com.yssdk.base.communal.element.NoticeActivity"
   android:configChanges="keyboardHidden|orientation|screenSize"
   android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
<activity
   android:name="com.yssdk.sdk.PaymentActivity"
   android:configChanges="keyboardHidden|orientation|screenSize"
   android:theme="@style/yssdk_gift_dialog" />

<activity
   android:name="com.yssdk.sdk.ui.ActicitySide"
   android:configChanges="keyboardHidden|orientation|screenSize"
   android:theme="@android:style/Theme.Translucent.NoTitleBar.Fullscreen" />
</application>
</menifest>

2.SDK初始化(必接)

接口:YsUnionSdk.getInstance().initSDK(Activity activity, YsSdkListener listener);

接口示例:

private void initSdk() {
    Log.i(TAG, "initSdk...");
    // init方法只能在主Activity的onCreate中调用,第二个参数为全局回调
    YsUnionSdk.getInstance().initSDK(activity, new YsSdkListener() {
        @Override
        public void initSuc(String msg) {
            initSuc = true;
            YsUnionSdk.getInstance().loginSDK(activity);
            Log.e(TAG, "收到回调初始化成功: " + msg);
            Log.e(TAG, "收到回调初始化成功: " + msg);

        }

        @Override
        public void initFailed(String reason) {
            initSuc = false;
            Log.e(TAG, "收到回调初始化失败: " + reason);
        }

        @Override
        public void onLoginSuc(String data) {
            Log.e(TAG, "收到回调登录成功 " + data);
            try {
                JSONObject jsonObject = new JSONObject(data);
                String cur_uid = jsonObject.getString("userId");//服务端登录验证使用,账号唯一标识,  建议和渠道id拼接作为唯一标识,避免多渠道渠道userId重复.某些渠道此字段可能有点长,建议留100位保存.
                String new_sign = jsonObject.getString("new_sign");//服务端登录验证使用
                String timestamp = jsonObject.getString("timestamp");//服务端登录验证使用
                String cp_ext = jsonObject.getString("cp_ext");//服务端登陆验证使用,这是一个json,  目前写死为{"test":"test"}
                String guid = jsonObject.getString("guid");//服务端登陆验证使用
                String channelId = jsonObject.getString("channelId");//渠道id  如联想为15   具体参见<各渠道参数>
                String channelVersion = jsonObject.getString("channelVersion");//渠道版本
                String packageId = jsonObject.getString("packageId");//包id.对应一个游戏安装包.
                String age = jsonObject.getString("age");//年龄
                String realNameStatus = jsonObject.getString("realNameStatus");//实名状态 0:未实名:1:已实名
                String isVisitors = jsonObject.getString("isVisitors");//是否游客 0:不是 ,1:游客
                //上面的参数,每次登录成功一定会返回。所以可用getString方法获取.
                userId = cur_uid;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onLoginFailed(String reason) {
            Log.e(TAG, "收到回调登录失败 " + reason);
            userId = "";
        }

        @Override
        public void onLogout(boolean shouldRelogin) {
            Log.e(TAG, "收到回调登出 " + shouldRelogin);
            userId = "";
            if (shouldRelogin) {
                // 1.退出游戏场景,回到游戏主界面。 TODO
                // 2.重新调起sdk登录
                YsUnionSdk.getInstance().loginSDK(activity);
            } else {
                // 1 退出游戏场景,回到游戏主界面。
                // 2 不需主动再调用sdk登录, 但需要有用户点击主界面能调起sdk登录的功能.
            }
        }

        @Override
        public void onPaySuc(String extension) {
            Log.e(TAG, "收到回调支付成功:" + extension);
        }

        @Override
        public void onPayFail(String extension) {
            Log.e(TAG, "收到回调支付失败:" + extension);
        }

        @Override
        public void onExit() {
            Log.e(TAG, "收到回调退出 onExit");
            // 上报角色信息 TODO
            YsUnionSdk.getInstance().submitDataSDK(activity, createUserPrams(YsUserExtraData.TYPE_EXIT_GAME));

            //清理资源 杀死进程 TODO
            finish();
            System.exit(0);
        }

        @Override
        public void onResult(int code, String msg) {
            Log.e(TAG, "收到回调其他 code=" + code + " msg=" + msg);
        }
    });
}

3.登陆(必接)

接口:YsUnionSdk.getInstance().loginSDK(Activity activity)

回调结果onLoginSuc(String json)解析之后的数据如下
参数 类型 说明
userId String 服务端登录验证使用,账号唯一标识, 建议和渠道id拼接作为唯一标识,避免多渠道渠道userId重复.某些渠道此字段可能有点长,建议留100位保存.
new_sign String 服务端登录验证使用
timestamp String 服务端登录验证使用
cp_ext String 服务端登陆验证使用,这是一个json, 目前写死为{“test”:”test”}
guid String 服务端登陆验证使用
channelId String 渠道id
channelVersion String 道版本
age String 年龄
realNameStatus String 实名状态 0:未实名:1:已实名
isVisitors String 是否游客 0:不是 ,1:游客

4.支付(必接)

接口:YsUnionSdk.getInstance().paySDK(Activity activity, YsUnionPayParams params)

支付参数YsUnionPayParam获取示例:

private YsUnionPayParams createPayParams() {
    orderId = orderId + "_";
    YsUnionPayParams payParams = new YsUnionPayParams();
    payParams.setBuyNum(1);// 一般只买一份
    // cp测试回调写 https://rh-api.hnjst.cn/success.php
    payParams.setCallBackUrl("https://rh-api.hnjst.cn/success.php");
    payParams.setExtension("回传参数");
    payParams.setOrderId(orderId);//cp的订单id
    payParams.setPartyName("武当派");
    payParams.setPer_price(1);// 单位为分, 但只支持元为单位,所以传100的整数
    payParams.setProductDesc("一锭做工完美的金元宝");
    payParams.setProductId("11100");
    payParams.setProductName("元宝");
    payParams.setRatio(10);// 1人民币 10个
    payParams.setRemainCoinNum(5000);// 此玩家钱袋里还有5000个元宝
    payParams.setRoleId("123");
    payParams.setRoleLevel(100);
    payParams.setRoleName("悟饭");
    payParams.setServerId("1");
    payParams.setServerName("华中区");
    payParams.setTime(System.currentTimeMillis());// 13位毫秒
    payParams.setTotalPrice(1); // 总价格 = 购买份数 * 单价
    payParams.setVip(12 + "");

    String gsonToString = GsonUtil.GsonToString(payParams);
    Log.d(TAG, "支付参数:" + gsonToString);
    return payParams;
}

支付结果会在初始化监听回调中返回,onPaySuc(String extension)回调支付成功,onPayFail(String extension)回调支付失败结果;

5.账号切换与注销(必接)

接口:YsUnionSdk.getInstance().logoutSDK(Activity activity, boolean isRelogin)

其中参数:isRelogin表示是否重新拉起登陆的意思,调用注销或者切换的逻辑为:玩家在悬浮窗、或者游戏内设置中点击注销账号,应回到游戏登陆界面,最后重新拉起登陆;如果isRelogin设置为false,需要cp方手动拉起登陆界接口!

6.游戏数据上报(必接)

接口:YsUnionSdk.getInstance().submitDataSDK(Activity activity, YsUserExtraData params)

YsUserExtraData数据获取示例:

// 上报参数
private YsUserExtraData createUserPrams(int type) {
    YsUserExtraData userExtraData = new YsUserExtraData();
    // 设置上报类型
    userExtraData.setDataType(type);
    userExtraData.setServerId("1");//玩家所在服务器的ID
    userExtraData.setServerName("华中区");//玩家所在服务器的名称
    userExtraData.setRoleId("123456789111");//玩家角色ID
    userExtraData.setRoleName("悟饭");//玩家角色名称 若无则传"无"
    userExtraData.setRoleLevel(100);//玩家角色等级
    userExtraData.setProfessionId(2);//当前玩家职业id
    userExtraData.setProfession("刺客");//当前玩家职业名称 若无,传入"无"
    userExtraData.setPower(10000);//战斗力
    userExtraData.setVip(5);//玩家VIP等级
    userExtraData.setRoleGender("女");//角色性别 (男或女)
    userExtraData.setPayTotal(2000);// 累计充值金额 元为单位
    userExtraData.setRemainCoinNum(5000);//  1级货币余额,此玩家钱袋里还有5000个元宝.
    userExtraData.setPartyId(1);//帮派id
    userExtraData.setPartyName("武当派");//帮派名称 若无,传入"无"
    userExtraData.setPartyRoleId(1);//角色在帮派中的称号id
    userExtraData.setPartyRoleName("武当-大师兄");// 角色在帮派中的称号  若无,传入"无"
    userExtraData.setRoleCreateTime((int) (System.currentTimeMillis() / 1000));//10位 秒

    // 人民币能买到的货币统计(传json) 若无则传0
    JSONArray balancelist = new JSONArray();
    JSONObject balance1 = new JSONObject();// 1级货币
    JSONObject balance2 = new JSONObject();// 2级货币
    try {
        balance1.put("balanceid", "1");
        balance1.put("balancename", "元宝");
        balance1.put("balancenum", "5000");

        balance2.put("balanceid", "2");
        balance2.put("balancename", "钻石");
        balance2.put("balancenum", "100");
    } catch (JSONException e) {
        e.printStackTrace();
    }
    balancelist.put(balance1).put(balance2);
    userExtraData.setBanlance(balancelist.toString());
    //userExtraData.setBanlance("0");//若无则传0

    // 此角色的好友关系(传json)  若无好友则传"无"
    JSONArray friendlist = new JSONArray();
    JSONObject friend1 = new JSONObject();
    JSONObject friend2 = new JSONObject();
    try {
        friend1.put("roleid", "150");//关系角色id
        friend1.put("intimacy", "100");//亲密度
        friend1.put("nexusid", "1");//1:夫妻,2:结拜,3:情侣,4:师徒 ,5:仇人;其余关系从6开始自定义编号  不能为空
        friend1.put("nexusname", "夫妻");//

        friend2.put("roleid", "151");
        friend2.put("intimacy", "2");
        friend2.put("nexusid", "6");//自定义关系id为6
        friend2.put("nexusname", "师兄弟");//自定义关系名称:师兄弟
    } catch (JSONException e) {
        e.printStackTrace();
    }
    friendlist.put(friend1).put(friend2);

    userExtraData.setFriendShip(friendlist.toString());
    //userExtraData.setFriendShip("无");//若无好友关系则传无

    /* 以上都为常规参数,各个上报事件都需要传. 选择服务器,创角的时候肯定很多参数是没有的,那么只传已经存在参数 */

    /** 上报类型为TYPE_LEVEL_UP 的时候传下面的参数 **/
    userExtraData.setRoleLevelUpTime((int) (System.currentTimeMillis() / 1000));// 10位秒

    /**
     * 上报类型为TYPE_TASK 的时候传下面的参数 任务统计 (任务完成时,不管是成功还是失败)
     */
    userExtraData.setTask_id(11);//ID cp定义
    userExtraData.setTask_name("追查凶手");
    userExtraData.setTask_status(1);// 1:成功 2:失败
    /**
     * 上报类型为TYPE_HONOR 的时候传下面的参数 荣誉统计(一个角色可以获得多个荣誉 如:排行榜多少名、xx勋章、称号)
     */
    userExtraData.setHonor_id(1);//ID cp定义
    userExtraData.setHonor_name("晋升副掌门");

    String gsonToString = GsonUtil.GsonToString(userExtraData);
    Log.d(TAG, "上报参数:" + gsonToString);
    return userExtraData;
}

7.退出接口(必接)

接口:YsUnionSdk.getInstance().exitSDK(Activity activity)

退出回调会在onExit()中返回,请在此回调方法中处理游戏退出的相关逻辑;

8.获取实名信息(选接)

接口:YsUnionSdk.getInstance().onGetRealNameInfo(Activity activity, RealNameCallback callback)

9. 获取SDK生成的设备识别码(选接)

接口:YsUnionSdk.getInstance().getUtma(Context context)

10.主Activity声明周期(必接)

请务必尽可能的接入以下生命周期!!

/* 生命周期  全部都要在super后面调用,除了onBackPressed不需要调用super*/
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    YsUnionSdk.getInstance().onActivityResult(activity, requestCode, resultCode, data);
}

@Override
public void onBackPressed() {
    //同步生命周期
    YsUnionSdk.getInstance().onBackPressed(activity);
    // 监听返回键调用退出接口
    YsUnionSdk.getInstance().exitSDK(activity);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    YsUnionSdk.getInstance().onConfigurationChanged(activity, newConfig);
}

@Override
protected void onStart() {
    super.onStart();
    YsUnionSdk.getInstance().onStart(activity);
}

@Override
protected void onPause() {
    super.onPause();
    YsUnionSdk.getInstance().onPause(activity);
}

@Override
protected void onResume() {
    super.onResume();
    YsUnionSdk.getInstance().onResume(activity);

}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    YsUnionSdk.getInstance().onNewIntent(activity, intent);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
                                       int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    YsUnionSdk.getInstance().onRequestPermissionsResult(activity, requestCode, permissions, grantResults);
}

@Override
protected void onStop() {
    super.onStop();
    YsUnionSdk.getInstance().onStop(activity);

}

@Override
protected void onDestroy() {
    super.onDestroy();
    YsUnionSdk.getInstance().onDestroy(activity);
}

@Override
protected void onRestart() {
    super.onRestart();

    YsUnionSdk.getInstance().onRestart(activity);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    YsUnionSdk.getInstance().onWindowFocusChanged(activity, hasFocus);
}

详细,请参考DEMO示例!
详细,请参考DEMO示例!
详细,请参考DEMO示例!

FQA:

  1. 由于目前渠道审核制度严格,请务必在我方弹出隐私协议窗口之后在获取相关设备信息(OAID、IMEI、AndroidID等)
  2. 请务必在我方SDK初始化成功之后,方可操作其他接口操作、否则会产生不可预料的闪退等问题;

页面列表

ITEM_HTML