《插件自助开发——用户系统》

用户系统包含用户帐号相关的接口,需要实现框架接口 ProtocolUser,并通过框架的 UserWrapper 类实现登陆验证、回调等。

构造函数和初始化

用户系统的类一般命名为“User+插件名”,构造函数参数为 Context,是主 Activity 的 Context,很多 SDK 接口需要该参数。在构造函数中实现初始化SDK等。
百度游戏的构造函数如下:

public UserBDYouxi(Context context)
{
    mActivity = (Activity)context;
    mUserInterface = this;
    configDeveloperInfo(PluginHelper.getParamsInfo());
}

说明:

客户端打包时,通过插件 config.xml 中参数列表,显示并配置的参数通过框架接口 PluginHelper.getParamsInfo 获取。
用户系统的初始化回调有两种返回值:
ACTION_RET_INIT_SUCCESS:初始化成功
ACTION_RET_INIT_FAIL:初始化失败

InterfaceUser

用户类插件需要实现接口 InterfaceUser,在 InterfaceUser 接口中,有如下函数:

public void login();                      //登陆
public boolean isLogined();             //获取登陆状态
public String getUserID();                //获取用户 ID(登陆成功时有效)
public boolean isSupportFunction(String paramString);   //是否支持函数名为paramString的扩展函数
public String getPluginId();             //获取插件 ID
public void setDebugMode(boolean paramBoolean);        // 设置调试模式(已废弃)
public String getSDKVersion();         //获取SDK 版本号
public String getPluginVersion();      //获取插件版本号

login()

1.登录流程描述 下载页面
1)游戏客户端调用登陆接口(向渠道平台服务器发起登录请求)
这个过程可以拆分为 3 步:1、用户调用 AnySDK 框架的 login 函数;2、AnySDK框架调用插件的 login 函数;3、插件 login 函数中调用 SDK 的登录接口。
第3步在插件客户端处理
2)用户登录成功,渠道平台服务器返回认证码 插件客户端处理:接收 SDK 登录的回调结果:如果不成功,回调失败;如果成功,进行登录验证。
3)AnySDK 框架拿着认证码向游戏服务器请求登录验证
这个过程可以拆分为 2 步:1、插件调用框架提供的函数 UserWrapper 类的 getAccessToken 方法;2、AnySDK 框架向游戏服务器发送登录验证请求。
其中,第 1 步在插件客户端处理
4)游戏服务器将认证码转发给 AnySDK 服务器
游戏服务器处理
5)AnySDK 服务器向渠道平台服务器进行用户登录验证
插件服务端处理
6)AnySDK 服务器接收验证结果
插件服务端处理
7)AnySDK 服务器将结果转发给游戏服务器
AnySDK服务端处理
8)游戏服务器通知 AnySDK 框架登录验证结果
插件客户端处理:登录验证信息会回调给调用 UserWrapper.getAccessToken 时传入的监听函数
9)AnySDK 框架回调给游戏客户端是否登陆成功
插件客户端处理:根据登录验证结果回调成功/失败
2.登陆验证
登陆验证函数定义如下:

public static void getAccessToken(Context paramContext, Hashtable<String, String> paramHashtable, SdkHttpListener paramSdkHttpListener)

参数:
paramContext:插件类生成时传入的 Context

paramHashtable:登陆验证请求的数据,必有字段为:
    1.channel:与服务端定义的通讯字段,一般为插件名。
    2.plugin_id:插件 ID
    还有用于登陆验证的字段,这些字段取决于服务端向 SDK 服务端做登陆验证需要的数据,如 token,uid 等。

paramSdkHttpListener:网络请求的监听。

酷派 SDK 的登陆验证代码如下:

public void getAccessToken(final Context context,
String authCode, final ILoginCallback listener) {

    Hashtable<String, String> info = new Hashtable<String,String>();
    info.put("plugin_id", PLUGIN_ID);
    info.put("channel", CHANNEL);
    info.put("ext1", authCode);

    LogD( "getAccessTokenParams:" + info.toString());

    UserWrapper.getAccessToken(context, info, new SdkHttpListener() {
        @Override
        public void onResponse(String response) {
            LogD("getAccessToken response:"+ response);
            try {
                JSONObject json = new JSONObject(response);
                String status = json.getString("status");
                if (status.equals("ok")) {
                    sIsLogined = true;
                    String dataString = json.getString("data");
                    dataString = removeBOM(dataString);
                    JSONObject data = new JSONObject(dataString);
                    mAccessToken = data.getString("access_token");
                    sUid = ((JSONObject) json.get("common")).getString("uid");
                    String ext = json.optString("ext");
                    ext = ext == null ? "" : ext;
                    listener.onSuccessed(UserWrapper.ACTION_RET_LOGIN_SUCCESS, ext);

                } else {
                        sIsLogined = false;
                        listener.onFailed(UserWrapper.ACTION_RET_LOGIN_FAIL, "status fail");
                    }
            } catch (JSONException e) {
                LogE("getAccessToken response error", e);
                    sIsLogined = false;
                    listener.onFailed(UserWrapper.ACTION_RET_LOGIN_FAIL, "getAccessToken response error");
            }
        }
        @Override
        public void onError() {
            sIsLogined = false;
            listener.onFailed(UserWrapper.ACTION_RET_LOGIN_FAIL, "getAccessToken onError");
          }
    });
}

3.登陆的回调
登陆的回调有三种返回值:
ACTION_RET_LOGIN_SUCCESS:登陆成功,必须是登陆验证成功后才会回调,回调消息中的 msg 为登陆验证是收到的 ext 字段的值。如酷派的登陆。
ACTION_RET_LOGIN_FAIL:登陆失败,在登陆过程中失败、出现错误的情况下,均回调登陆失败。
ACTION_RET_LOGIN_CANCEL:取消登陆,无法区分是取消还是失败时,回调失败。

isLogined()

获取登陆状态,为登陆、登陆失败、登陆取消、登出等状态下,登陆状态为 false;登陆成功后,登陆状态为 true。

getUserID()

获取用户 ID,登陆成功后才能获取到正确的值。用户 ID 是 SDK中用户的唯一标志,具体名称可能不一致,如 uID,openID 等。

isSupportFunction(String paramString)

是否支持函数名为 paramString 的扩展函数,实现方式参照模板。

getPluginId()

插件的唯一标志,多支付时判断支付方式的标识。

setDebugMode(boolean paramBoolean)

已废弃,实现方式参照模板。

getSDKVersion()

SDK 版本是指第三方 SDK 的版本号,格式可能都不一样,如 6.0、1.0.3、2.1.0.4 等,这个版本号格式不需要任何改动。

getPluginVersion()

格式『版本序号_SDK版本号』,版本序号从『2.0.0』开始,每次更新+0.0.1

扩展接口

扩展函数是对 InterfaceUser 接口的扩展,不同的 SDK 支持的扩展接口不同。目前比较通用的扩展接口如下:

public void logout();                 //登出
public void accountSwitch()           //切换账号
public void enterPlatform();          //进入平台中心
public void showToolBar(int place);   //显示悬浮工具栏
public void hideToolBar();            //隐藏悬浮工具栏
public void pause();                   //暂停游戏
public void exit();                    //退出游戏
public void submitLoginGameRole(JSONObject jsonExData);//提交游戏数据
public void realNameRegister();        //实名注册
public void antiAddictionQuery();      //防沉迷查询

logout()

登出。在该函数中调用 SDK 提供的注销登陆的接口。如果未登陆的情况下调用时会崩溃,只在登陆的情况下调用 SDK 的注销登陆接口,一般情况下不需要判断。
登出回调有两种返回值:
ACTION_RET_LOGOUT_SUCCESS:登出成功
ACTION_RET_LOGOUT_FAIL:登出失败

accountSwitch()

切换账号。在该函数中调用 SDK 提供的切换账户的接口。切换账户接口和登录接口一样,在收到 SDK 的成功回调后,需要进行登录验证,登录验证成功,切换帐号才算成功。
切换账号的回调有两种返回值:
ACTION_RET_ACCOUNTSWITCH_SUCCESS:切换账号成功,必须在登录验证成功后才会回调,回调消息中的 msg 为登录验证是收到的 ext 字段的值。
ACTION_RET_ACCOUNTSWITCH_FAIL:切换账号失败。

enterPlatform()

