接入准备

APK包必须签名,签名不可更改

APK包必须 zipalign 优化

minSdk 24

compileSdk 35 (34升级到35常见问题)

targetSdk 35

buildToolsVersion = "35.0.0"

Gradle JDK 不能低于17

SDK需支持AndroidX 检查AndroidX配置项

项目需支持AndroidX,检查配置

检查gradle.properties中是否缺少以下配置:
		
android.useAndroidX=true
android.enableJetifier=true
		
	

Gradle版本配置

  1. 建议Gradle插件版本使用8.8.2(在项目级build.gradle中配置)
  2. 对应Gradle版本使用8.10.2

    以下示例在 gradle/wrapper/gradle-wrapper.properties 文件中将 Gradle 的版本设置为 8.10.2
            
    ...
    distributionUrl=https\://services.gradle.org/distributions/gradle-8.10.2-all.zip
    ...
       
    

build.gradle配置

修改项目级build.gradle文件

  • 更改项目级build.gradle以引用Android Gradle插件以及依赖项的仓库配置:

                
    				
    buildscript {
    
      repositories {
        google() 
        jcenter()
        mavenCentral()
      }
    
      dependencies {
        // ...
        //配置Gradle插件版本
        classpath 'com.android.tools.build:gradle:8.8.2'
      }
    }
    
    allprojects {
      // ...
      repositories {
        // ...
        google() 
        jcenter()
        mavenCentral()
    	
        maven{//RangersAppLog
            url 'https://artifact.bytedance.com/repository/Volcengine/'
        }
        
        maven {
            allowInsecureProtocol = true
            url 'http://maven.aliyun.com/nexus/content/repositories/releases/'
        }
        
        maven {
            url 'https://developer.huawei.com/repo/'
        }
    	
        maven { //PnSDK
            allowInsecureProtocol = true
            url 'http://git-maven.17995api.net:8888/api/v4/projects/112/packages/maven'
        }
        
      }
    }				
    
    			

修改应用级build.gradle文件

  • 应用级build.gradle中添加配置和依赖项:

            
    apply plugin: 'com.android.application'
    //...
    
    android {
        //...
        defaultConfig {
        	//...
        	//该配置的值写死,不要修改。
            //注意:该值一定要配置在apply plugin: 'com.android.application'层级的build.gradle中
    
            manifestPlaceholders.put("APPLOG_SCHEME","rangersapplog.byAx6uYt".toLowerCase())
        }
    
        //解决编译时的重复问题。
        packagingOptions {
            exclude 'META-INF/INDEX.LIST'
            exclude 'META-INF/DEPENDENCIES'
        }
    }
    
    //建议配置动态版本的缓存策略,保证能够及时更新sdk的版本
    configurations.all {
        resolutionStrategy.cacheDynamicVersionsFor 10, 'minutes'
    }        	
    
    // ...
    dependencies {
        // ...
        implementation 'com.pn:pnsdk-cn:+'
        implementation 'com.pn.pnsdk:res-[APPID]:+'
        //注意:[APPID]请替换为实际参数,AppID参数可以在提供的说明文档中找到。
        //例如:implementation 'com.pn.pnsdk:res-9000001:+'
    }
       
    

混淆规则

在混淆配置文件末尾添加如下:
-keep class com.pn.sdk.** {*;}

                        

SDK API使用说明

初始化SDK

		
请确保在 Launcher Activity OnCreate 函数中初始化SDK

protected void onCreate(Bundle savedInstanceState) {

    String appID  = "APPID";
    String appKey = "APPKEY";
    String channel  = "渠道标识";
    
    Map extraMap = new HashMap();
    extraMap.put("termAgreed", true或者false);

    //termAgreed为true,表明游戏在调用startWithAppID之前用户已经同意过条款,该条款由游戏自行处理。
    //termAgreed为false,使用SDK条款页面。
    //extraMap为null,默认使用SDK条款页面。

PnSDK.startWithAppID(activity , appId, appKey, channel, "cn", extraMap); } 所需要的参数,可以在对接说明文档中找到.

重写Activiy中onNewIntent方法

        
请确保在 Launcher Activity onNewIntent 函数中调用SDK的onNewIntent接口

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    PnSDK.onNewIntent(this, intent);
}
        
    

广播监听

		

<实现广播接收器>

