Skip to content

Android 海外AAB接入文档

说明

  • aab 是 google play 上传应用的一种资源格式
  • (必须适配 android 14系统版本,否则会影响google play上架)
  • 推荐使用Unity 导出 Android Studio 项目出包方式
  • 如游戏首次接入,要做好 Android 手机全面屏适配(常见适配方式一般都是默认全屏展示,顶部刘海或摄像头相关不能影响到游戏相关 UI 功能,否则云测时会影响评级)
  • 确保所有调用SDK的接口都放在()调用
  • Unity 中调用到 java 中的接口注意需要切换到 UI 线程再调用 SDK 的接口
  • 请务必详细查看文档,如有对某些接入部分存在疑问可直接在对接群与技术沟通
  • 本文档会不定期更新,如涉及接口变动会在群内同步消息,更多更新内容请查看Android SDK更新
  • 点击此处可进行Android-AAB-Demo 下载

接入流程

说明

  • 1.找运营申请相关参数与配置,目前接入需要三个配置文件google-services.json, access.config以及 keystore 签名文件
  • 2.下载 Demo 示例工程,文件使用参考Demo相关工程结构配置
  • 3.配置远程仓库配置并调用相关接口

参数配置(

project:build.gradle

xml
buildscript {
    repositories {
        maven {
            url 'https://sdk.wdyxgames.com/nexus/repository/sdk-public/'
        }
    }
}

allprojects {
    repositories {
        maven {
            url 'https://sdk.wdyxgames.com/nexus/repository/sdk-public/'
        }
    }
}

或 settings.gradle 下配置

xml
pluginManagement {
    repositories {
        maven {
            url 'https://sdk.wdyxgames.com/nexus/repository/sdk-public/'
        }
    }
}
dependencyResolutionManagement {

    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        maven {
            url 'https://sdk.wdyxgames.com/nexus/repository/sdk-public/'
        }
    }
}

app:build.gradle 配置(

注意:apk 出包时仅引用 hoolai-core 库即可

xml
//引入google插件 id 'com.google.gms.google-services'
plugins {
    id 'com.android.application'
    id 'com.google.gms.google-services'
}

//引入依赖库
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    //hoolai-core(必接)
    implementation 'com.hoolai.access.open:hoolai-core:1.0.4.2-global'
    //access-native(必接)
    implementation 'com.hoolai.access.platform:access-native:0.1.2.1425-global'
    //fangzhou(必接)
    implementation 'com.hoolai.access.open.fangzhou:fangzhou:4.5.16.11'
    //基础功能模块,登录/支付/分享等(必接)
    implementation 'com.hoolai.oversea:hl-oversea-global:1.0.5.1' 
    //aihelp(必接)
    implementation 'com.hoolai.oversea.aihelp:aihelp:1.0.0.1'
    //appsflyer(必接)
    implementation 'com.hoolai.oversea.appsflyer:appsflyer:1.0.0.2'
    //firebase(必接)
    implementation 'com.hoolai.oversea.firebase:firebase:1.0.1.0'
    //facebooklinks(必接)
    implementation 'com.hoolai.oversea.links:facebooklinks:1.0.1.0'
    //openInstall(选接)
    implementation 'com.hoolai.oversea.opins:openInstall:1.0.0.0'
    //crashlytics(⚠️该库已废弃,和firebase类库已合并)
    //implementation 'com.hoolai.oversea.crash:crashlytics:1.0.0.0'
}

