API集成

集成指引

SDK基础的API有 Application初始化 Activity初始化 闪屏 登录/退出登录 支付 游戏角色上报 用户触发退出游戏逻辑 . 可参考demo进行接入。此外还需要注册 全局事件回调,在收到事件时及时做出相应处理。

Application初始化

SDK初始化过程需要在Application中完成。初始化可以使用 快速初始化 非入侵初始化 其中的一种进行接入。

快速初始化

使用非入侵初始化请忽略这个小节

  • 若无特殊逻辑需要处理,可在 AndroidMainfest.xml 中Applicaiton节点指定为SDK提供的的 BaseApplication

AndroidMainfest.xml

<!-- 直接指定name为SDK的BaseApplication -->
<application
  android:name="com.netease.yofun.external.BaseApplication"
  >
</application>

非入侵初始化

使用快速初始化请忽略这个小节

  • 若有自己的Applicaiton且要在其中处理一些特殊逻辑,那么可以使用非入侵的方式接入:即用自己的Applicaiton来继承SDK提供的的 BaseApplication

YourCustomApplication.java

public class YourCustomApplication extends BaseApplication {

  @Override
  public void onCreate() {
      super.onCreate();
      // do something
  }

}
  • 若这个Application不能修改继承关系,也可以在自己的 Application 中重写 attachBaseContext()onCreate() 方法,并在其中加入SDK的初始化代码:

YourCustomApplication.java

public class YourCustomApplication extends Application {
  @Override
  protected void attachBaseContext(Context base) {
      super.attachBaseContext(base);
      //SDK的初始化代码
      MultiDex.install(base);
      Api.getInstance().applicationAttach(this);
  }
  @Override
  public void onCreate() {
      super.onCreate();
      //SDK的初始化代码
      Api.getInstance().applicationCreate(this);
  }
}

Important

这里MultiDex.install 是必须的。

Activity初始化

init方法一是初始化sdk;二时检查用户是否同意隐私协议,不同意隐私协议时,会回调onQuit(true),通知游戏退出应用。

请在游戏的主Activity中调用init方法,如下:

// 初始化结果
Api.getInstance().register(mAction = new HubActionAdapter() {

      @Override
      public void onInit(int code, String msg) {
          Toast.makeText(MainActivity.this,
                  (code == HubCode.Init.OK) ? "已完成初始化" : "初始化失败#" + code + msg,
                  Toast.LENGTH_SHORT).show();
      }

      @Override
      public void onQuit(boolean realQuit) {
          if (realQuit) {
              if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
                  finishAndRemoveTask();
              }
              android.os.Process.killProcess(android.os.Process.myPid());
          }
      }
});

// 调用初始化
Api.getInstance().init(this);

闪屏要求

闪屏是 必须要接入的 SDK提供了几种闪屏的方法可以尝试接入,择一接入即可:

// 方法1
// SDK内置了3中类型实现的闪屏(0,1,2)可以自测效果选择调用。
Api.getInstance().displayChannelLogo(this, 0, null);

// 方法2
// 在启动的时候显示一个白底的MUMU的logo,logo xhdpi资源在:
// test/common-resource/netease_yofun_splash_logo.png

应用角标规范

SDK要求游戏图标必须要有圆角,规范:

对512x512的图标,SDK要求游戏图标的圆角半径必须为 64px ,即图标的四个角都是圆角,且圆角半径为 64px

请注意处理应用角标,角标资源在: test/common-resource/ic_launcher_cover

快速接入角标

全局事件回调

1. 全局事件监听

SDK提供全局的事件回调,可在游戏主界面注册监听,接入示例:

//To handle action result
mAction = new HubActionAdapter() {

    @Override
    public void onLogin(int code, String msg, UserInfo info) {
        // 请处理登录事件
        println("onLogin", (code == HubCode.OK ? info.toString() : "fail:" + code));
    }

    @Override
    public void onPay(int code, String msg, PayInfo info) {
        // 请处理支付的结果
        println("onPay", (code == HubCode.OK ? info.toString() : "fail:" + code));
    }

    @Override
    public void onLogout(int code) {
        // 请处理账户登出事件
        println("onLogout", "called");
    }

    @Override
    public void onQuit(boolean realQuit) {
        // 请处理关闭游戏的逻辑
        println("onQuit", realQuit);
        if (realQuit) finish();

        // 1.[重要]如果需要退出当前应用进程的话,需要清除当前应用中所有的Activity,
        //即调用所有activity的finish;[建议]: 在baseActivity中维护管理当前没有被销毁的activity,
        //当我们想要退出当前进程的时候,可以通过baseActivity去遍历、销毁Activity。
        // 2.如果当前的进程中所有的activity都销毁掉了,调用退出进程接口
        // android.os.Process.killProcess(android.os.Process.myPid())


        // 也可参考如下方式:
        // if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) {
        //    //比较强力的退出方式 只在api21以上有效
        //    ActivityManager am = (ActivityManager) getActivity().getSystemService(Context.ACTIVITY_SERVICE);
        //    if (null != am) {
        //        List<ActivityManager.AppTask> appTasks = am.getAppTasks();
        //        for (ActivityManager.AppTask task : appTasks) {
        //                task.finishAndRemoveTask();
        //        }
        //    }
        // }
        // //该方法只针对栈中只有一个Activity时有效
        // System.exit(0);
    }
};
Api.getInstance().register(mAction);

Warning

onLogout(int code)回调方法的触发时机有:登出接口

所以请注意:

  1. 此时SDK账号已经登出了,所以不要在此处重复调用SDK的登出接口
  2. 强制踢下线的场景包括防沉迷等,所以务必确保游戏在任何时期都能有效响应回调方法并做游戏内的登出处理

Tip

注意处理onLogin(),onLogout()回调用的时序问题。

时序问题出现的场景可能是:

  1. 游戏在调用了登录接口后,在收到onLogin()回调时,会先在自己的服务器上做登录校验,校验成功后才会正式进入游戏。
  2. 如果在此次服务端的登录校验完成之前,SDK先触发了onLogout()回调,此时游戏在收到onLogout()回调后没有正确处理登出事件,而是一直在等待自己服务端的登录校验结果,直到这个登录校验完成,之后直接进入了游戏。
  3. 此时用户明明已被SDK踢下线——表现为SDK悬浮球已消失——但用户还能正常进入游戏。

2. 主动释放回调注册

注意不要随便释放回调,一旦释放,所有的回调均将接收不到,所以请确保完全没用时(比如游戏完全退出)再释放回调。

if (mAction != null) Api.getInstance().unregister(mAction);

3. 按需使用初始化回调

初始化相关回调有两个: onInit() 具体使用场景已在前文说明。
mAction = new HubActionAdapter() {

    @Override
    public void onInit(int code, String msg) {
        //初始化成功回调
        println("onInit", (code == HubCode.OK ? " success " : " fail: " + code));
    }

};

4. 接口中的参数含义

类型 参数一 参数二 参数三
onLogin 登录返回码 错误提示 用户信息
onPay 支付返回码 错误提示 支付信息
onLogout 登出返回码

5. 回调的触发时机

回调事件基本都是与API接口对应的,一些特殊情况可以参考demo 接入示例项目 ,在demo中右侧会按时间顺序打印出当前触发的回调。

登录/退出登录

Api.getInstance().login(Activity);
Api.getInstance().logout(Activity);

注意点:登录是异步操作,登录操作的结果在 全局回调 中 onLogin/onLogout 返回;

用户触发退出游戏逻辑

Api.getInstance().quit(Activity);

注意点:退出游戏是异步操作,操作的结果在 全局回调 中 onQuit 返回。

Important

