tencent cloud

Superapp 实践教程

PDF
聚焦模式
字号
最后更新时间: 2026-03-22 09:54:59

1. 初始化

继承并实现 MiniConfigProxy 类。
MiniConfigProxy 的实现类,添加注解如下:
@ProxyService(proxy = MiniConfigProxy.class)
参考代码如下:
@ProxyService(proxy = MiniConfigProxy.class)
public class MiniConfigProxyImpl extends MiniConfigProxy {
/**
* 获取 superapp 的 Application 实例
* 注意:1. 小程序是多进程架构,请确保子进程也可以正常获取到 Application 实例。
* 2. Applicaton实例缓存建议在 Application.attachBaseContext 中进行,
* 避免因为组件时序问题导致 SDK 获取到空的 Application 实例。
* @return
*/
@Override
public Application getApp() {
//必须使用 superapp 的 Application 实例
return "your superapp Application";
}

/**
* 创建初始化配置信息
* @return
*/
@Override
public MiniInitConfig buildConfig() {
MiniInitConfig.Builder builder = new MiniInitConfig.Builder();
MiniInitConfig config = builder
.configAssetName("tcsas-android-configurations.json") // assets中配置文件名称
.autoRequestPermission(true) // 配置小程序使用到需要权限的API时是否自动向用户申请对应的系统权限
.debug(true) // 日志开关,默认关闭的
.build();
return config;
}
}
注意:
1. MiniInitConfig 的 configAssetName 用于指定配置文件在源码工程中的路径和名称。
2. 由于 SDK 最早会在内部 ContentProvider 中获取 superapp 的 Application 实例,因此 Application 实例缓存建议在 Application.attachBaseContext 方法中进行,可以避免因为时序问题导致 SDK 获取到空的 Application 实例。
至此,小程序 SDK 的接入就完成了。下一步可通过小程序 SDK 提供的 API 实现小程序的打开和预览。

2. 打开小程序

打开小程序时,会先判断本地是否有缓存的小程序,如果没有,则会自动从远程服务器上下载小程序,然后打开。如果有缓存的小程序,则会先打开本地小程序,同时后台校验服务器端是否有新版本。
说明:
如果有新版本,则下载新版小程序,下次打开时,就会使用新版小程序。
启动参数说明:
/**
* 打开小程序时是否强制检查更新(冷启动时有效),false:优先使用本地缓存,同时异步获取最新数据;true:待网络返回后才打开小程序
*/
public boolean isForceUpdate = false;
/**
* 入口地址,支持添加参数:path?key=value&key1=value1
*/
public String entryPath;
/**
* 接收小程序启动过程中错误信息
*/
public ResultReceiver resultReceiver;

/**
* 小程序启动参数
*/
public String params;

/**
* 设置打开小程序时使用的任务模式
*
* false: 多任务模式,true: 为单任务模式
*/
public boolean isSingleTask;
通过小程序 ID 启动。
//通过小程序ID打开小程序
//
TmfMiniSDK.startMiniApp(activity, appId, new MiniStartOptions());

2.1 根据小程序ID(appId)打开小程序

在 Superapp 首页列表中,可打开正式版本(通过审核并已经发布上线)的小程序。参考如下代码:
TmfMiniSDK.startMiniApp(activity, appId, miniStartOptions);
说明:
appId 字段为小程序的 ID,需要通过小程序开发者或者小程序搜索接口获取。

2.2 扫码打开小程序

小程序 SDK 提供根据平台二维码内容打开小程序的接口;在使用小程序 SDK 提供的扫码能力前,需要提前接入扫一扫的扩展能力,扫码能力的接入可以参考:扫码扩展SDK
TmfMiniSDK.startMiniAppByScan(activity);
小程序支持通过URL跳转的方式由第三方应用和扫码工具打开。使用该能力前需要先配置 superapp 的URL Scheme,在 superapp 中添加以下字符串资源:
<string name="mini_sdk_intent_filter_scheme">your scheme</string>
其中 your scheme 部分应当替换为 superapp 的 Scheme。
小程序 URL 的 host 固定为 applet,URL 的完整格式为:${scheme}://applet?appid=${appId}&path=${encode过的path}&param=${encode过的param}。URL 中每个参数的定义如下:
参数名
类型
是否必填
说明
appId
String
小程序 ID
path
String
小程序入口路径,需要进行URI编码
param
String
传递给小程序的 query,需要进行URI编码
产品控制台会为所有正式版小程序创建对应的 URL,并根据该 URL 生成二维码。控制台创建 URL 时默认会使用 tcmpp+superapp 的 appKey 作为 Scheme。