AndroidManifest.xml 配置(

以下配置为 google 授权登录,Facebook 授权登录,以及 Google Play Games Services v2 授权登录配置,如不需要可不配置(这里需要在 demo 中验证)

javascript
<!--Games Services Sign In v2 如要使用PGS登录必须配置!否则不需要加-->
<meta-data android:name="com.google.android.gms.games.APP_ID"
    android:value="@string/game_services_project_id"/>
<!--Games Services Sign In v2 如要使用PGS登录必须配置!否则不需要加-->

<!--注意需为游戏的启动类 Activity 中配置intent-filter!以下为示例无需 copy!-->
<activity
    android:name="com.hoolai.access.demo.GameActivity"
    android:hardwareAccelerated="true"
    android:launchMode="singleTask"
    android:theme="@style/HlAccountTransparent"
    android:configChanges="orientation|keyboardHidden|screenSize"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.MAIN" />
        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
    
    <!-- SDK内部配置(必须) 其中scheme的value值为accesssdk+channelId-->
    <intent-filter>
        <action android:name="android.intent.action.VIEW"/>
        <category android:name="android.intent.category.BROWSABLE"/>
        <category android:name="android.intent.category.DEFAULT"/>
        <data android:scheme="accesssdk1"/>
    </intent-filter>
    <!-- SDK内部配置(必须) 其中scheme的value值为accesssdk+channelId-->
</activity>
<!--注意需为游戏的启动类 Activity 中配置intent-filter!示例无需 copy!-->

<!--Facebook login share-->
<provider
    android:name="com.facebook.FacebookContentProvider"
    android:authorities="com.facebook.app.FacebookContentProvider1234567890"
    android:exported="true" />

<meta-data
    android:name="com.facebook.sdk.ApplicationId"
    android:value="@string/facebook_app_id" />

<meta-data
    android:name="com.facebook.sdk.ClientToken"
    android:value="@string/facebook_client_token" />

<activity
    android:name="com.facebook.CustomTabActivity"
    android:exported="true">
    <intent-filter>
        <action android:name="android.intent.action.VIEW" />

        <category android:name="android.intent.category.DEFAULT" />
        <category android:name="android.intent.category.BROWSABLE" />

        <data android:scheme="@string/fb_login_protocol_scheme" />
    </intent-filter>
</activity>
<!--Facebook end-->

上面的参数配置位置在 res/values/strings.xml 文件中配置,以下参数由运营提供

javascript
<string name="facebook_app_id">facebookAppId</string>
<string name="fb_login_protocol_scheme">fbScheme</string>
<string name="facebook_client_token">facebookClientToken</string>
<string translatable="false"  name="game_services_project_id">googleProjectId</string>

接口文档

生命周期接入

Application 接入(

方式一:游戏无自定义 Application 时使用 HLApplication,参考 AndroidManifest.xml 中的 <application name 标签属性配置

方式二:如游戏有自定义 Application 通过继承 HLApplication 即可

方式三:游戏有自定义 Application 且不能继承 HLApplication 时需要在 Application 生命周期进行以下调用:

java
public class YourApplication extends YourBaseApplication {

    @Override
    public void onCreate() {
        super.onCreate();
        FastSdk.onApplicationCreate(this);
    }

    @Override
    public void onTerminate() {
        super.onTerminate();
        FastSdk.onTerminate(this);
    }

    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
        FastSdk.onConfigurationChanged(this, newConfig);
    }

    @Override
    protected void attachBaseContext(Context context) {
        super.attachBaseContext(context);
        FastSdk.attachBaseContext(this, context);
    }
}

Activity 生命周期接入(

java
@Override
protected void onSaveInstanceState(Bundle outState) {
    super.onSaveInstanceState(outState);
    FastSdk.onSaveInstanceState(outState);
}

@Override
protected void onStart() {
    super.onStart();
    FastSdk.onStart(this);
}

@Override
protected void onResume() {
    super.onResume();
    FastSdk.onResume(this);
}

@Override
protected void onStop() {
    super.onStop();
    FastSdk.onStop(this);
}

@Override
protected void onPause() {
    super.onPause();
    FastSdk.onPause(this);
}

@Override
protected void onRestart() {
    super.onRestart();
    FastSdk.onRestart(this);
}

@Override
protected void onDestroy() {
    super.onDestroy();
    FastSdk.onDestroy(this);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    FastSdk.onNewIntent(intent);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    FastSdk.onActivityResult(this, requestCode, resultCode, data);
}

@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    FastSdk.onRequestPermissionsResult(requestCode, permissions, grantResults);
}

@Override
public void onConfigurationChanged(Configuration newConfig) {
    super.onConfigurationChanged(newConfig);
    FastSdk.onConfigurationChanged(this, newConfig, getResources());
}

@Override
public void onBackPressed() {
    FastSdk.exit();
}

@Override
public Resources getResources() {
    return FastSdk.getResources(super.getResources());
}
//以下为更新内容
@Override
protected void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
    super.onRestoreInstanceState(savedInstanceState);
    FastSdk.onRestoreInstanceState(savedInstanceState);
}