注意,游戏在收到关闭游戏的回调后的处理,需要根据自己实际情况和需求来实现关闭游戏的代码逻辑,比如杀死进程或退出Activity等。

如果在关闭游戏时发生异常,请先自查自己关闭游戏的方式,因为此时已经跟SDK无关,只是单纯的Android系统API调用,demo中也只是一个示例,不同Android平台不保证完全可行。

支付

PayInfo info = new PayInfo();
info.setGameOrderId("hub_test_" + System.currentTimeMillis()); //游戏订单id
info.setGoodsId("product_01"); //商品-id
info.setGoodsName("一堆钻石");  //商品-名称
info.setGoodsCount(1);         //商品-数量
info.setGoodsPrice(price);     //商品-价格单价
info.setOrderPrice(price);     //订单-金额-单位分(或其它货币最小单位)
info.setActualPrice(price);    //订单-实际支付金额-单位分(或其它货币最小单位)
info.setCurrency("CNY");    //订单-货币类型三位大写字母(如CNY)
// 游戏支付回调接口地址
info.setNotifyUrl("https://sdkhub-test.webapp.163.com/api/v1/test/notify/aebfw63ihmaaaaab");
try {
    // 举个例子,不一定必须是json
    // reserveInfo to game-server
    JSONObject reserveInfo = new JSONObject();
    reserveInfo.put("key1", "value1");
    reserveInfo.put("key2", "value2");
    reserveInfo.put("key3", "value3");
    info.setReserved(reserveInfo.toString()); // 回传字段,回调通知时原样回传给游戏
} catch (Exception e) {/*ignore it*/}
Api.getInstance().pay(this, info);

注意:价格单位是 (或其它货币最小单位)

注意点:

  1. 支付是异步操作,支付操作的结果在 全局回调 中 onPay 返回;
  2. 支付参数的详细信息见 支付信息;
  3. 支付失败时,请结合demo检查支付接口传入的所有参数,确保参数数量、类似等都正确。

Important

游戏的支付回调是要自己配置在客户端的!

游戏角色上报

请在游戏发生对应的角色事件后,上报对应的游戏角色事件。

目前需要上报的事件类型有:角色创建成功、角色登录成功。

根据不同的事件类型选择对应的 GameEventType,并通过 uploadGameEventInfo() 进行上报。

GameEventInfo gameEventInfo = new GameEventInfo.GameEventInfoBuilder();
// 必传
gameEventInfo.roleId("789"); // 角色id
gameEventInfo.roleName("John");  // 角色名称
gameEventInfo.serverId("server1");  //  区服id
gameEventInfo.serverName("My Server");  // 区服名字

// 可选
gameEventInfo.eventType(GameEventType.LOGIN_SUCCESS);  // 角色事件类型
gameEventInfo.roleLevel(42);  //  角色等级
gameEventInfo.roleType("Warrior");  // 角色职业、类型
gameEventInfo.partyName("My Party");  // 工会名称
gameEventInfo.powerNum(1000);  // 战力数值
gameEventInfo.gameVipLevel(5);  // 游戏vip等级
gameEventInfo.gameMoney(5000);  // 游戏货币数量

Api.getInstance().uploadGameEventInfo(this, gameEventInfo.build());

注意点:

  1. GameEventType 代表上报的角色事件类型,目前共有两种取值。其中,LOGIN_SUCCESS 代表游戏角色的登录成功事件,ROLE_CREATE_SUCCESS 代表游戏角色的创建成功事件。请分别在对应场景下进行上报;
  2. 参数的详细信息见 角色数据

测试模式

网易Yofun 允许在测试中查看日志信息,在正式发版时,请勿打开测试模式!

Api.getInstance().setDebugMode(BuildConfig.DEBUG);

网易Yofun 附加信息

网易Yofun 会缓存部分全局参数

Api.getInstance().getInfo().copy()

详细内容见 ApiInfo ,请勿修改 getInfo() 的内容。