进入平台中心。在该函数中调用 SDK 提供的进入平台中心的接口。
登录的回调有两种返回值:
ACTION_RET_PLATFORM_ENTER:进入平台中心。
ACTION_RET_PLATFORM_BACK:从平台中返回游戏。

showToolBar()

显示悬浮工具栏。需要注意 SDK 是否要去必须登录后才能显示悬浮窗,有些 SDK 在未登录的情况下调用后,会出现悬浮窗不显示,显示出悬浮窗后点击或移动会崩溃的情况,这时,需要在 README.md 文档中的注意事项中注明。

hideToolBar()

隐藏悬浮工具栏。在悬浮窗未显示的情况下调用该函数是否有崩溃或卡死等问题,如果有,需要在 README.md 文档中的注意事项中注明。

pause()

暂停游戏。常见模式为,调用暂停接口后,弹出 SDK 的暂停界面。
当玩家关闭暂停界面,重新进入游戏时,回调 ACTION_RET_PAUSE_PAGE

exit()

退出游戏。退出游戏接口指的是,玩家主动退出游戏时,通过调用 SDK 的该接口,弹出确定退出游戏的界面,询问玩家。
当玩家确认要退出游戏时,回调 ACTION_RET_EXIT_PAGE
注意:
该接口与注销 SDK 释放资源接口的区别。注销 SDK 释放资源接口在主 ActivityonDestroy() 回调中调用。

submitLoginGameRole(JSONObject jsonExData)

提交游戏数据。从用户传入的数据,选择需要的数据并转换为相应的格式后,调用提交数据接口。
用户传入的数据如下:

参数 是否必传 参数说明
roleId Y 角色ID
roleName Y 角色名称
roleLevel Y 角色等级
zoneId Y 服务器ID
zoneName Y 服务器名称
dataType Y 数据类型,1 为进入游戏,2 为创建角色
ext Y 扩展字段

以 OPPO 为例,其代码如下:

public void submitLoginGameRole(final JSONObject jsonExData) {
    PluginWrapper.runOnMainThread(new Runnable() {
        @Override
        public void run() {
            String extendInfo = new StringBuilder()
            .append("gameId=").append(OPPOWrapper.getInstance().getOPPOGameId())
            .append("&service=").append(jsonExData.optString("zoneName"))
            .append("&role=").append(jsonExData.optString("roleName"))
            .append("&grade=").append(jsonExData.optString("roleLevel")).toString();
            GameCenterSDK.getInstance().doSubmitExtendInfo(new ApiCallback() {
                @Override
                public void onSuccess(String content, int code) {
                    LogD("submitGameRole success");
                }

                @Override
                public void onFailure(String content, int code) {
                    LogD("submitGameRole faied");
                }
            },extendInfo,mActivity);
        }
    });
}

realNameRegister()

实名认证。调用 SDK 提供的实名认证接口。实名认证完成后回调 ACTION_RET_REALNAMEREGISTER
以 360 为例,其代码如下:

public void realNameRegister() {
    if (!isLogined()) {
        login();
        return;
    }
    PluginWrapper.runOnMainThread(new Runnable() {
        @Override
        public void run() {
            Intent intent = getRealNameRegisterIntent(QH360Wrapper.getInstance().isLandscape(), true, QH360Wrapper.getInstance().getUserID());
            Matrix.invokeActivity(mContext, intent, new IDispatcherCallback() {
                @Override
                public void onFinished(String arg0) {
                    actionResult(UserWrapper.ACTION_RET_REALNAMEREGISTER, arg0);
                }
            });
        }
    });
}

antiAddictionQuery()

防沉迷查询。调用 SDK 提供的防沉迷接口。实名认证完成后回调 ACTION_RET_ANTIADDICTIONQUERY
以 360 为例,其代码如下:

public void antiAddictionQuery() {
    if (!isLogined()) {
        login();
        return;
    }
    PluginWrapper.runOnMainThread(new Runnable() {
        @Override
        public void run() {
            Intent intent = getAntiAddictionIntent(QH360Wrapper.getInstance().getUserID(), QH360Wrapper.getInstance().getmToken());
            Matrix.execute(mContext, intent, new IDispatcherCallback() {
                @Override
                public void onFinished(String data) {
                    actionResult( UserWrapper.ACTION_RET_ANTIADDICTIONQUERY, data);
                }
            });
        }
    });
}

【评论区】