# 客户端接入指南 --- 本文档面向 Android 开发者,描述的接入方式适合运营在 4399 平台的普通单机游戏。 ## SDK 下载 SDK和相关示例的下载地址可在游戏创建后,进入 **「游戏管理-SDK服务」** 页面获取。 image ## SDK 说明 ### 用户信息与隐私策略

注意

如果您是开发者,在为用户提供服务前请阅读 《4399通行证用户服务协议》《隐私政策》,了解SDK对个人信息收集范围、处理目的以及权限使用情况。请您向用户提供服务时,告知相关信息并取得用户同意。

如果您是用户,请在使用我们的服务前阅读 《4399通行证用户服务协议》《隐私政策》,了解SDK对个人信息收集范围、处理目的以及权限使用情况。充分理解后再开始使用我们的服务。

### 功能描述 4399 运营 SDK,为单机类游戏提供防沉迷、数据统计、增量更新、有服务器/无服务器充值等功能 ### SDK 组成 #### 客户端 SDK SDK 优先提供在线`aar`依赖方式,Demo 结构遵循 Android Studio(as) 规范,但仍然保留了 `jar+res` 的依赖方式。 SDK 支持的编译配置 **android:minSdkVersion >= 16**。 #### 服务端 API 需要充值服务端回调,参考 [SDK 服务端接入文档](https://sdkftp.4399doc.com/external/operate/3.14/server_api_1.html) ## 集成流程 ### 准备 首次接入 SDK,要在 [4399 开放平台](https://open.4399.cn/) 注册应用,主要是提交APK、素材,配置游戏币、充值回调地址等信息。 完成后,开发者将得到 SDK 的基础参数:`game key`或`GameKey`,游戏在 4399 平台的运营标识(开发者平台的游戏信息页面显示为“游戏ID”) ### 引入依赖 根据游戏需要,以下三种方式可选其一 - *在线aar* 若使用*在线aar*,开发者只要在使用 SDK 的 module 的 `build.gradle`中引入以下内容即可 ```groovy repositories { maven { // 4399 SDK 开放仓库:正式 url 'https://mvn.4399doc.com/repository/maven-releases' } maven { // 4399 SDK 开放仓库:快照 url 'https://mvn.4399doc.com/repository/maven-snapshots' } } dependencies { implementation fileTree(dir: 'libs', include: ['*.jar', '*.aar']) // 运营 SDK:建议使用最新正式版本(release仓库中的版本),可通过浏览仓库地址或向运营咨询版本 implementation "cn.m4399.sdk:operate:3.14.4" // volley 和 support 是 SDK 使用的外部依赖,若接入方已有,可忽略 implementation 'com.android.volley:volley:1.2.1' //noinspection GradleCompatible implementation "com.android.support:support-v4:28.0.0" } ``` *注意:若使用`7.0+`版本的 gradle 及 android build 插件,仓库地址应配置在`settings.gradle`中* - *本地aar* 若使用*本地aar*,则要下载 [在线aar](https://mvn.4399doc.com/repository/maven-releases/cn/m4399/sdk/operate/3.14.4/operate-3.14.4.aar) 和 [jar+res](https://sdkftp.4399doc.com/external/operate/3.14/operate-3.14.4+574.zip) 到本地,并将`aar`和`jar`包中的以下文件 拷贝到游戏模块的`libs`目录下 ``` operate/libs/volley-v1.2.1.jar operate/libs/support-v13-23.2.1.jar ``` Gradle 文件中注意添加本地依赖 ```groovy dependencies { implementation fileTree(dir: 'libs', include: ['*.jar','*.aar']) } ``` - *jar+res* [jar+res 依赖引入](https://sdkftp.4399doc.com/external/operate/3.14/jar_res_import.html) 比较繁琐,但是完成后,后续接口调用仍然是一样的。 #### abi 适配与 so 库 若游戏不需要支持所有 [abi](https://developer.android.google.cn/ndk/guides/abis?hl=zh-cn) ,可以按需选用。 `aar`依赖方式,按以下方式配置需要的`abi`;`jar+res`依赖方式需要手动删除**不需要**的`abi`目录 ``` android { defaultConfig { ndk { // 根据游戏需要选择 abiFilters "armeabi", "armeabi-v7a", "x86", "arm64-v8a" } } } ``` ### 接口调用:初始化(必须) **功能简介:** 此接口初始化 SDK 内部状态,并完成“更新、激活、防沉迷”等流程。**SDK 初始化后才能正确调用其他接口** **调用时机:** 建议在游戏 `Activity` 的开始处如 `onCreate` 方法中进行 ```java // 初始化选项,传入游戏配置,更多说明见接入文档 OperateConfig opeConfig = new OperateConfig.Builder(this) // 设置游戏运营 key,此参数需要在原创开放平台注册应用后得到 .setGameKey(GAME_KEY) // 设置SDK页面方向,应与游戏方向一致,部分第三方页面需要在AndroidManifest中设置 .setOrientation(GAME_ORIENTATION) // 设置游戏充值是否支持超出金额,可选,true支持,默认false .setSupportExcess(GAME_SUPPORT_EXCESS) // 设置游戏是否兼在高于Android 9.0版本系统容全面屏,true兼容,默认false .compatNotch(GAME_COMPACT_NOTCH) .build(); // 初始化SDK SingleGame.init(this, opeConfig, new OpeInitedListener() { @Override public void onInitFinished() { // 完成防沉迷等初始化流程,可进入游戏 } }); ``` 初始化的几点说明 #### 页面方向 - *游戏页面* 应如下配置`android:configChanges`等,否则系统强制方向变化(一般发生是打开外部应用,如支付宝、微信)或系统设置变化时,可能会发生异常 ```xml ``` 其中`android:configChanges` 新增的配置项,是为适配 Android 分屏模式而添加的,更多内容参考[多窗口支持](https://developer.android.google.cn/guide/topics/ui/multi-window?hl=zh-cn#config) **分屏(画中画)兼容**:游戏进入分屏再点击桌面图标启动,会重启游戏页面,而并没有完整的启动应用,这会导致部分功能异常, 为了兼容这种情况,SDK 为应用默认设置了`android:resizeableActivity="false"`,即不支持分屏模式, 若游戏出于某些原因必须要覆盖此项,则务必按最低标准设置入口 Activity 和主 Activity的`android:configChanges`,即 ```xml ``` - *SDK 页面*,**方向支持横屏或竖屏,但不支持横竖屏切换** 通过`OperateConfig.setOrientation()`设置 SDK 页面方向,值是系统类`android.content.pm.ActivityInfo`定义的常量 | 方向参数| 含义| |----------------------------------------|---------| | `SCREEN_ORIENTATION_LANDSCAPE`,`int`, 0 | 横屏| | `SCREEN_ORIENTATION_PORTRAIT`, `int`, 1 | 竖屏 | | `SCREEN_ORIENTATION_SENSOR_LANDSCAPE`,`int`, 6 | 横屏,可180度旋转 | | `SCREEN_ORIENTATION_SENSOR_PORTRAIT`,`int`, 7 | 竖屏 | - *第三方页面*,其方向一般使用 SDK 默认设置即可,需要锁定可设置`android:screenOrientation`,如下所示 ```xml ``` #### 悬浮窗 悬浮窗会在用户登录后附着在游戏页面上层,点击后打开对页面展示个人信息、设置,和游戏论坛、官网等入口。 *极少数游戏登录 Activity 并不是游戏主 Activity ,则悬浮窗可能发生异常,建议游戏做相应调整* - 悬浮窗风格 可根据游戏的风格选择合适的悬浮窗样式,并通过设置`OperateConfig.setPopLogoStyle()`设置。 |样式类型|图示| |--------|----| |`PopLogoStyle.POPLOGOSTYLE_ONE`(默认)|![image](https://4399public.oss-cn-beijing.aliyuncs.com/ope/logo_one_normal.png)| |`PopLogoStyle.POPLOGOSTYLE_TWO`|![image](https://4399public.oss-cn-beijing.aliyuncs.com/ope/logo_two_normal.png)| |`PopLogoStyle.POPLOGOSTYLE_THREE`|![image](https://4399public.oss-cn-beijing.aliyuncs.com/ope/logo_three_normal.png)| |`PopLogoStyle.POPLOGOSTYLE_FOUR`|![image](https://4399public.oss-cn-beijing.aliyuncs.com/ope/logo_four_normal.png)| * 悬浮窗初始位置 可根据游戏的风格选择合适的悬浮窗样式,并通过设置`OperateConfig.setPopWinPosition()`设置。 |样式类型|位置| |--------|----| |`PopWinPosition.POS_LEFT`(默认)| 屏幕左侧| |`PopWinPosition.POS_RIGHT`|屏幕右侧| |`PopWinPosition.POS_TOP`|屏幕上侧| |`PopWinPosition.POS_BOTTOM`|屏幕下侧| ### 接口调用:充值 **功能简介:** 若游戏支持内购,调用此接口将支持用户完成支付流程,4399 充值系统支持在微信、QQ钱包、支付宝、云闪付等 APP 内完成支付 **调用时机:** 账号登录后,用户点击游戏游戏内充值按钮时 单机游戏需要充值功能时,首先要确认是使用服务端回调模式,还是客户端模式。 若是前者,只要在注册游戏时完成充值配置即可;若游戏没有自己的服务器,而不得不使用客户端回调,首先要注册回调对象。 **注意,客户端回调模式不安全,APK 容易被静态破解** - 注册客户端充值回调 ```java // 单机游戏充值时,允许使用客户端回调,如需使用请联系运营确认 // 注意 !!!!!:客户端回调不安全,APK 容易被篡改 // 设置发放物品回调,需要客户端回调才使用 SingleGame.setDeliveringGoodsListener(new SingleGame.OnDeliveringGoodsListener() { @Override public boolean onDelivering(OrderFinished of) { Log.i(TAG, of.money() + " " + of.conclude().first + " " + of.conclude().second); // 如果游戏因为某些原因发放失败,应返回false return true; } }); ``` - 充值 ```java /* * 充值 * * money, 充值金额,整型,单位元,1 ~ 50000,必须 * mark, 游戏方订单,必须, * 支持大小写字母、数字、'|'(竖线)、'-'(中划线)、'_'(下划线),最长32位,不可为空,不可重复 * commodity, 商品名,可选,不传时认为商品名是游戏币 */ String mark = GameSettings.createUniqueMark(); SingleGame.recharge(this, // 充值金额,整数,单位元 // mark: 游戏订单,游戏可以再其中映射用户名、商品信息 new Order(money, mark) // 是否支持超出金额,默认不支持 .supportExcess(false) // 商品名,可选,不传时认为商品名是游戏币 .commodity(getString(R.string.recharge_commodity_name)), new OperateCenter.OnRechargeFinishedListener() { @Override public void onRechargeFinished(boolean success, int resultCode, String msg) { Log.i(TAG, resultCode + " " + msg); } }); ``` 关于`Order`对象中的`supportExcess(boolean)`接口 > **关于超出金额模式(超额)** > 由于卡类等充值渠道有金额限制,可能出现*充值金额*无法匹配任何金额的情况; > 如果游戏能处理超出*传入金额* 部分的货币,即将多余部分以游戏发放给用户,则可以设置`true`; > 否则,应设置为`false`或不调用,SDK将直接隐藏无匹配金额的充值渠道。 ## 游戏更新 **功能简介:** 在 4399 平台发布的游戏,在有新版本提交后,调用此接口可以返回对应的更新弹窗,让用户在应用内即可完成更新。 **调用时机:** 初始化且回调后 此功能需要在4399后台提交新版本,并开启相关开关,详情可咨询运营。 更新功能会检查是否有新版本游戏上线,如果有,则显示更新内容、提示用户升级。 按升级内容,可分为全量更新和**增量更新**(只需下载新旧版 APK 文件中的差异部分)。 按开发者接入方式又可分为自动更新(无需操作,默认初始化完成)和自定义界面更新 自定义界面增量更新接入方法详见: [4399运营SDK增量升级说明](https://sdkftp.4399doc.com/external/operate/3.14/operate_upgrade_api.html)