本文介绍了接入小程序小游戏的流程和部分使用小程序小游戏的内容。
前置条件
创建应用并下载配置文件。
详情请参考 扫码测试适配。
添加小程序小游戏 SDK 前,请确保已经接入工程到 mPaaS。详情请参考 将 mPaaS 添加到您的项目中。
添加 SDK
基线版本
小程序小游戏支持自定义基线版本 cp_change_114400936。请参照 选择合适的基线 指南,添加 cp_change_114400936 基线以完成配置。

安装组件和依赖
修改项目根目录 build.gradle
增加 mvn 仓库。
maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } maven { credentials { username "mvn_read_ws" password "mrk8929" } url "http://mvn.cloud.alipay.com/nexus/content/repositories/releases/" } maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'http://maven.aliyun.com/nexus/content/repositories/google/' name 'aliyun-google' } maven { credentials { username '617696fc6970513e6e677c83' password '2qAa=hHdfLOp' } url 'https://packages.aliyun.com/63dc774a9dee9309492b993a/maven/repo-jpkdy' }在 buildscript 中增加配置。
buildscript { ext.mpaas_artifact = "mpaas-baseline-cp_change_56100909" ext.mpaas_baseline = "23" repositories { mavenLocal() maven { url 'http://maven.aliyun.com/nexus/content/groups/public/' } maven { url 'http://maven.aliyun.com/nexus/content/repositories/google' } maven { credentials { username "mvn_read_ws" password "mrk8929" } url "http://mvn.cloud.alipay.com/nexus/content/repositories/releases/" } google() maven { url 'http://maven.aliyun.com/nexus/content/repositories/google/' name 'aliyun-google' } } dependencies { classpath 'com.android.boost.easyconfig:easyconfig:2.6.7' // 根据项目实际gradle版本修改版本号 classpath 'com.android.tools.build:gradle:4.0.1' // 使用项目实际的gradle版本 } }
申请游戏依赖的 mPaaS 内核 key
申请游戏依赖的 mPaaS 内核 key 请参考 接入 mPaaS 内核。
修改 app 下的 build.gradle
增加依赖和 configuration。
android {
...
configurations {
all*.exclude group: 'com.mpaas.mriver', module: 'mriveruc-build' // 移除
all*.exclude module: 'nebulaucsdk-build'
}
}
dependencies {
...
implementation platform("com.mpaas.android:$mpaas_artifact:$mpaas_baseline")
implementation 'com.mpaas.android:minigame' // 小游戏
}初始化 mPaaS
在使用 mPaaS 框架前需要进行一些初始化操作对 Application 对象进行改造。由于是否使用热修复功能会采取不同的初始化内容,因此本文将根据是否使用热修复功能分别向您介绍相应的初始化操作。
不使用热修复功能
不使用 热修复 功能时,只需在 Application 中添加如下代码:
@Override
public void onCreate() {
super.onCreate();
MP.init(
this,
MPInitParam.obtain().setCallback(new MPInitParam.MPCallback() {
@Override
public void onInit() {
Log.d("TAG", "mPaaS Init finish");
}
})
);
}如果您集成使用 Kotlin 的话,可以使用 mPaaS 提供的 mPaaS KTX,详情参考 mPaaS Kotlin 扩展。
如果您需要继续使用 QuinoxlessFramework 初始化方式,您的调用不会受到任何影响,代码和业务不需要做任何更改。
请不要在使用 MP.init 方法前过滤进程,除主进程外,在 tools 和 push 子进程中也需要执行初始化代码。
使用热修复功能
使用 热修复 功能时,需要完成以下操作。
操作步骤
使 Application 对象重新继承
QuinoxlessApplicationLike,并注意将此类防混淆。此处以 “MyApplication”为例。@Keep public class MyApplication extends QuinoxlessApplicationLike implements Application.ActivityLifecycleCallbacks { private static final String TAG = "MyApplication"; @Override protected void attachBaseContext(Context base) { super.attachBaseContext(base); Log.i(TAG, "attacheBaseContext"); } @Override public void onCreate() { super.onCreate(); Log.i(TAG, "onCreate"); registerActivityLifecycleCallbacks(this); } @Override public void onMPaaSFrameworkInitFinished() { LoggerFactory.getTraceLogger().info(TAG, getProcessName()); } @Override public void onActivityCreated(Activity activity, Bundle savedInstanceState) { Log.i(TAG, "onActivityCreated"); } @Override public void onActivityStarted(Activity activity) { } @Override public void onActivityResumed(Activity activity) { } @Override public void onActivityPaused(Activity activity) { } @Override public void onActivityStopped(Activity activity) { } @Override public void onActivitySaveInstanceState(Activity activity, Bundle outState) { } @Override public void onActivityDestroyed(Activity activity) { }}在
AndroidManifest.xml文件中将 Application 对象指向 mPaaS 提供的Application对象。 将生成的 “MyApplication” 类添加到 key 为mpaas.quinoxless.extern.application的meta-data中。示例如下:<application android:name="com.alipay.mobile.framework.quinoxless.QuinoxlessApplication" > <meta-data android:name="mpaas.quinoxless.extern.application" android:value="com.mpaas.demo.MyApplication" /> </application>引入 Apache HTTP 客户端。
在使用 RPC 或者热修复功能的时候,需要调用到 Apache HTTP 客户端相关的功能。只需在
AndroidManifest.xml加入如下代码。更多信息,请参见 使用 Apache HTTP 客户端。<uses-library android:name="org.apache.http.legacy" android:required="false"/>
API
初始化
import android.app.Application;
import android.util.Log;
import com.mpaas.core.MP;
import com.mpaas.core.MPInitParam;
import com.mpaas.mas.adapter.api.MPLogger;
import com.mpaas.mriver.api.init.MriverInitParam;
import com.mpaas.mriver.nebula.api.uc.MRUCInitCallback;
import com.mpaas.mriver.nebula.api.uc.MRUCService;
import com.mpaas.mriver.xriver.XRiver;
import com.mpaas.uc.dynamic.api.MPUCDynamicInit;
public class MRiverApp extends Application implements MPInitParam.MPCallback{
private static final String TAG = "MRiverApp";
@Override
public void onCreate() {
super.onCreate();
MP.init(this, createInitParams());
}
@Override
public void onInit() {
MPLogger.setUserId("xxxx"); // 设置userId,用来白名单灰度、IDE扫码预览使用
}
MPInitParam createInitParams() {
final MriverInitParam mriverInitParam = MriverInitParam.getDefault();
mriverInitParam.setMriverInitCallback(new MriverInitParam.MriverInitCallback() {
@Override
public void onInit() {
XRiver.init();
}
@Override
public void onError(Exception e) {
}
});
return MPInitParam.obtain().setCallback(this).addComponentInitParam(mriverInitParam);
}
}配置拦截 RPC(广告依赖)
//初始化完成时
Mriver.setProxy(MRGameRpcProxy.class, new MRGameRpcProxy() {
@Override
public boolean rpc(String s, Object o, JSONObject jsonObject, App app, Page page, int i, String s1, boolean b, BridgeCallback bridgeCallback) {
if (!TextUtils.isEmpty(s) && s.contains("querygamedefaultad")) {
JSONObject data = new JSONObject();
data.put("success", false);
bridgeCallback.sendJSONResponse(data);
}
return true;
}
});启动游戏
XRiver.startApp("appId"); // appId表示后台发布的游戏id账号授权
客户端注入 my.getAuthCode() 能力
初始化完成后设置 proxy。在客户端注入 my.getAuthCode() 能力,直接返回的 openId 即为游戏所需要的用户 ID。
Mriver.setProxy(RVOpenAuthProxy.class, new RVOpenAuthProxy() {
@Override
public void getAuthAccountInfo(Context context, List<String> list, String s, boolean b, Page page, IAuthCallback iAuthCallback) {
// ignore
iAuthCallback.onSuccess(BridgeResponse.SUCCESS.get());
}
@Override
public void auth(Context context, Page page, String sessionId, List<String> scope, Map<String, String> map, boolean b, Bundle bundle, IAuthCallback iAuthCallback) {
// handle authCode request
// auth_base表示静默授权,不会弹申请窗;auth_user会弹出申请弹窗
if (scope != null && (scope.contains("auth_user") || scope.contains("auth_base")) && page.getApp() != null) {
String appId = page.getApp().getAppId();
// 从App服务端获取authCode/openId
String authCode = requestAuthCodeFromSuperAppServer(appId);
String openId = requestOpenIdFromSuperAppServer(appId);
if (!TextUtils.isEmpty(authCode)) {
JSONObject jsonObject = new JSONObject();
jsonObject.put("authCode", authCode);
jsonObject.put("openId", openId); // 返回openId
iAuthCallback.onSuccess(jsonObject); // callback to miniprogram
} else {
iAuthCallback.onFail(-1, "auth code request err");
}
}
}
@Override
public boolean appxRpc(JSONObject jsonObject, BridgeCallback bridgeCallback) {
// ignore
bridgeCallback.sendJSONResponse(BridgeResponse.SUCCESS.get());
return true;
}
});广告
方式一
内置穿山甲模式,只需配置广告位。注册获取广告信息的接口,注入广告数据。
Mriver.setProxy(MRGameAdProxy.class, new MRGameAdProxy() {
/**
* appId: 小游戏id
* adType: 广告类型: 0 激励视频广告; 1 banner广告; 2 插屏/全屏广告
**/
@Override
public void getGameAdInfo(String appId, App app, int adType, GameAdInfoCallback callback) {
Map<String, String> adInfo = new HashMap();
if (adType == 1) {
adInfo.put("code", "xxx"); // 添加广告位信息
} else {
}
if (callback != null) {
callback.onCallback(adInfo);
}
}
});方式二
自定义广告显示。
Mriver.setProxy(MiniAdShowProxy.class, new MiniAdShowProxy() {
@Override
public void showAd(String s, Page page, int i, MiniGameAdShowCallback miniGameAdShowCallback) {
}
});数据埋点监听
初始化时设置数据埋点监听。
Mriver.setProxy(PaladinGameTracker.class, new PaladinGameTracker() {
@Override
public void gamePageAppear(Activity activity, String appId, String subPageToken, String channelInfo) {
// 游戏第一次打开或者页面从后台切换到前台
Log.i(TAG, "gamePageAppear: " + appId);
}
@Override
public void gamePageDisappear(Activity activity, String appId, String subPageToken, String channelInfo) {
// 游戏退出或者切换到后台
Log.i(TAG, "gamePageDisappear: " + appId);
}
});关卡上报
本功能专为闯关类游戏设计,适用于具有明确关卡规则与进度体系的场景。
注册自定义 Bridge
MriverEngine.registerBridge(ReportGameStatusExtension.class);实现 ReportGameStatusExtension
package com.mpaas.demo.tinyapp;
import android.util.Log;
import com.alibaba.ariver.app.api.App;
import com.alibaba.ariver.app.api.Page;
import com.alibaba.ariver.engine.api.bridge.extension.BridgeCallback;
import com.alibaba.ariver.engine.api.bridge.extension.BridgeResponse;
import com.alibaba.ariver.engine.api.bridge.extension.annotation.BindingApiContext;
import com.alibaba.ariver.engine.api.bridge.extension.annotation.BindingCallback;
import com.alibaba.ariver.engine.api.bridge.extension.annotation.BindingNode;
import com.alibaba.ariver.engine.api.bridge.extension.annotation.BindingRequest;
import com.alibaba.ariver.engine.api.bridge.model.ApiContext;
import com.alibaba.ariver.kernel.api.annotation.ActionFilter;
import com.alibaba.ariver.kernel.api.annotation.NativeActionFilter;
import com.alibaba.ariver.kernel.api.extension.bridge.BridgeExtension;
import com.alibaba.ariver.kernel.api.security.Permission;
import com.alibaba.ariver.kernel.common.utils.JSONUtils;
import com.alibaba.fastjson.JSONObject;
public class ReportGameStatusExtension implements BridgeExtension {
private static final String TAG = "ReportGameExtension";
public ReportGameStatusExtension() {
}
@ActionFilter
@NativeActionFilter
public void reportGameStatus(@BindingApiContext ApiContext apiContext, @BindingNode(App.class) App app, @BindingNode(Page.class) Page page, @BindingRequest JSONObject params, @BindingCallback final BridgeCallback bridgeCallback) {
JSONObject reportData = JSONUtils.getJSONObject(params,"data", null);
if (reportData == null) {
bridgeCallback.sendBridgeResponse(BridgeResponse.INVALID_PARAM);
return;
}
// 从启动参数读取 ad schema
Log.i(TAG, "reportData: " + reportData.toJSONString());
bridgeCallback.sendBridgeResponse(BridgeResponse.SUCCESS);
}
public void onInitialized() {
}
public void onFinalized() {
}
public Permission permit() {
return null;
}
}
以下是 ReportGameStatusExtension 上报时打印的 reportData 典型 JSON 结构。
{
"currentLevel": 4, // 当前正在挑战的关卡编号
"duration": 23, // 本局游戏持续时长 (单位:秒/毫秒,需根据协议确认)
"passedLevels": 3 // 已成功通关的关卡总数
}游戏行为上报
新增小游戏进度上报功能:基于 gameMessage 统一通道,action 字段实现事件路由,payload 字段透传行为ID与累计值。
上报 API
my.call('gameMessage', {
data: {
action: 'action_task_report', //行为任务上报固定为 action_task_report
payload: {
actionTaskEvent: 'catch_pigs', //行为任务标识
value: 10 //当前累计行为量
}
}
});数据字段说明
字段名 | 中文名称 | 说明 |
| 消息路由类型 | 行为任务上报固定为 |
| 上报数据 | 参数格式约束:必须直接传递原生 JSON 对象, |
| 行为任务标识 | 具体行为的唯一标识,需与平台协商约定,并与任务配置保持一致。 |
| 当前累计值 | 当前统计周期内该行为的累计值,必须为非负安全整数。 |
外层
action必须固定为action_task_report,严禁用于区分具体游戏行为。系统将自动忽略非法、重复或数值倒退的上报数据;跨会话累计值需由 CP 自行维护并上报最新状态。
对接前请务必与平台对齐以下要素:
actionTaskEvent标识、行为定义、触发时机、累计口径及重置周期。payload.value须传入当前累计总值(非增量)。例如完成第3次时,应依次上报 1、2、3。