# 修订记录

|	日期 	|	版本	|	说明	|	 作者	|
| :--: | :--: | :-- | :--: |
|	2021-07-09	|	1.0.0	|	文档建立	| 麦锦培 |


# 1.接入前检查

- 游戏资源文件名、布局名、布局id名等建议使用规范命名，避免和SDK资源冲突
- Android Studio 3.0及以上，由于谷歌服务一系列SDK已不提供jar包形式，因此SDK不提供jar包形式以eclipse接入
- Android Gradle Plugin Version : 4.1.3+
- Gradle Version : 6.5+
- Android Studio开启Android X支持，请在游戏项目根目录的**`gradle.properties`**中设置
```properties
android.useAndroidX=true
android.enableJetifier=true
```

- 请务必使用我们提供的keystore签名文件进行签名，否则SDK功能会异常


# 2.SDK资源接入说明

- 1.接入中存在问题请参考SDK提供的Demo工程或联系技术解决
- 2.拷贝SDK目录下**`assets/yyxx_game`**至项目中
- 3.拷贝SDK目录下**`res/values/strings.xml`**中的内容至项目中相应的文档中，如果没有strings.xml则新建一份即可
- 4.在应用**`build.gradle`**中**`dependencies`**节点下添加SDK依赖，目前只提供远程依赖，需要离线aar包请联系我方技术
> 在项目级**`build.gradle`**文件下的**`allprojects`**节点下添加仓库的url
```groovy
	allprojects {
		repositories {
			...
			mavenCentral()
			...
		}
	}
```

> 在应用级**`build.gradle`**文件下的**`allprojects`**节点下添加仓库的url
```groovy
	implementation 'io.github.yyxxgame.sdk:eyuangame-sdk-ktx:1.0.0'
```


# 3.接口说明

> <font color=red size=5>**SDK的所有接口如无特殊说明，默认均为必接且请务必在游戏主线程调用**</font>

## 1）同步Application中的生命周期

- 若游戏无自定义Application则直接在清单文件AndroidManifest.xml的**``application``**节点中设置name属性为SDK提供的Application**``cn.yyxx.eyuangame.base.EYuanGameApplication``**

```xml
  <application android:name="cn.yyxx.eyuangame.base.EYuanGameApplication">
    ···
  </application>
```

- 若游戏有自定义Application，则需要继承SDK提供的Application

```java
	public class DemoApplication extends EYuanGameApplication {
		@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();
		EYuanGame.getInstance().onStart(this);
	}
```

- 同步onResume

```java
	@Override
	protected void onResume() {
		super.onResume();
    EYuanGame.getInstance().onResume(this);
	}
```

- 同步onRestart

```java
	@Override
	protected void onRestart() {
		super.onRestart();
		EYuanGame.getInstance().onReStart(this);
	}
```

- 同步onPause

```java
	@Override
	protected void onPause() {
		super.onPause();
		EYuanGame.getInstance().onPause(this);
	}
```

- 同步onStop

```java
	@Override
	protected void onStop() {
		super.onStop();
		EYuanGame.getInstance().onStop(this);
	}
```

- 同步onDestroy

```java
	@Override
	protected void onDestroy() {
		super.onDestroy();
		EYuanGame.getInstance().onDestroy(this);
	}
```

- 同步onActivityResult

```java
	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		EYuanGame.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){
		EYuanGame.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
	EYuanGame.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
	EYuanGame.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)

	//角色创建
	EYuanGame.getInstance().roleCreate(this, gameRoleInfo);

	//角色登录
	EYuanGame.getInstance().roleLauncher(this, gameRoleInfo;

	//角色升级
	EYuanGame.getInstance().roleUpgrade(this, gameRoleInfo;
```


## 8）支付储值

> 请务必保证调用角色信息上报中的角色登录上报后再调用
> <font color=red size=5>**客户端SDK回调的只是支付流程的结果，实际支付结果将由服务端回调**</font>
> 默认情况均为内购包即上架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回调的只是支付流程的结果，实际支付结果将由服务端回调
	EYuanGame.getInstance().charge(this, gameChargeInfo, true , new ICallback() {
		@Override
			public void onResult(int code, String result) {
				if (code == 0) {
					//TODO 支付流程完成
				} else {
					//TODO 支付失败
				}
			}
	});
```


## 9）SDK游戏打点上报（按需接入）

SDK埋点事件信息实体对象SdkEvent

|	参数 	|	类型	|	说明	|
| :--: | :--: | :--: |
|	eventName	|	string	|	事件名称	|
|	standard	|	bool	|	是否fb标准事件	|
|	fbAliasName	|	string	|	fb标准事件名称，非标准事件则为""	|

```java
	/**
	 * 游戏内打点上报
	 *
	 * @param context Aontext上下文
	 * @param sdkEvent SDK埋点事件信息实体对象
	 */
	public void linkingEvent(Context context, SdkEvent sdkEvent)
```

- 示例

```java
	//fb标准事件
	SdkEvent sdkEvent = new SdkEvent();
	sdkEvent.setEventName("tutorial");
	sdkEvent.setStandard(true);
	sdkEvent.setFbAliasName("fb_mobile_tutorial_completion");
	EYuanGame.getInstance().linkingEvent(this, sdkEvent);

	//fb非标准事件
	SdkEvent sdkEvent = new SdkEvent();
	sdkEvent.setEventName("finish_marry");
	sdkEvent.setStandard(false);
	sdkEvent.setFbAliasName("");
	EYuanGame.getInstance().linkingEvent(this, sdkEvent);
```


## 10）显示SDK退出框（选接）

> 用户（玩家）按下返回键时调用，接入方需要实现Activity的onKeyDown，并判断keyCode为KeyEvent.KEYCODE_BACK时调用该接口

```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) {
			EYuanGame.getInstance().openExitView(this, new ICallback() {
				@Override
				public void onResult(int code, String result) {
					if (code == 0) {
						//结束当前Activity
						//如果要杀进程需要在onDestroy中处理，不然会不执行SDK的onDestroy方法
						finish();
					}
				}
			});
			return true;
		}
		return super.onKeyDown(keyCode, event);
	}

	@Override
	protected void onDestroy() {
		super.onDestroy();
		EYuanGame.getInstance().onDestroy(this);
		//结束当前应用进程
		System.exit(0);
	}
```


## 11）获取SDK当前用户ID（选接）

```java
	/**
	 * 获取当前SDK版本
	 *
	 * @return
	 */
	public String getCurrentUserId()
```

- 示例

```java
	EYuanGame.getInstance().getCurrentUserId();
```


## 12）获取SDK当前版本（选接）

```java
	/**
	 * 获取当前SDK版本
	 *
	 * @return
	 */
	public String getCurrentSdkVersion()
```

- 示例

```java
	FlyFunGame.getInstance().getCurrentSdkVersion();
```