为了保证控制台生成正确的URL,应当将实际的superapp URL Scheme配置到控制台中。点击下方的修改按钮即可更改生成URL时使用的Scheme:

配置完毕后用户可以直接扫描生成的二维码,或是通过URL跳转打开对应的小程序。

3. 小程序列表展示

3.1 使用搜索接口获取全部小程序

小程序 SDK 提供线上小程序搜索的接口,可以通过此接口对小程序按关键字和分类进行搜索。若关键字和分类传入为空时,则返回所有小程序。
说明:
SearchOptions 参数用于指定小程序搜索的关键字和分类信息。
MiniCallback 参数用于获取小程序的搜索结果。
/**
* 小程序搜索
*
* @param searchOptions
* @param callback
*/
public static void searchMiniApp(SearchOptions searchOptions, MiniCallback<List<MiniApp>> callback)

3.2 获取之前使用过的小程序

小程序 SDK 提供以下 API 用于访问最近使用的小程序列表。
/**
* 获取最近访问小程序列表
* @param callback
*/
public static void getRecentList(IRecentMiniCallback callback)

4. 语言切换

SDK 引擎目前支持简体中文、繁体中文、英语、法语、阿拉伯语、印尼语。小程序可通过 MiniAppProxy 接口设置语言。
// 实现 MiniAppProxy 接口
public class YourMiniAppProxyImpl extends BaseMiniAppProxyImpl {
@Override
public Locale getLocale() {
// 返回你想要设置的语言
return Locale.SIMPLIFIED_CHINESE; // 简体中文
// 或 return Locale.US; // 英文
// 或 return new Locale("ar", "SA"); // 阿拉伯语
// 或 return new Locale("in", "ID"); // 印尼语
// 或 return Locale.FRANCE; // 法语
}
}

5. 账号切换

小程序 SDK 提供开放接口,用于调用和实现登录、获取用户信息、支付等Superapp提供的能力。
注意:
返回值是用户账号(必须唯一),设置后数据会按账号隔离存储,一般填 uin 或 openid。该账号也会用于登录、用户信息获取、支付等 开放接口 流程中。
/**
* 用户账号,必须唯一,设置后数据会按账号隔离存储, 一般填 uin 或 openid
*/
@Override
public String getAccount() {
return "tmf_test";
}
注意:
当用户退出登录时,需要调用终止小程序,避免小程序沙盒数据在不同用户间交叉共享,示例代码:
TmfMiniSDK.stopAllMiniApp(MainActivity.this);

6. 胶囊定制

6.1 定制关闭按钮事件监听

定制胶囊按钮的关闭事件监听,能够让 superapp 在关闭按钮点击时获取到对应的回调事件。
关闭按钮示意图:

API 说明:onCapsuleButtonCloseClick方法返回值表示是否自定义关闭按钮监听,返回值为 true 表示自定义,false(默认值)表示使用默认监听。
/**
* 点击胶囊按钮的关闭选项
* 调用环境:子进程
*
* @param miniAppContext 小程序运行环境(小程序进程,非主进程)
* @param onCloseClickedListener 点击小程序关闭时回调
* @return 不支持该接口,请返回false
*/
public abstract boolean onCapsuleButtonCloseClick(IMiniAppContext miniAppContext,
DialogInterface.OnClickListener onCloseClickedListener);

6.2 定制更多按钮事件监听

定制更多按钮的事件监听,能够让 superapp 在更多按钮点击时监听到对应回调事件。
更多按钮示意图:



API 说明:onCapsuleButtonMoreClick 方法返回值表示是否自定义更多按钮监听,返回值为 true 表示自定义,false(默认值)表示使用默认监听。
/**
* 点击胶囊按钮的更多选项
*
* @param miniAppContext 小程序运行环境
* @return 不支持该接口,请返回false
*/
public abstract boolean onCapsuleButtonMoreClick(IMiniAppContext miniAppContext);

6.3 定制更多按钮展示列表

当用户触发更多按钮点击事件时,会弹出如下的可选扩展按钮列表,默认列表示意图如下:

通过重写 MiniAppProxy 的 getMoreItems 方法,可以实现定制更多菜单扩展按钮列表。
API 说明:
getMoreItems 方法返回值表示定制的扩展按钮列表;
方法参数 MoreItemList.Builder 用于添加扩展按钮,扩展按钮的展示顺序和添加顺序一致;
MoreItem的id属性用于区分按钮,需要具备唯一性。
/**
* 返回胶囊更多面板的按钮,扩展按钮的ID需要设置为[100, 200]这个区间中的值,否则,添加无效
* 调用环境:子进程
*
* @param builder
* @return
*/
public abstract ArrayList<MoreItem> getMoreItems(MoreItemList.Builder builder);

警告:
扩展按钮的ID需要设置为[100, 200]这个区间中的值,否则,添加无效。
示例代码:
@Override
public ArrayList<MoreItem> getMoreItems(IMiniAppContext miniAppContext, MoreItemList.Builder builder) {
MoreItem item1 = new MoreItem();
// 设置菜单id(必须),扩展按钮的ID需要设置为[100, 200]这个区间中的值,否则,添加无效。
item1.id = ShareProxyImpl.OTHER_MORE_ITEM_1;
// 设置菜单标题(可选)
item1.text = getString(miniAppContext, R.string.applet_mini_proxy_impl_other1);
// 设置菜单图标(可选)
item1.drawable = R.mipmap.mini_demo_about;
// 设置无障碍描述(可选), 默认是菜单标题
item2.contentDescription = "菜单无障碍描述";
// 监听点击事件
item2.onClickListener = new MoreItem.MoreItemClickListener() {
@Override
public void onClick(IMiniAppContext context, MoreItem item) {
// 处理点击事件
}
};

// 自行调整顺序。
builder.addMoreItem(item1)
// 根据需求添加内置菜单项
.addRestart(getString(miniAppContext, R.string.applet_mini_proxy_impl_restart),
R.mipmap.mini_demo_restart_miniapp)
// 根据需求添加内置菜单项
.addAbout(getString(miniAppContext, R.string.applet_mini_proxy_impl_about),
R.mipmap.mini_demo_about)
// 根据需求添加内置菜单项
.addSetting(getString(miniAppContext, R.string.mini_sdk_more_item_setting_0),
R.drawable.mini_sdk_setting,
//设置无障碍描述(可选), 默认是菜单标题
"小程序设置");
return builder.build();
}

private String getString(IMiniAppContext miniAppContext, int id) {
return miniAppContext.getContext().getString(id);
}

7. 小程序内部 UI

SDK 也支持小程序内部使用的 UI 自定义显示。
小程序 API
AbsMiniUiProxy 方法
wx.showLoading
/**
* 自定义小程序检查更新loading页面
* 调用环境:主进程
*
* @param context
* @return
*/
public abstract IMiniLoading updateLoadingView(Context context);
wx.showToast
/**
* Toast展示接口
* @param activity 当前 Activity
* @param pageRoot 当前页面根 ViewGroup
* @param toastInfo Toast 信息
* @return 返回 Toast 实例
*/
IToast showToast(Activity activity, ViewGroup pageRoot, ToastInfo toastInfo);
wx.showActionSheet
/**
* 通用 ActionSheet 展示接口
* @param context 上下文
* @param actionSheetInfo ActionSheet 信息
* @return true 表示使用自定义 ActionSheet,false 表示使用 SDK 默认 ActionSheet
*/
boolean showActionSheet(Activity context, ActionSheetInfo actionSheetInfo);

8. SDK 运行日志打印

通过实现 LogProxy 代理,可以实现小程序 SDK 内部日志的打印控制。
public abstract class LogProxy {

/**
* 日志打印
*
* @param logLevel 日志级别
* @param tag 日志标识
* @param msg 打印信息
* @param t 异常
*/
abstract public void log(int logLevel, String tag, String msg, Throwable t);

/**
* 是否染色,用于控制日志输出。
*/
abstract public boolean isColorLevel();
}

9. 暗黑模式处理

目前 SDK 里的 UI 是系统跟随,Superapp 可通过实现 IDarkModeProxy 代理并重写 isDarkMode 方法来设置主题。
public interface IDarkModeProxy {
boolean isDarkMode();
}

10. 自定义API

10.1 无UI类型