@Override
public void onWindowFocusChanged(boolean hasFocus) {
    super.onWindowFocusChanged(hasFocus);
    FastSdk.onWindowFocusChanged(hasFocus);
}

SDK 功能接入

初始化(

注意

  • SDK初始化期间,解决游戏黑屏的建议:准备一张名为"unity_static_splash"的图片,拷贝至res/drawable目录即可
  • 游戏启动后首先调用此接口,后才能进行热更/版本检测/游戏初始化/登录等功能调用
  • 在未收到初始化回调或收到onInitFailed时,游戏不可进行后续功能调用
  • 初始化失败时建议引导用户重新初始化或重启游戏
java
//游戏主Activity的onCreate中
//SDK初始化回调
FastSdk.hlSystemListener = new HLSystemListener() {
    @Override
    public void onInitSuccess(InitResult initResult) {
        //gameId,channelId,channel
    }

    @Override
    public void onInitFailed(String reason) {
       
    }

    @Override
    public void onCustomExit() {
        /* demo 只作为参考,游戏应该根据自己所需逻辑实现
         * 渠道没有退出二次确认框
         * 根据需要加二次确认框
         */
        //渠道不存在退出界面,如百度移动游戏等,此时需在此处弹出游戏退出确认界面,否则会出现渠道审核不通过情况
        //游戏实现自己的退出界面 ,实现退出逻辑,请勿直接照搬demo
        //根据需要加二次确认框
        new AlertDialog.Builder(GameActivity.this)
                .setTitle("游戏退出弹窗")
                .setMessage("我是游戏的弹窗界面哦")
                .setNegativeButton("取消", null)
                .setPositiveButton("确定", (dialog, which) -> onExitSuccess(s))
                .setCancelable(false).show();
    }

    @Override
    public void onExitSuccess(String result) {
        //如果渠道有退出界面,点击渠道退出后会触发该回调用于释放游戏资源,也有可能此时程序已被kill不会执行到此处,可预留处理一些资源释放操作
        //处理退出逻辑
        moveTaskToBack(true);
        finish();
        //建议游戏按照下面代码逻辑,退出程序兼容性最好,否则可能会造成oppop、vivo等渠道退出不彻底,导致再次点击启动应用黑屏。
        Intent intent = new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_HOME);
        intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(intent);
        android.os.Process.killProcess(android.os.Process.myPid());
    }

    @Override
    public void onUpdate(String data) {
        //版本升级
    }
};

//SDK账号回调
FastSdk.hlAccountListener = new HLAccountListener() {
    @Override
    public void onRefreshUser(LoginResult result) {
         //小号切换,此回调中之需要游戏验证用户合法性问题,无小号可忽略
         //如果游戏不支持内部切换玩家信息,游戏需要调用登出,再重新登录(不需要重新初始化)
    }

    @Override
    public void onLoginSuccess(LoginResult result) {
         
    }

    @Override
    public void onLoginFailed(String reason) {
    
    }

    @Override
    public void onLogout(Object... var1) {
       
    }
};

//SDK支付回调
FastSdk.hlPaymentListener = new HLPaymentListener() {
    @Override
    public void onPaySuccess(String result) {
        
    }

    @Override
    public void onPayFailed(String reason) {

    }
    
    
    @Override
    public void onQuerySuccess(List<GoodsInfo> list) {
        //海外游戏必须处理,获取商品列表用于展示
    }
};

