[!WARNING|labelVisibility:hidden|iconVisibility:hidden] 自 2026 年 8 月 31 日起:

  • 新应用和应用更新必须以 Android 16(API 级别 36)或更高版本为目标平台,才能提交到 Google Play;但 Wear OS 和 Android Automotive OS 应用除外,此类应用必须以 Android 15(API 级别 35)或更高版本为目标平台,而 Android TV 和 Android XR 应用必须以 Android 14(API 级别 34)或更高版本为目标平台。
  • 如果新用户的设备搭载的 Android OS 版本高于现有应用的目标 API 级别,则该应用必须以 Android 15(API 级别 35)或更高版本为目标平台,才能继续在此类设备上使用。以 Android 14(API 级别 34)或更低版本为目标平台的应用,包括以 Android 13(API 级别 33)或更低版本为目标平台的 Wear OS、Android TV 和 Android XR 应用,以及以 Android 12(API 级别 31)或更低版本为目标平台的 Android Automotive OS 应用,只能在所搭载 Android OS 版本不高于应用目标 API 级别的设备上使用。
  • 如果需要更多时间来更新应用,可申请延期至 2026 年 11 月 1 日,开发者可以在 Play 管理中心内找到应用的延期表单。如需了解详情,请参阅符合 Google Play 的目标 API 级别要求

1. 接入准备

1.1 前提条件

接入之前请确保项目满足以下要求:

  • 最低 SDK 版本 23 或更高版本
  • 编译 SDK 版本 36 或更高版本
  • 对于 Kotlin 应用,请使用 Kotlin 版本 1.9 或更高版本

1.2 配置文件

  • 获取配置文件 sf_config_gp.xml(游戏发行方提供),配置文件名称不做强制要求
  • 将配置文件添加到游戏工程的应用级模块的 <project>/<app-module>/src/main/res/values 目录中

2. 集成SDK

可以通过 Gradle 自动集成或手动集成。

2.1 自动集成(推荐)

  • 在项目根目录的 settings.gradle 文件中添加如下配置:

    dependencyResolutionManagement {
      repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
      repositories {
          google()
          mavenCentral()
          ...
          maven {
              url 'https://maven.cnb.cool/zhiduohuyu/sdk-build/-/packages/'
              credentials {
                  username 'cnb'
                  password 'c8PhqkHaf1zli14e2yCl4h872OD'
              }
          }
      }
    }
    
  • 在模块级的 build.gradle 文件中添加 SDK 的依赖项:

    dependencies {
      implementation fileTree(dir: 'libs', include: ['*.aar', '*.jar'])
      ...
      // Import the BoM for the Sofish platform
      implementation platform('com.sofish.game:game-bom:1.7.5')
      implementation 'com.sofish.game:game-sdk'
    }
    

2.2 手动集成

下载最新的SDK,并将 SFSDKDemo/sf-sdk/libs 目录下的 aar 文件拷贝到模块级的 libs 目录中,然后在模块的 build.gradle 文件中添加需要的第三方 SDK 依赖项:

dependencies {
    api fileTree(dir: 'libs', include: ['*.aar', '*.jar'])

    // Facebook
    implementation 'com.facebook.android:facebook-login:18.2.3'

    // Google Sign-In
    implementation 'com.google.android.gms:play-services-auth:21.5.1'
    implementation 'com.google.android.gms:play-services-games-v2:21.0.0'

    // AppsFlyer
    implementation 'com.appsflyer:af-android-sdk:6.18.0'

    // ThinkingData
    implementation 'cn.thinkingdata.android:ThinkingAnalyticsSDK:3.2.3'

    // Google Play In-App Reviews
    implementation 'com.google.android.play:review:2.0.2'
    // Google Play In-App Update
    implementation 'com.google.android.play:app-update:2.1.0'
    // Google Play Billing
    implementation 'com.android.billingclient:billing:8.3.0'
    // Google Play Install Referrer
    implementation 'com.android.installreferrer:installreferrer:2.2'
    // Google Advertising ID
    implementation 'com.google.android.gms:play-services-ads-identifier:18.3.0'

    // Firebase
    implementation platform('com.google.firebase:firebase-bom:34.13.0')
    implementation 'com.google.firebase:firebase-analytics'
    implementation 'com.google.firebase:firebase-crashlytics'
    implementation 'com.google.firebase:firebase-messaging'
    implementation 'com.google.firebase:firebase-config'
}

2.3 迁移到Gradle

  • 删除之前添加到 libs 目录的 aar 文件
  • 删除手动集成部分添加的依赖项
  • 添加自动集成部分的配置和依赖项
  • 其他配置文件保持不变