如果在小程序中需要调用某些 superapp 提供的能力,在小程序 SDK 未实现或无法实现时,开发者可以通过注册扩展(自定义) API 来实现相关能力,使得小程序能够调用 superapp 中提供的自定义 API 能力 。
Superapp 通过继承 BaseJsPlugin 实现自定义的小程序API能力。
说明:
继承 BaseJsPlugin 并用注解进行定义 @JsPlugin(secondary = true)
定义一个方法,方法只能有一个参数且参数必须是 RequestEvent 类型;
然后在方法上定义注解@JsEvent("事件名"),当小程序 JS 调用“事件名”时就会调用到@JsEvent修饰的对应方法;
@JsEvent 支持定义多个事件名;
支持同步或异步返回数据(同一事件只能选择一种方式);
可以通过调用 sendState 给小程序端多次返回中间状态,sendState 调用结束后必须调用 ok 或 fail 标识整个流程结束。
示例代码:
@JsPlugin(secondary = true)
public class CustomPlugin extends BaseJsPlugin {

@JsEvent("testSync")
public String custom1(final RequestEvent req) {
//获取参数
//req.jsonParams
//同步返回数据
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("key", "value");
} catch (JSONException e) {
throw new RuntimeException(e);
}
return req.okSync(jsonObject);
}

@JsEvent("testAsync")
public void getAppBaseInfo(final RequestEvent req) {
//获取参数
//req.jsonParams
//异步返回数据
//req.fail();
//req.ok();
JSONObject jsonObject = new JSONObject();
try {
jsonObject.put("key", "test");
} catch (JSONException e) {
e.printStackTrace();
}
req.ok(jsonObject);
}
}
在小程序中可以这样使用。
//异步api调用
var opts = {
api_name: 'testAsync',
success: function(res) {},
fail: function(res) {},
complete: function(res) {},
data: { // 入参
name : 'kka',
age : 22
}
}
wx.invokeNativePlugin(opts);

//同步api调用
var opts = {
api_name: 'testSync',
sync:true
}
var rst = wx.invokeNativePlugin(opts);

10.1.1 进阶使用

自定义 API 支持在 Superapp 配置文件的方式进行配置,在小程序中通过直接调用 wx.api 的方式来调用。
1. 将 Superapp 中实现的配置文件统一放在 customapi-config.json,参考内容如下:
{
"extApi":[{
"name": "test",
"sync": false,
"params": {
"data": ""
}
},
{
"name": "testSync",
"sync": true,
"params": {
"name": "",
"title": ""
}
}
]
}


2. 把 customapi-config.json 放入 Android 工程 assets 目录中:

3. 代码中指定自定义 API 配置文件的路径信息。
@ProxyService(proxy = MiniAppProxy.class)
public class MiniAppProxyImpl extends BaseMiniAppProxyImpl {
@Override
public MiniConfigData configData(Context context, int configType, JSONObject params) {
if(configType == MiniConfigData.TYPE_CUSTOM_JSAPI) {
//自定义JsApi配置
MiniConfigData.CustomJsApiConfig customJsApiConfig = new MiniConfigData.CustomJsApiConfig();
customJsApiConfig.jsApiConfigPath = "tcmpp/custom-config.json";


return new MiniConfigData
.Builder()
.customJsApiConfig(customJsApiConfig)
.build();
}
return null;
}
4. 在小程序中直接用 wx.test() 的方式调用。
//异步api调用
var opts = {
success: function(res) {},
fail: function(res) {},
complete: function(res) {},
data: {
name : 'kka',
age : 22
}
}
wx.testAsync(opts);

//同步api调用
var rst = testSync(opts);

10.2 自定义UI

小程序 SDK 的使用者可以自定义客户端原生组件为小程序提供支持。小程序开发者通过特定的小程序 API 能够在小程序页面中创建并操作原生组件以及与原生组件进行通信。Android 的客户端原生组渲染在小程序页面之上,不支持 zIndex,始终位于小程序其他组件上层并会遮挡小程序内容。该类型组件以普通 View 的形式进行绘制。
说明:
为了实现扩展组件,依赖于小程序开发者的在小程序中的改造和宿主应用开发者在宿主应用中的改造,二者结合才能实现小程序视图组件的扩展。
应用的开发者需要实现特定的代理,在小程序调用自定义组件 API 时创建原生组件以及响应对原生组件的操作。

10.2.1 原生组件扩展

通过如下设置覆写代理,宿主可以自定义创建原生组件:
@ProxyService(proxy = ExternalElementProxy.class)
public class MyExternalElementProxy extends ExternalElementProxy{}
代理需要实现以下内容:
1. 插入组件。当小程序向页面中插入原生组件时会调用此方法。开发者需要实现此方法,并将自定义组件作为子 View 加入到 parent 参数提供的容器中。
/**
* 创建组件,当小程序创建自定义原生组件时将会调用此接口
*
* @param widgetId 小程序创建的组件唯一ID
* @param widgetContext 小程序组件的上下文,用于向小程序回传内容
* @param type 小程序创建的组件类型名称
* @param parent 承载原生组件的父容器
* @param params 小程序创建组件时传递的参数
*/
public abstract void handleInsertElement(long widgetId, ExternalWidgetContext widgetContext,
String type, ViewGroup parent, JSONObject params);
2. 更新组件。当原生组件在小程序中的位置以及大小发生变化时会调用此方法通知应用。原生组件的父容器布局会按照变化后的样式进行自适应,原生组件本身则可以根据需要对自身进行调整。
/**
* 更新组件样式,当小程序更新自定义原生组件的样式时将会调用此接口
*
* @param widgetId 小程序组件ID
* @param widgetContext 小程序组件的上下文,用于向小程序回传内容
* @param params 小程序更新组件时传递的参数
*/
public abstract void handleUpdateElement(long widgetId, ExternalWidgetContext widgetContext,
JSONObject params);
3. 操作组件。当小程序向原生组件发送事件时会调用此方法(例如按钮点击,状态变更),事件的具体内容需要开发者自行在 params 中进行定义。
/**
* 操作组件,当小程序需要向组件发送指令或者调用特有方法的时候将会调用此接口
*
* @param widgetId 小程序组件ID
* @param widgetContext 小程序组件的上下文,用于向小程序回传内容
* @param params 小程序更新组件时传递的参数
*/
public abstract void handleOperateElement(long widgetId, ExternalWidgetContext widgetContext,
JSONObject params);
4. 删除组件。当小程序删除已添加的原生组件时将调用此方法通知应用。此时组件的父容器将被移除,应用应当对组件进行销毁处理。
/**
* 删除组件
*
* @param widgetId 小程序组件ID
* @param widgetContext 小程序组件的上下文,用于向小程序回传内容
*/
public abstract void handleRemoveElement(long widgetId, ExternalWidgetContext widgetContext);

10.2.2 小程序原生组件上下文

小程序组件的上下文包含了使原生组件能够向对应的小程序组件发送消息的方法。onExternalElementEvent 方法会直接向小程序发送 onExternalElementEvent 事件,小程序应该捕获并处理该事件;callbackSuccess、callbackFail 则是在小程序调用 API 向应用发送事件时对当次小程序 API 调用传入的 success 或者 fail 方法进行回调。
/**
* 向小程序发送 onExternalElementEvent 事件
*
* @param jsonObject 事件携带的JSON数据
*/
public final void onExternalElementEvent(JSONObject jsonObject);

/**
* 调用小程序提供的success回调方法
*
* @param jsonObject 回调携带的JSON数据,可以为空
*/
public final void callbackSuccess(JSONObject jsonObject);

/**
* 调用小程序提供的fail回调方法
*
* @param jsonObject jsonObject 回调携带的JSON数据,可以为空
* @param message 错误信息描述
*/
public final void callbackFail(JSONObject jsonObject, String message);

10.2.3 小程序扩展实现

小程序向页面中插入客户端自定义的组件需要先在 wxml 中引入一个 external-element 节点:
<external-element
id="comp1"
type="maTestView"
_insert2WebLayer="true"
style="width: 200px;height: 100px;"
bindexternalelementevent="handleEvent"
></external-element>
此处 type 为与应用约定创建的组件类型名称一致,_insert2WebLayer 表示该组件为同层组件或者非同层组件(true 为同层,需客户端实现同层组件代理;false 为非同层,需要客户端实现非同层代理),bindexternalelementevent 可捕获 native 传递的 onExternalElementEvent 或者onXWebExternalElementEvent,回调参数包括:
{
target,
currentTarget,
timeStamp,
touches,
detail, // native传递的参数
}
之后小程序通过 ID 创建一个与该节点相关联的上下文:
this.ctx = wx.createExternalElementContext('comp1');
该方法会通知应用在节点的位置创建对应的原生组件。小程序后续可以通过该上下文向原生组件发送事件,对原生组件进行操作:
this.ctx.call({
params1: {
name: 'name1',
age: 11
},
params2: {
name: 'name2',
age: 22
},
success: (e) => {
console.log('====operate success=====', e)
},
fail: (e) => {
console.log('====operate fail=====', e)
},
complete: (e) => {
console.log('====operate complete=====', e)
}
})



帮助和支持

本页内容是否解决了您的问题?

填写满意度调查问卷,共创更好文档体验。

文档反馈