//SDK分享回调
FastSdk.hlShareListener = new HLShareListener() {
    @Override
    public void onShareSuccess() {

    }

    @Override
    public void onShareFailed(String reason) {

    }
};

//SDK初始化,此方法需要在启动游戏时的隐私权限回调方法中调用
//后面的所有SDK功能都需要在初始化回调成功之后调用
//注意:调用onCreate之前需要将以上用到的接口先进行实例化
FastSdk.onCreate(this);

登录(

注意

  • 调用此方法时确保已经执行“game_init_result”事件报送,更多具体内容请查阅 游戏自定义报送
  • 初始化未收到回调或初始化失败时禁止调用登录接口
java
FastSdk.login();

用户中心(

java
//调用时机必须在登录成功之后
FastSdk.openAccountCenter(activity);

获取商品列表信息(

java
//调用时机,必须在确认登录成功之后使用!
//必须在登录成功之后或商品详情界面展示之前调用,注意查询成功后会通过FastSdk.hlPaymentListener接口中将所有商品信息回调回来
//注意由于商品信息获取为异步获取,如登录成功之后由于网络等原因无法获取到商品信息或获取为空,请在打开游戏商城界面时或下次支付之前增加判断再次获取
//如果始终无法获取到商品信息,请使用游戏内默认配置的商品信息展示支付,注意要和 SDK 管理台中配置的商品信息保持一致
FastSdk.queryGoodsInfo();

支付(

java
//调用支付之前需要先进行基础事件的报送,比如创角,进服,升级等
PayParams payParams = new PayParams();
payParams.setItemId("item60");//商品ID,必传
payParams.setItemName("60钻石");//商品名称,必传
payParams.setAmount(100);//商品金额,必传,单位:分
payParams.setNotifyUrl("");//支付回调地址,非必传,如不设置可不写
//扩展信息,回调时原样返回,因为各渠道回调参数限制不一致。
//回调参数暂时只支持长度255。callBackInfo中不要使用这些符号:“|”、“=”、“+”、“/”。
payParams.setCallbackInfo("支付扩展信息,游戏透传参数");
payParams.setCurrency("USD");//币种通过商品信息接口查询获取,必传
FastSdk.pay(activity, payParams);

数据上报()

注意(支付之前必须先进行基础数据上报)

创角,进服,升级等事件进行数据上报时,roleId,roleName,serverId,serverName参数不能为空且必传,否则会影响支付功能!!
其他必接数据请查看

java
//eventType取值:
//创角: EventType.CreateRole
//进服: EventType.EnterServer
//升级: EventType.LevelUp
//前三种是必须上报,下面这种根据运营需求进行自定义事件上报
//自定义点:EventType.CustomerEvent,设置自定义点位后必须设置setExtendAction("game_init"),setPhylum("14")等

PlayerInfo playerInfo = new PlayerInfo();
playerInfo.setRoleId("32424");//角色唯一标识id,必传
playerInfo.setRoleName("昵称");//必传,String
playerInfo.setRoleLevel("6");//必传,注意字符串必须是数字,比如"123"
playerInfo.setZoneId("1");//必传,没有可传默认值"1",注意字符串中的值必须为数字
playerInfo.setZoneName("华东大区");//必传,没有可传默认值,比如"1区"等
playerInfo.setServerId("1");//必传,没有可传默认值"1",注意字符串中的值必须为数字
playerInfo.setServerName("区名称");//必传,没有可传默认值,比如"1区"等
playerInfo.setBalance("66");//必传,获取不到时传""
playerInfo.setVip("5");//必传
playerInfo.setPartyname("帮派名称");//非必传

//新增内容: extra必须携带数据,参考客户端数据报送特殊数据报送
//扩展信息,格式:key:value,key:value
playerInfo.setExtra("a:arm,b:bom,gameResourceUrl:xxx,gameLoginServerUrl:xxx");
playerInfo.setClassField("");//事件结果,可不填
//playerInfo.setPhylum("");//扩展数据报送时需要按照提供的事件编号填写,如:1
//playerInfo.setExtendAction("点位名称"); //基础打点不传,自定义打点传
FastSdk.report(EventType.EnterServer, PlayerInfo playerInfo);

注意

  • 需要接入CLS网络探测功能的同学注意!!!点击查看规则详情
  • 该功能请在SDK初始化之后尽早报送,可以单独报送,也可以跟着其他点位一起上报
  • 探测地址可以是域名或IP
  • 探测地址中的冒号用@替换,避免格式错误
  • 探测地址的key必须使用以下三个字段:gameResourceUrl,gameLoginServerUrl,gameServerUrl

如:playerInfo.setExtra("key:value,gameResourceUrl:http@xxx/open/init, gameServerUrl:tcp@111.222.333.6@8888");

EventType

参数名描述是否必填
EventType.CreateRole创建角色
EventType.EnterServer游戏进服
EventType.LevelUp角色升级
EventType.CustomerEvent自定义

PlayerInfo

参数名类型描述是否必填
roleIdString角色id
roleNameString角色名称
roleLevelString等级
zoneIdString大区id,没有大区传serverId
zoneNameString大区名称,没有大区传serverName
serverIdString服务器id
serverNameString服务器名称
balanceString余额
vipStringvip等级
partyNameString公会名称
appVersionString应用版本号
appResVersionString游戏资源版本号
extendActionString事件名称
roleCreateTimeString角色创建时间
phylumString事件id,参考“客户端数据上报”文档
classFieldString事件结果,ok/fail
extraString扩展信息(注意:cls报点用到该字段)

客服唤起(选接)

java
FastSdk.openService(activity);

系统分享与 Facebook 分享(选接)

java
ShareParams params = new ShareParams();
params.setTitle("标题");
params.setContent("内容");
params.setPicPath("picPath");//本地或网络图片链接
params.setShareUrl("http://xx.com");

//FACEBOOK
params.setBmp(bmp); 

FastSdk.share(ShareType.FACEBOOK, ShareType.ChildType.WX_CHAT, params);

方舟 SDK 报送接口(选接)

额外游戏数据报送,例如游戏中某些特殊关卡,数据等,如非要求接入可不接

java
String action = "game_xxx";
Map<String, Object> hashMap = new HashMap<>();
hashMap.put("xxx", 123);
hashMap.put("ooo", "321");
FastSdk.gameDataReport(action, hashMap);

Appsflyer(选接)

appsflyer 深度链配置,如集成其他 appsflyer 报送功能后, SDK会自动引入相关配置默认生效

xml
<!--appsflyer 深度链接(选接,非必接),此处参数配置由运营直接在appsflyer后台查看获取,需添加到游戏入口启动类中-->
  <intent-filter  android:autoVerify="true">
      <action android:name="android.intent.action.VIEW" />
      <category android:name="android.intent.category.DEFAULT" />
      <category android:name="android.intent.category.BROWSABLE" />
      <data android:scheme="https"android:host="xxxx-brand.onelink.me"android:pathPrefix="/xxx" />
  </intent-filter>
  <!--appsflyer 深度链接 end-->

Firebase(选接)

仅需加入 firebase 依赖库,功能由 SDK 侧自动集成可直接使用

Aihelp(选接)

仅需加入 aihelp 依赖库,可通过客服接口唤起

导入上面的依赖库,增加回调接口监听

java
//_TODO:Facebook DeepLink回调,该接口选接_
_//使用时必须在初始化之前配置,如需使用该功能需要先去Facebook后台填写游戏的启动Activity,且需要在游戏入口类配置scheme启动<intent-filter>_
//具体可参考https://developers.facebook.com/docs/applinks/add-to-content
FastSdk.hlDeepLinkListener = new HLDeepLinkListener() {
    @Override
    public void onDeepLinkSuccess(String jsonStr) {
        //返回内容可参考https://developers.facebook.com/docs/applinks/navigation-protocol?locale=zh_CN
    }
};

openInstall(选接

导入依赖进行接口监听

xml
<meta-dataandroid:name="com.openinstall.APP_KEY"android:value="OPENINSTALL_APPKEY"/>

<!--AndroidManifest.xml 游戏主Activity-->
<activityandroid:name=".MainActivity"
    android:exported="true"
    android:launchMode="singleTask">
        <intent-filter>
            <action android:name="android.intent.action.VIEW"/>
            <category android:name="android.intent.category.DEFAULT"/>
            <category android:name="android.intent.category.BROWSABLE"/>
            <data android:scheme="OPENINSTALL_SCHEME"/>
        </intent-filter>
</activity>

注意

OPENINSTALL_APPKEY 替换成 openinstall 为应用分配的 appkey,将 OPENINSTALL_SCHEME 替换为真正的 scheme 参数,此处由运营提供

用户通过 openInstall 分享且安装后打开,会在 SDK 登录成功回调 UserInfo 中 getMap 中增加两个字段 key 为 openInstall_channelCode 与 openInstall_appData 通过此处获取到相关数据进行处理相应逻辑即可

Firebase Crashlytics(选接

1.项目根目录下build.gradle配置

xml
plugins {
    //Make sure that you have the AGP plugin 8.1+ dependency
    id 'com.android.application' version '8.1.4' apply false
    //...

    //Make sure that you have the Google services Gradle plugin 4.4.1+ dependency
    id 'com.google.gms.google-services' version '4.4.2' apply false

    //Add the dependency for the Crashlytics Gradle plugin
    id 'com.google.firebase.crashlytics' version '3.0.2' apply false
}

2.app模块下build.gradle配置

xml
plugins {
        id 'com.android.application'
        //Make sure that you have the Google services Gradle plugin
        id 'com.google.gms.google-services'
        //Add the Crashlytics Gradle plugin
        id 'com.google.firebase.crashlytics'
}

//引入依赖库
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    ...
    implementation 'com.hoolai.oversea.crash:crashlytics:1.0.0.0'
}

3.如需增加其他额外功能配置,Demo已经有示例,可参照demo接入官方文档

Catappult支付

项目根目录下build.gradle配置替换依赖implementation 'com.hoolai.oversea:hl-oversea-global:1.0.5.0'为下面依赖配置

xml

//引入依赖库
dependencies {
    implementation fileTree(include: ['*.jar'], dir: 'libs')
    //如需接入catappult支付渠道请引用下面这个依赖,注意与com.hoolai.oversea:hl-oversea-global:${version}两个依赖同时只能引入一个
    implementation 'com.hoolai.oversea:hl-oversea-global-catappult:1.0.5.2'
    //access-native 1.0.2.1426版本及以上版本
    implementation 'com.hoolai.access.platform:access-native:0.1.2.1426.1-global'
}

Q&A

初始化失败,出现“非正版应用”提示,如何处理?

签名文件不正确,如果没有签名文件可联系运营同学。

账密登录时没有账号?

账密登录方式没有注册功能,需要运营同学提供账号/密码。

如何测试沙箱环境支付?

和运营同学确认,确保已开启沙箱环境,并确保账号已加入测试白名单。

无法拉起支付?

检查进入游戏时是否报送创角或进服事件。

支付成功不到账?

1.检查提供的支付回调url是否正确。

2.检查支付接口,在支付参数中是否调用了setNotifyUrl(url),如果调用了则会优先回调此url。

渠道包中从游戏内登出时悬浮球不隐藏

游戏未调用Fastsdk.logout(),建议游戏“设置”界面做两个按钮:“切换服务器”、“切换账号”,在执行“切换账号”时调用logout。

Hoolai Access SDK