3. Application配置

  • 如果游戏需要自定义Application, 则游戏的Application需要继承com.sf.sdk.app.SFApplication类。
  • 如果游戏不需要自定义Application,无需进行Application配置,保持默认配置即可。

4. 多语言设置(选接)

SDK目前支持的语言有:简体中文繁体中文英文葡萄牙语西班牙语泰语韩语

  • 如果应用使用的库包含语言资源(例如 AppCompat 或 Google Play 服务),则应用编译时都会包含这些库中包含的所有语言字符串。如果只想保留应用支持的语言,则可以使用resConfig属性指定应用支持的语言,未指定的语言资源都将被移除。例如应用仅支持英语和简体中文,则需要在应用级模块的build.gradle文件中添加以下配置:

      android {
          defaultConfig {
              ...
              resConfigs "en", "zh-rCN"
          }
      }
    
  • 在游戏中切换语言时,如果游戏是通过Cocos/Unity开发的,在设置Cocos/Unity的语言环境时,同时还需要设置Android原生的语言环境。示例代码如下:

      // 泰语
      private static final Locale THAI = new Locale("th", "TH");
      // 韩语
      private static final Locale KOREAN = new Locale("ko", "KR");
      // 英文
      private static final Locale ENGLISH = new Locale("en", "US");
      // 简体中文
      private static final Locale CHINESE_SIMPLIFIED = new Locale("zh", "CN");
      // 繁体中文(台湾)
      private static final Locale CHINESE_TRADITIONAL = new Locale("zh", "TW");
    
      // 切换语言
      SFPlatform.getInstance().switchLanguage(activity, locale);
    

5. 应用清单配置说明

5.1 冷启动优化

为了缓解游戏冷启动时CPU负载过高和GAID锁竞争问题,可以禁用部分第三方SDK的自动初始化功能,需要在项目应用级模块的 <project>/<app-module>/src/main/AndroidManifest.xml 文件中添加以下配置:

<!--Firebase-->
<provider
    android:name="com.google.firebase.provider.FirebaseInitProvider"
    android:authorities="${applicationId}.firebaseinitprovider"
    android:exported="false"
    tools:node="remove" />
<!--Facebook-->
<provider
    android:name="com.facebook.internal.FacebookInitProvider"
    android:authorities="${applicationId}.FacebookInitProvider"
    android:exported="false"
    tools:node="remove" />
<!--Google Play Games-->
<provider
    android:name="com.google.android.gms.games.provider.PlayGamesInitProvider"
    android:authorities="${applicationId}.playgamesinitprovider"
    android:exported="false"
    tools:node="remove" />

5.2 ContentProvider优化(选接)

接入其他第三方SDK或广告SDK时,会引入第三方SDK在AndroidManifest.xml注册的ContentProvider,注册过多的ContentProvider会拖慢应用冷启动的速度,有阻塞主线程导致ARN的风险。为了解决这个问题,SDK内部可以通过配置延迟加载ContentProvider的初始化,减少冷启动的时间,降低冷启动的资源争抢和 ANR 风险。如果游戏没有冷启动用户流失占比较高的问题,可以忽略该部分内容。

延迟加载ContentProvider可以通过以下步骤完成:

  • 找出需要延迟加载的ContentProvider,在AndroidManifest.xml文件中通过在<provider>标签中添加android:enabled="false"属性禁用该ContentProvider。代码示例如下:

      <provider
          android:name="com.google.android.gms.ads.MobileAdsInitProvider"
          android:authorities="com.sofish.watersort.gp.mobileadsinitprovider"
          android:enabled="false"
          android:exported="false"
          android:initOrder="100" />
      <provider
          android:name="com.applovin.sdk.AppLovinInitProvider"
          android:authorities="com.sofish.watersort.gp.applovininitprovider"
          android:enabled="false"
          android:exported="false"
          android:initOrder="101" />
      <provider
          android:name="com.squareup.picasso.PicassoProvider"
          android:authorities="com.sofish.watersort.gp.com.squareup.picasso"
          android:enabled="false"
          android:exported="false" />
      <provider
          android:name="sg.bigo.ads.controller.provider.BigoAdsProvider"
          android:authorities="com.sofish.watersort.gp.BigoAdsProvider"
          android:enabled="false"
          android:exported="false" />
      <provider
          android:name="com.mbridge.msdk.config.component.status.MBComponentLifecycleProvider"
          android:authorities="com.sofish.watersort.gp.mbcomponentlifcycleprovider"
          android:enabled="false"
          android:exported="false" />
    
  • sf_config_gp.xml文件或者<project>/<app-module>/src/main/res/values目录下的其他资源文件中添加以下2项配置:

      <bool name="sf_allow_manual_disabled_provider">true</bool>
    
      <string-array name="sf_disabled_provider_names">
          <item>com.google.android.gms.ads.MobileAdsInitProvider</item>
          <item>com.applovin.sdk.AppLovinInitProvider</item>
          <item>com.squareup.picasso.PicassoProvider</item>
          <item>sg.bigo.ads.controller.provider.BigoAdsProvider</item>
          <item>com.mbridge.msdk.config.component.status.MBComponentLifecycleProvider</item>
      </string-array>
    