public class MyBroadcastReceiver extends BroadcastReceiver { final String TAG = "MyBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction();
if (TextUtils.equals(action, "PnSDKPassportNotification")) { // 通行证状态发生变化, 已登录或者已登出 Log.v(TAG, "游戏接收到广播:PnSDKPassportNotification"); Map accountInfoMap = PnSDK.getAccountInfo(); if (null == accountInfoMap) { Log.d(TAG, "游戏接收到PnSDKPassportNotification广播,账户没登录不向下执行代码"); //TODO 没有登录 return; } String uid = (String) accountInfoMap.get("uid");// 获取用户唯一ID String jwt = (String) accountInfoMap.get("jwt");// 登录凭证 int age = (int) accountInfoMap.get("age"); // 实名制用户年龄, 未登记返回为0 String idmd5 = (String) accountInfoMap.get("idmd5"); // 实名制用户身份证md5, 未登记返回为“” String aaStatus = (String) accountInfoMap.get("aa-status");// 防沉迷状态, 返回 "restricted" 禁止继续游戏 int guest = (int) accountInfoMap.get("guest"); // 是否游客,1为游客,0为其它账号或者已绑定游客 Log.d(TAG, "PnAccountInfo ,uid: " + uid + " jwt: " + jwt); //TODO 客户端需要将 jwt 登录凭证上传至游戏服务器, 游戏服务器再通过SDK服务器 验证接口 进行验证,以确保登录账号合法。 return; }
if (TextUtils.equals(action, "PnSDKPaymentNotification")) { //TODO 充值结束(返回充值信息) Log.v(TAG, "游戏接收到广播:PnSDKPaymentNotification"); String productid = intent.getStringExtra("productid"); String nonce = intent.getStringExtra("nonce"); String orderid = intent.getStringExtra("orderid"); String transactionid = intent.getStringExtra("transactionid"); if (TextUtils.isEmpty(productid)) { // 用户取消 或者 充值失败 或者 拉取了第三方充值 // 通常情况下,客户端不需要做任何处理,不要弹出充值失败等提示 } else { Log.d(TAG, "游戏广播接收,充值成功 " + productid); //TODO 充值成功 } return; } if (TextUtils.equals(action, "PnSDKTermNotification")) { //TODO 条款广播(注意:该通知可能会收到多次) Log.v(TAG, "游戏接收到广播:PnSDKTermNotification"); if (PnUtils.termAgreed()) { //todo 同意条款 } else { //todo 拒绝条款 } } } }

<在主页面注册广播>

public class MainActivity extends Activity { private MyBroadcastReceiver myBroadcastReceiver; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); myBroadcastReceiver = new MyBroadcastReceiver(); IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction("PnSDKPassportNotification"); intentFilter.addAction("PnSDKPaymentNotification"); intentFilter.addAction("PnSDKTermNotification"); if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //Android14(34)及以上必须添加标记 registerReceiver(myBroadcastReceiver, intentFilter , Context.RECEIVER_NOT_EXPORTED); }else { registerReceiver(myBroadcastReceiver, intentFilter); } } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); //... PnSDK.onActivityResult(requestCode, resultCode, data); } @Override protected void onDestroy() { super.onDestroy(); unregisterReceiver(myBroadcastReceiver); } }

登录通行证

		
PnSDK.signIn(activity);
		
	

切换账号

		
// 首先登出当前账号
PnSDK.signOut(activity);

// 紧接着调登入接口
PnSDK.signIn(activity);
        
	

客服中心

游戏必须接入SDK的客服中心,建议在游戏内设置界面和登录界面放置客服中心按钮,详情需求请参阅对接说明文档。


若未登录游戏服务器,服务器ID 请传入 "none"
若游戏角色未登录,角色昵称 请传入 "not logged in"
extraMap 扩展参数 需增加roleid(角色ID), level(角色等级)参数,角色未登录时可为NULL

Map extraMap = new HashMap();
extraMap.put("roleid", 角色ID);
extraMap.put("level", 角色等级);
...

PnSDK.bugReport(activity, "服务器ID", "角色昵称", "游戏客户端版本号", extraMap);


						

帐号管理


//帐号管理主要提供 账号绑定, 重置游客 等功能, 建议在游戏设置界面中放置 帐号管理 按钮

extraMap 扩展参数 需增加roleid(角色ID), level(角色等级)参数,角色未登录时可为NULL

Map extraMap = new HashMap();
extraMap.put("roleid", 角色ID);
extraMap.put("level", 角色等级);
...

PnSDK.userCenter(activity, "服务器ID", "角色昵称", "游戏客户端版本号", extraMap);


						

事件埋点


// 事件标识 详细说明请查阅对接说明文档

PnSDK.evtTrack(activity,"eventName");

						

评分接口


//用户评分接口的使用时机,请参阅对接说明文档

若未登录游戏服务器,服务器ID 请传入 "none"
若游戏角色未登录,角色昵称 请传入 "not logged in"
extraMap 扩展参数 需增加roleid(角色ID), level(角色等级)参数

Map extraMap = new HashMap();
extraMap.put("roleid", 角色ID);
extraMap.put("level", 角色等级);
...

PnSDK.appReview(activity, "服务器ID", "角色昵称", "游戏客户端版本号", extraMap);

						

系统回调

实现系统回调,否则SDK无法正常工作

onActivityResult

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

微信登录&微信支付

正常使用微信功能,必须完成以下操作

        
在{$applicationId}.wxapi目录下新增两个类:
1、WXEntryActivity类,该类必须继承 com.pn.sdk.wxapi.BaseWXEntryActivity,不需要实现任何功能。
2、WXPayEntryActivity类,该类必须继承 com.pn.sdk.wxapi.BaseWXPayEntryActivity,不需要实现任何功能。
(例如{$applicationId}为 com.xx.xxx,则新添加类的位置如下图所示)

充值接入说明

充值界面由游戏开发方提供.

充值项的设定,请参阅对接说明文档.

充值


product        充值产品ID
srvid          服务器ID
nonce 透传参数  充值透传参数,SDK充值平台会原样传回到游戏服务器,,详见支付服务器对接
extraMap       扩展参数 需增加roleid(角色ID), level(角色等级)参数

Map extraMap = new HashMap();
extraMap.put("roleid", 角色ID);
extraMap.put("level", 角色等级);
    ...
PnSDK.payWithProductID(activity, "产品ID", "服务器ID", "nonce 透传参数", extraMap);

// 充值完成后, SDK会发送广播PnSDKPaymentNotification, 查看 广播监听 说明

						

注意

收到 PnSDKPaymentNotification 回调不代表充值已到账,以游戏服务端收到SDK充值平台回调为准.

充值流程图

进阶

本地推送


本地推送说明:

1. 原则上无互动性的消息,都应该使用本地推送
2. 服务器推送仅使用在交互性的消息上

						

设置推送


// 延迟60秒后弹出推送 
PnSDK.setNotification("推送ID", 60, "通知标题", "通知内容", null);

// 特定时间弹出推送
SimpleDateFormat formatter = new SimpleDateFormat(“yyyy-MM-dd HH:mm:ss”);
Date date = null;
try {
    date = formatter.parse("2021-10-01 12:00:00");
} catch (ParseException e) {
    e.printStackTrace();
}
if(null != date){
    PnSDK.setNotification("推送ID" , date , "通知标题" , "通知内容" , null);
}


						

移除推送


// 移除ID为 @"推送ID1", @"推送ID2" 的本地推送
List idList = new ArrayList<>();
idList.add("推送ID1");
idList.add("推送ID2");
PnSDK.deleteNotifications(idList);
            
// 移除所有本地推送
PnSDK.deleteNotifications(null);


						

其它接口

服务接口


service         服务名
Map extraMap    扩展参数,角色未登录时可为NULL

Map extraMap = new HashMap();
extraMap.put("roleid", "角色ID");
extraMap.put("nickname", "角色昵称");
...

PnSDK.openService(this, "服务名", extraMap);

                        
服务名 extraMap 参数 说明
survey roleid 角色ID(可选)
nickname 角色昵称(可选)
打开调查问卷
terms 打开服务条款
privacy 打开隐私条款
privacy_teen 打开防沉迷提示

聊天室屏蔽规则


聊天屏蔽規則:

1,对指定等级做屏蔽字限制;
2,对等级高于我们设定值的玩家不做限制;
3,被屏蔽发言自己客户端可正常显示,无特殊提示;
4,被屏蔽的发言整句都不显示在聊天频道,触发屏蔽的玩家和其他玩家都无法得知是哪句话触发了屏蔽


舉例:
我們限制等級15級以下的玩家,聊天有限制

15級以下的玩家,如果聊天中包涵:line,LINE,=,元寶,等字眼,他所發的消息,就只有他自己看得到,其他玩家是收不到了。

						

激励广告

配置

  1. 应用级build.gradle中添加依赖项:

            
    dependencies {
        // ...
        implementation 'com.pn:pnsdk-cn:+'
        implementation 'com.pn.pnsdk:res-[APPID]:+'
        //其中[APPID]请替换为实际参数,参数可以在提供的对接说明文档中找到
    
        implementation 'com.pn:csj-bridge:+'
    }
       
    

显示广告

            
                
extraMap 扩展参数,传入null 

PnSDK.showAdWithExtra(activity , null);
                

            

广告状态监听

        

<实现广播接收器>

public class MyBroadcastReceiver extends BroadcastReceiver { final String TAG = "MyBroadcastReceiver"; @Override public void onReceive(Context context, Intent intent) { String action = intent.getAction(); if (TextUtils.equals(action, "PnSDKAdRewardsNotification")) { Log.v(TAG, "游戏接收到广播:" + "PnSDKAdRewardsNotification"); String status = intent.getStringExtra("status"); Log.d(TAG , "广告状态:" + status); if(TextUtils.equals(status , "cancel")){ Log.d(TAG , "无广告,取消显示"); return; } if(TextUtils.equals(status , "start")){ Log.d(TAG , "广告显示开始"); return; } if(TextUtils.equals(status , "complete")){ Log.d(TAG , "广告显示结束"); return; } if(TextUtils.equals(status , "reward")){ Log.d(TAG , "玩家已观看广告,需发送广告奖励"); String label = intent.getStringExtra("label"); int amount = intent.getIntExtra("amount" , -1); Log.d(TAG , "label: " + label + " amount: " + amount ); //todo 发放奖励 } } } }

常见问题

compileSdkVersion从33升级到34问题

报错:One of RECEIVER_EXPORTED or RECEIVER_NOT_EXPORTED should be specified when a receiver isn't being registered exclusively for system broadcasts
原因:以 Android 14(API级别34)或更高版本为目标平台并使用上下文注册的接收器的应用和服务必须指定一个标志,以指明接收器是否监听其他应用的广播: 分别为 RECEIVER_EXPORTED(接收所有系统广播,包括本应用的广播) 或 RECEIVER_NOT_EXPORTED(只接收本应用的广播)。
解决:
    
参考代码:

IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction("XXXXXX");

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
    //Android14(34)及以上必须添加标记
    registerReceiver(broadcastReceiver, intentFilter , Context.RECEIVER_NOT_EXPORTED);
}else {
    registerReceiver(broadcastReceiver, intentFilter);
}


    

新建项目按照文档不能正常接入问题

由于Android studio的“北极狐”版本新建项目时,生成的Gradle是最新版本,并且build.gradle文件和setting.gradle文件中内容和sdk对接方式有冲突。 修改方法:
  1. 清空项目级build.gradle中的配置,然后参考build.gradle配置
  2. 删除应用级build.gradle中的依赖:implementation 'androidx.appcompat:appcompat:版本号'
  3. settings.gradle文件中只保留:
    rootProject.name = "项目名"
    include ':app'
    
  4. 修改Gradle版本配置

Gradle插件版本过低不匹配

为适配Android 11中的软件包可见性,SDK中的清单文件中添加了<queries>元素。
该元素要求Android Gradle插件版本为4.1及更高版本(建议参考:Gradle版本配置 升级至4.1.0+),为了兼容较低版本,针对 Android Gradle插件3.3及更高版本发布一组补丁程序。

如果您使用的是旧版AGP并且升级4.1.0+有困难,请升级到以下某个版本:

如果您使用的Android Gradle插件版本... 请升级到
4.0.* 4.0.1
3.6.* 3.6.4
3.5.* 3.5.4
3.4.* 3.4.3
3.3.* 3.3.3

更新说明

SDK在2025-06-16日支持targetSdk 35,游戏在升级targetSdk时需要注意编译工具的版本问题:

官方说明: Android 15 SDK 包含与某些较低版本的 Android Studio 不兼容的变更。 为了获得 Android 15 SDK 的最佳开发体验,请使用 Android Studio Koala 功能更新 | 2024.1.2 或更高版本。 并要求Android Gradle插件版本为8.6.1 或更高版本。
为了更好的版本兼容,推荐使用以下版本:
                            
1、推荐Android Studio Meerkat | 2024.3.1 (支持Gradle plugin8.8.2)  


2、升级Gradle Plugin至8.8.2
3、升级Gradle 至8.10.2 (gradle-8.10.2-all)
(您可以在 Android Studio 的 File > Project Structure > Project 菜单中查看或指定插件版本)


4、SDK Build Tools 35.0.0
5、JDK 17
6、miniSDK Version 24
7、compile Version 35