[TOC]
# 修订记录
| 日期 | 版本 | 说明 | 作者 |
|:----------:|:-----:|:---- |:---:|
| 2022-02-28 | 1.0.0 | 文档建立 | 麦锦培 |
# 1.接入前检查
- 游戏资源文件名、布局名、布局id名等建议使用规范命名,避免和SDK资源冲突
- Android Studio 3.0及以上,由于谷歌服务一系列SDK已不提供jar包形式,因此SDK不提供jar包形式以eclipse接入
- Android Gradle Plugin Version : 7.0.2+
- Gradle Version : 7.0.2+
- Android Studio开启Android X支持,请在游戏项目根目录的**`gradle.properties`**中设置
```properties
android.useAndroidX=true
android.enableJetifier=true
```
- 请务必使用我们提供的keystore签名文件进行签名,否则SDK功能会异常
- [服务端接口文档](http://yydocs.yyxxgame.com/web/#/147/892)
- [客户端SDK接入Demo](http://gogs.yyxxgame.com/Client/EYuanCommSdkDemo)
# 2.SDK资源接入说明
- 1.接入中存在问题请参考SDK提供的Demo工程或联系技术解决
- 2.拷贝对应渠道目录下**`assets`**至项目中
- 3.拷贝对应渠道目录下**`res/values/strings.xml`**中的内容至项目中相应的文档中,如果没有strings.xml则新建一份即可,如果该目录没有则不需要处理
- 4.在应用**`build.gradle`**中**`dependencies`**节点下添加SDK依赖,目前只提供远程依赖
> 在项目级**`build.gradle`**文件下的**`allprojects`**节点下添加仓库的url
```groovy
allprojects {
repositories {
...
mavenCentral()
// 华为sdk仓库
maven { url 'https://developer.huawei.com/repo' }
...
}
}
```
> 在应用级**`build.gradle`**文件下的**`allprojects`**节点下添加仓库的url
```groovy
implementation 'io.github.yyxxgame.sdk:eyuancomm-sdk-ktx-comm:1.0.0-rc3'
implementation 'io.github.yyxxgame.sdk:eyuancomm-sdk-ktx-impl:1.0.0-rc3'
// 以下sdk依赖在生成对应包时按需引入,为了避免资源冲突请不要同时引入
implementation 'io.github.yyxxgame.sdk:eyuancomm-channel-lib-huawei:1.0.0-rc3'
implementation 'io.github.yyxxgame.sdk:eyuancomm-channel-lib-oppo:1.0.0-rc3'
```
# 3.接口说明
> **SDK的所有接口如无特殊说明,默认均为必接且请务必在游戏主线程调用**
## 1)同步Application中的生命周期
- 若游戏无自定义Application则直接在清单文件AndroidManifest.xml的**``application``**节点中设置name属性为SDK提供的Application**``cn.yyxx.eyuangame.base.EYuanCommApplication``**
```xml
···
```
- 若游戏有自定义Application,则需要继承SDK提供的Application
```java
public class DemoApplication extends EYuanCommApplication {
@Override
protected void attachBaseContext(Context base) {
super.attachBaseContext(base);
}
@Override
public void onCreate() {
super.onCreate();
}
}
```
## 2)同步游戏Activity中各个生命周期至SDK
- 同步onStart
```java
@Override
protected void onStart() {
super.onStart();
EYuanCommSdk.getInstance().onStart(this);
}
```
- 同步onResume
```java
@Override
protected void onResume() {
super.onResume();
EYuanCommSdk.getInstance().onResume(this);
}
```
- 同步onRestart
```java
@Override
protected void onRestart() {
super.onRestart();
EYuanCommSdk.getInstance().onReStart(this);
}
```
- 同步onPause
```java
@Override
protected void onPause() {
super.onPause();
EYuanCommSdk.getInstance().onPause(this);
}
```
- 同步onStop
```java
@Override
protected void onStop() {
super.onStop();
EYuanCommSdk.getInstance().onStop(this);
}
```
- 同步onDestroy
```java
@Override
protected void onDestroy() {
super.onDestroy();
EYuanCommSdk.getInstance().onDestroy(this);
}
```
- 同步onActivityResult
```java
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
EYuanCommSdk.getInstance().onActivityResult(this, requestCode, requestCode, data);
}
```
- 同步onNewIntent
```java
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
EYuanGame.getInstance().onNewIntent(this, intent);
}
```
## 3)SDK通用回调接口ICallback说明
```java
public interface ICallback {
void onResult(int code, String result);
}
```
| 参数 | 类型 | 说明 |
|:------:|:------:|:-------------:|
| code | int | 状态码(0成功,-1失败) |
| result | string | 返回信息 |
## 4)SDK初始化
- 在游戏的主Activity的onCreate中调用
```java
/**
* SDK初始化
*
* @param activity Activity上下文
* @param isLandscape 是否横屏
* @param callback SDK初始化回调
*/
public void initialize(final Activity activity, final Boolean isLandscape, ICallback callback)
```
- 示例
```java
@Override
protected void onCreate(Bundle savedInstanceState){
EYuanCommSdk.getInstance().initialize(this, false, new ICallback() {
@Override
public void onResult(int code, String result) {
if (code == 0) {
//TODO SDK初始化成功
} else {
//TODO SDK初始化失败,result是失败的debug信息
}
}
});
}
```
## 5)用户账号登录
```java
/**
* SDK用户登录
*
* @param activity Activity上下文
* @param isAuto 是否自动登录
* @param callback 登录回调对象
*/
public void login(Activity activity, Boolean isAuto, ICallback callback)
```
**登录回调返回的result信息**
| 参数 | 类型 | 说明 |
|:------:|:------:|:--------:|
| userId | string | SDK的用户ID |
| token | string | 签名token |
- 示例
```java
EYuanCommSdk.getInstance().login(DemoActivity.this, true, new ICallback(){
@Override
public void onResult(int code, String result) {
if (code == 0) {
//TODO 对SDK返回的用户信息进行验签
//result返回的是JSON字符串,可以得到uid和token等信息
//签名规则详见服务端接入文档
} else {
//TODO 登录失败,result是返回的debug信息
}
}
});
```
## 6)用户账号登出
> 用户在游戏中触发登出,游戏回到选服界面重新拉起登录
```java
/**
* SDK用户登出账号
*
* @param activity Activity上下文
* @param callback 登出回调对象
*/
public void logout(Activity activity, ICallback callback)
```
- 示例
```java
EYuanCommSdk.getInstance().logout(this, new ICallback() {
@Override
public void onResult(int code, String result) {
if (code == 0) {
//TODO 用户登出成功,登出成功后请返回游戏选服界面,然后拉起登录框,如果调用登录接口,请设置为非自动登录
} else {
//TODO 用户登出失败,result是返回的debug信息
}
}
}
```
## 7)角色信息上报
> 请务必根据当前角色的触发的事件进行上报
角色信息实体对象SdkRoleInfo,如无特别说明所有字段均不能为null或空串""
| 参数 | 类型 | 说明 |
|:-------------:|:------:|:---------------------------:|
| userId | string | 当前用户ID |
| serverId | string | 当前角色所在的服务器ID |
| serverName | string | 当前角色所在的服务器名 |
| roleId | string | 当前角色ID |
| roleName | string | 当前角色名 |
| roleLevel | string | 当前角色等级 |
| roleCTime | long | 当前角色创建的时间戳(10位),角色一旦创建则是固定值 |
| vipLevel | string | 当前Vip角色等级,若无传"none" |
| balance | string | 当前角色游戏币余额,若无传"none" |
| totalPurchase | int | 累计充值金额,若无传0) |
> 角色创建
```java
/**
* SDK角色创建信息上报
*
* @param activity Activity上下文
* @param roleInfo 角色信息实体
*/
public void roleCreate(Activity activity, SdkRoleInfo roleInfo)
```
> 角色进入服务器(角色登录)
```java
/**
* SDK角色登录信息上报
*
* @param activity Activity上下文
* @param roleInfo 角色信息实体
*/
public void roleLauncher(Activity activity, SdkRoleInfo roleInfo)
```
> 角色升级
```java
/**
* SDK角色升级信息上报
*
* @param activity Activity上下文
* @param roleInfo 角色信息实体
*/
public void roleUpgrade(Activity activity, SdkRoleInfo roleInfo)
```
- 示例
```java
SdkRoleInfo gameRoleInfo = new SdkRoleInfo();
//用户ID
gameRoleInfo.setUserId(EYuanGame.getInstance().getCurrentUserId());
//角色ID
gameRoleInfo.setRoleId(roleId);
//角色名称
gameRoleInfo.setRoleName(roleName);
//角色等级
gameRoleInfo.setRoleLevel(roleLevel);
//创角时间戳(角色一旦创角则是固定值)
gameRoleInfo.setRoleCTime(System.currentTimeMillis()/1000)
//服务器ID
gameRoleInfo.setServerId(serverId);
//服务器名
gameRoleInfo.setServerName(serverName);
//用户VIP等级,无该字段则传空串""
gameRoleInfo.setVipLevel("1");
//当前角色游戏币余额
gameRoleInfo.setBalance("600");
//累计充值金额,若无传0)
gameRoleInfo.setTotalPurchase(0)
//角色创建
EYuanCommSdk.getInstance().roleCreate(this, gameRoleInfo);
//角色登录
EYuanCommSdk.getInstance().roleLauncher(this, gameRoleInfo;
//角色升级
EYuanCommSdk.getInstance().roleUpgrade(this, gameRoleInfo;
```
## 8)支付储值
> 请务必保证调用角色信息上报中的角色登录上报后再调用
> **客户端SDK回调的只是支付流程的结果,实际支付结果将由服务端回调**
> 默认情况均为内购包即上架Google Play,具体情况请根据运营需求接入
支付信息实体对象SdkChargeInfo,如无特别说明所有字段均不能为null或空串""
| 参数 | 类型 | 说明 |
|:-----------:|:------:|:--------------------:|
| userId | string | 当前用户ID |
| serverCode | string | 当前角色所在的服务器ID |
| serverName | string | 当前角色所在的服务器名 |
| roleId | string | 当前角色ID |
| roleName | string | 当前角色名 |
| roleLevel | string | 当前角色等级 |
| amount | int | 金额,单位分,币种固定为币种美金 |
| productId | string | 商品ID |
| productName | string | 商品名称 |
| productDesc | string | 商品描述 |
| cpOrderId | string | 游戏订单号 |
| cpExt | string | 游戏透传信息,最终会元游返回,可为空 |
| cpPayTime | long | 下单时间,10位Unix时间戳 |
| cpPaySign | string | 支付签名,具体签名规则详见服务端接口文档 |
```java
/**
* SDK用户支付
*
* @param activity Activity上下文
* @param chargeInfo 支付信息实体对象
* @param isIab 是否内购
* @param callback 支付回调对象
*/
public void charge(Activity activity, SdkChargeInfo chargeInfo, boolean isIab , ICallback callback)
```
- 示例
```java
long ts = System.currentTimeMillis();
SdkChargeInfo gameChargeInfo = new SdkChargeInfo();
//用户ID
gameChargeInfo.setUserId(EYuanGame.getInstance().getCurrentUserId());
//角色ID
gameChargeInfo.setRoleId(roleId);
//角色名称
gameChargeInfo.setRoleName(roleName);
//角色等级
gameChargeInfo.setRoleLevel(roleLevel);
//创角时间戳(角色一旦创建则是固定值)
gameChargeInfo.setRoleCTime(创角时间戳(角色一旦创建则是固定值));
//服务器ID
gameChargeInfo.setServerId(serverId);
//服务器名
gameChargeInfo.setServerName(serverName);
//游戏的订单号
gameChargeInfo.setCpOrderId(orderId);
//透传字段,会在服务端回调中原样返回
gameChargeInfo.setCpExt("cp_callback_info||" + orderId);
//金额,单位分,币种美金
gameChargeInfo.setAmount(99);
//商品ID,计费点
gameChargeInfo.setProductId("com.shzd.1usd");
//商品名称
gameChargeInfo.setProductName("60元宝");
//商品描述
gameChargeInfo.setProductDesc("60元宝");
//下单时间
gameChargeInfo.setCpPayTime(payTs)
//支付签名
gameChargeInfo.setCpPaySign("支付签名,具体签名规则详见服务端接口文档")
//客户端SDK回调的只是支付流程的结果,实际支付结果将由服务端回调
EYuanCommSdk.getInstance().charge(this, gameChargeInfo, true , new ICallback() {
@Override
public void onResult(int code, String result) {
if (code == 0) {
//TODO 支付流程完成
} else {
//TODO 支付失败
}
}
});
```
## 9)显示SDK退出框
> 用户(玩家)按下返回键时调用,接入方需要实现Activity的onKeyDown,并判断keyCode为KeyEvent.KEYCODE_BACK时调用该接口
> 调用退出框前,请先调用hasExitView()判断是否有渠道退出框,如果返回false则显示游戏原生退出框即可
```java
/**
* 显示退出框
*
* @param activity Activity上下文
* @param callback 退出回调对象
*/
public boolean hasExitView(Activity activity)
```
```java
/**
* 显示退出框
*
* @param activity Activity上下文
* @param callback 退出回调对象
*/
public void openExitView(Activity activity, ICallback callback)
```
- 示例
```java
//重写Activity的onKeyDown并判断KeyDown事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if (keyCode == KeyEvent.KEYCODE_BACK) {
if (EYuanCommSdk.getInstance().hasExitView(this)) {
EYuanCommSdk.getInstance().openExitView(this, new ICallback() {
@Override
public void onResult(int code, String result) {
if (code == 0) {
// 结束当前Activity
// 如果要杀进程需要在onDestroy中处理,不然会不执行SDK的onDestroy方法
finish();
}
}
});
}else {
// 显示游戏原生退出框
}
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
protected void onDestroy() {
super.onDestroy();
EYuanCommSdk.getInstance().onDestroy(this);
//结束当前应用进程
System.exit(0);
}
```
## 10)设置SDK浮标切换用户监听
> 在SDK初始化成功后设置浮标切换用户监听
```java
/**
* 设置SDK浮标切换用户监听
*
* @param callback 切换用户回调对象
*/
public void setOnFloatBallLogout(ICallback callback)
```
- 示例
```java
EYuanCommSdk.getInstance().initialize(this, true, new ICallback() {
@Override
public void onResult(int code, @NonNull String result) {
if (code == 0) {
// SDK初始化成功设置浮标切换用户监听
EYuanCommSdk.getInstance().setOnFloatBallLogout(new ICallback() {
@Override
public void onResult(int code2, @NonNull String result2) {
if (code2 == 0) {
// 用户触发浮标切换账号,游戏需退回到登录选服页,并调用SDK的login()接口拉起登录
} else {
// 预留,暂时无需处理
}
}
});
}
}
});
```
## 11)获取SDK当前用户ID(选接)
```java
/**
* 获取当前SDK版本
*
* @return
*/
public String getCurrentUserId()
```
- 示例
```java
EYuanCommSdk.getInstance().getCurrentUserId();
```
## 12)获取SDK当前版本(选接)
```java
/**
* 获取当前SDK版本
*
* @return
*/
public String getCurrentSdkVersion()
```
- 示例
```java
EYuanCommSdk.getInstance().getCurrentSdkVersion();
```
## 13)SDK日志接口(选接)
> 若游戏有需要持久化java、kotlin和C++(联系我方技术获取头文件)层的日志,可以使用SDK的日志接口。SDK的日志框架底层使用C++进行开发,使用了Linux系统的mmap内存拷贝技术
> SDK会默认缓存3天的日志,过期则自动删除
> 缓存的文件使用Facebook开源的压缩算法zlib进行压缩
> 缓存路径为**手机内部存储目录/Android/data/包名/files/dolin/zap**,即应用的私有目录
> 更多使用方法请联系我方技术
```java
// debug日志
Logger.d(TAG,msg);
// info日志
Logger.i(TAG,msg);
// error日志
Logger.e(TAG,msg);
```