[!TIP|labelVisibility:hidden|iconVisibility:hidden] 注意:sf_allow_manual_disabled_providertrue时,sf_disabled_provider_names为上面禁用的需要延迟初始化的ContentProvider,这2条属性需要同时存在延迟初始化才会生效。

<provider>标签中有以下几种情况的不适合延迟初始化,保持原来的配置不变:

  • android:exported="true"表示跨进程访问
  • android:process表示独立进程属性
  • android:permission表示具有特定权限保护
  • FileProvider 及其子类表示资源分发,同时带有android:grantUriPermissions="true"属性和android.support.FILE_PROVIDER_PATHSmeta-data属性。

5.3 变现说明(选接)

如果游戏需要接入 Facebook插屏广告,需要在项目应用级模块的 <project>/<app-module>/src/main/AndroidManifest.xml 文件中添加以下配置:

<activity
    android:name="com.facebook.CustomTabActivity"
    android:exported="true"
    tools:node="merge"
    tools:replace="android:exported" />

[!WARNING|labelVisibility:hidden|iconVisibility:hidden] 在SDK中 android:exported 的值为false,如果设置为true,com.facebook.CustomTabActivity可能会导致游戏无法正常加载。如果需要修改 android:exported 的值请和游戏发行方确认!

6. 方法调用说明

[!WARNING] 所有方法调用,都必须通过com.sf.sdk.SFPlatform 类在UI线程中调用!!!

7. 初始化(必接)

7.1 调试模式

SFPlatform.getInstance().setDebugMode(true);   // 正式发布时建议设置为false

7.2 SDK初始化

SDK初始化方法建议在游戏启动的Activity#onCreate()方法中调用,如果游戏包含热更新功能,则建议在不需要热更新时/完成热更新之后调用,代码示例如下:

SFPlatform.getInstance().init(activity, new SFSDKListener() {
    @Override
    public void onInitSuccess() {
        // 初始化成功回调
    }

    @Override
    public void onInitFailed(int code, String message) {
        // 初始化失败回调
    }

    @Override
    public void onLoginSuccess(SFUser user) {
        // 登录成功回调,游戏需要刷新当前用户信息
    }

    @Override
    public void onLoginSuccessWaitForNetwork(SFUser user) {
        // 登录成功回调(触发登录操作时网络不可用,网络恢复时自动登录),游戏根据具体情况处理当前用户信息
    }

    @Override
    public void onLoginFailed(int code, String message) {
        // 登录失败回调
    }

    @Override
    public void onLinkSuccess(SFUser user) {
        // 账号绑定成功回调
    }

    @Override
    public void onLinkFailed(int code, String message) {
        // 账号绑定失败回调
    }

    @Override
    public void onPaymentSuccess(SFOrder order) {
        // 支付成功回调(不依赖服务端通知的可以直接进行发货)
    }

    @Override
    public void onPaymentFailed(int code, String message) {
        // 支付失败回调
    }

    @Override
    public void onRestoreSuccess(List<SFOrderRecord> success, List<SFOrderRecord> failure) {
        // 恢复购买成功回调(success表示恢复成功的购买,failure表示恢复失败的购买)
    }

    @Override
    public void onRestoreFailed(int code, String message) {
        // 恢复购买失败回调(表示恢复购买操作未成功处理)
    }

    @Override
    public void onExitGame() {
        // 退出游戏回调
    }

    @Override
    public void onLogout() {
        // 退出登录回调,游戏需要清除已登录的用户信息
    }

    @Override
    public void onDeleted() {
        // 账号注销回调,在玩家成功提交账号注销申请时回调
    }
});

SFUser数据结构如下:

参数名称 参数类型 是否可为空 说明
uid String 用户 ID
name String 用户名
loginName String 用户登录名(昵称)
token String 用户登录令牌
expiredTime long 用户登录令牌有效期(秒)
registerTime long 用户注册时间(时间戳)
accountType Boolean 当前登录账号类型
newAccount String 是否为新用户

results matching ""

    No results matching ""