This commit is contained in:
dzc committed 2026-11-11 19:38:29 +08:00
1 parent 7571180b55
commit 26e8a38893
78 files changed
+8035 -457

No files matched your search

+15
View File
@@ -0,0 +1,15 @@
# 极光推送原生依赖
来源 https://github.com/jiguang-official/jpush-uniapp-plugin
版本 1.3.2,固定提交 `16a5132c69bb035d818989e6656bfa77e922aee4`。
本项目保留 Android、iOS 实现、接口与所需原生资源。iOS 静态库跟随官方提交,Android 通过 Maven 引入 JPush 6.3.0。
本地适配将 APNs entitlement 设为与会员服务默认配置一致的 production,iOS 最低版本设为官方兼容范围 iOS 12,并增加 `clearNotificationAll` 用于退出时清理通知。开发证书联调需同时调整此 entitlement、`jpush-config.js` 和服务端 APNs 环境。
Android 通知点击在官方事件分发后通过系统启动 Intent 拉起应用,复用已有应用任务。JS 尚未初始化时沿用官方事件队列暂存点击,待 `setEventCallBack` 后回放。
原生应用配置放在与 package.json 同级的 AndroidManifest.xml、Info.plist 和 nativeResources 目录,供 HBuilderX 云打包直接收集。Android AppKey 和渠道在 nativeResources/android/manifestPlaceholders.json 配置,与 src/common/jpush-config.js 保持一致。
当前 UniApp Android 包名为 `com.zax.htys`,云打包时使用同一包名。极光应用需绑定此包名。
+121
View File
@@ -0,0 +1,121 @@
{
"id": "jg-jpush-u",
"displayName": "jg-jpush-u",
"version": "1.3.2",
"description": "jg-jpush-u",
"keywords": [
"jg-jpush-u"
],
"repository": "https://github.com/jiguang-official/jpush-uniapp-plugin",
"engines": {
"HBuilderX": "^4.25",
"uni-app": "^4.75",
"uni-app-x": "^4.75"
},
"dcloudext": {
"type": "uts",
"sale": {
"regular": {
"price": "0.00"
},
"sourcecode": {
"price": "0.00"
}
},
"contact": {
"qq": ""
},
"declaration": {
"ads": "无",
"data": "说明文档地址:\nhttps://docs.jiguang.cn/jpush/client/jghgzy_a_i_h#sdk-申请系统权限的说明",
"permissions": "说明文档地址:\nhttps://docs.jiguang.cn/jpush/client/jghgzy_a_i_h#sdk-申请系统权限的说明"
},
"npmurl": "",
"darkmode": "x",
"i18n": "x",
"widescreen": "x"
},
"uni_modules": {
"dependencies": [],
"encrypt": [],
"platforms": {
"cloud": {
"tcb": "√",
"aliyun": "√",
"alipay": "√"
},
"client": {
"uni-app": {
"vue": {
"vue2": "-",
"vue3": "-"
},
"web": {
"safari": "-",
"chrome": "-"
},
"app": {
"vue": "-",
"nvue": "-",
"android": {
"extVersion": "",
"minVersion": "21"
},
"ios": {
"extVersion": "",
"minVersion": "12"
},
"harmony": {
"extVersion": "",
"minVersion": "12"
}
},
"mp": {
"weixin": "-",
"alipay": "-",
"toutiao": "-",
"baidu": "-",
"kuaishou": "-",
"jd": "-",
"harmony": "-",
"qq": "-",
"lark": "-",
"xhs": "-"
},
"quickapp": {
"huawei": "-",
"union": "-"
}
},
"uni-app-x": {
"web": {
"safari": "-",
"chrome": "-"
},
"app": {
"android": {
"extVersion": "",
"minVersion": "21"
},
"ios": {
"extVersion": "",
"minVersion": "12"
},
"harmony": {
"extVersion": "",
"minVersion": "12"
}
},
"mp": {
"weixin": "-"
}
},
"App": {
"app-android": "u",
"app-harmony": "u",
"app-ios": "u"
}
}
}
}
}
@@ -0,0 +1,35 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
package="cn.jiguang.uni_modules.jpush_u">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.VIBRATE" />
<application>
<service
android:name="uts.sdk.modules.jgJpushU.PushService"
android:enabled="true"
android:stopWithTask="true"
android:exported="false"
android:process=":pushcore">
<intent-filter>
<action android:name="cn.jiguang.user.service.action" />
</intent-filter>
</service>
<receiver
android:name="uts.sdk.modules.jgJpushU.PushMessageReceiver"
android:exported="false">
<intent-filter>
<action android:name="cn.jpush.android.intent.RECEIVER_MESSAGE" />
<category android:name="${applicationId}" />
</intent-filter>
</receiver>
</application>
</manifest>
@@ -0,0 +1,472 @@
/**
* PushMessageReceiver.uts
* 极光推送消息接收器,继承自JPushMessageReceiver
*/
import Context from 'android.content.Context';
import Intent from 'android.content.Intent';
import Log from 'android.util.Log';
import Bundle from 'android.os.Bundle';
import ArrayList from 'java.util.ArrayList';
import CmdMessage from 'cn.jpush.android.api.CmdMessage';
import CustomMessage from 'cn.jpush.android.api.CustomMessage';
import JPushMessage from 'cn.jpush.android.api.JPushMessage';
import NotificationMessage from 'cn.jpush.android.api.NotificationMessage';
import VoipDataMessage from 'cn.jpush.android.api.VoipDataMessage';
import JPushMessageReceiver from 'cn.jpush.android.service.JPushMessageReceiver';
import JSONObject from 'org.json.JSONObject';
// 导入事件回调管理器
import { eventCallbackManager } from './index.uts';
// 导入 EventCallBack 类型
import type { EventCallBack } from '../interface.uts';
/**
* 推送消息接收器类
* 继承自极光推送的JPushMessageReceiver
*/
export class PushMessageReceiver extends JPushMessageReceiver {
private static readonly TAG: string = "U-PushMessageReceiver";
constructor() {
super();
Log.e(PushMessageReceiver.TAG, "PushMessageReceiver constructor called");
}
/**
* 将JPushMessage转换为JSON字符串
*/
private convertJPushMessageToJson(jPushMessage: JPushMessage): string {
try {
const jsonObject = new JSONObject();
jsonObject.put("alias", jPushMessage.getAlias());
jsonObject.put("tags", jPushMessage.getTags());
jsonObject.put("pros", jPushMessage.getPros());
jsonObject.put("checkTag", jPushMessage.getCheckTag());
jsonObject.put("errorCode", jPushMessage.getErrorCode());
jsonObject.put("tagCheckStateResult", jPushMessage.getTagCheckStateResult());
jsonObject.put("isTagCheckOperator", jPushMessage.isTagCheckOperator());
jsonObject.put("sequence", jPushMessage.getSequence());
jsonObject.put("mobileNumber", jPushMessage.getMobileNumber());
jsonObject.put("protoType", jPushMessage.getProtoType());
jsonObject.put("action", jPushMessage.getAction());
return jsonObject.toString();
} catch (e) {
Log.e(PushMessageReceiver.TAG, "convertJPushMessageToJson error: " + e.toString());
return "{}";
}
}
/**
* 将CustomMessage转换为JSON字符串
*/
private convertCustomMessageToJson(customMessage: CustomMessage): string {
try {
const jsonObject = new JSONObject();
jsonObject.put("messageId", customMessage.messageId);
jsonObject.put("extra", customMessage.extra);
jsonObject.put("message", customMessage.message);
jsonObject.put("contentType", customMessage.contentType);
jsonObject.put("title", customMessage.title);
jsonObject.put("senderId", customMessage.senderId);
jsonObject.put("appId", customMessage.appId);
jsonObject.put("platform", customMessage.platform);
return jsonObject.toString();
} catch (e) {
Log.e(PushMessageReceiver.TAG, "convertCustomMessageToJson error: " + e.toString());
return "{}";
}
}
/**
* 将NotificationMessage转换为JSON字符串
*/
private convertNotificationMessageToJson(message: NotificationMessage): string {
try {
const jsonObject = new JSONObject();
jsonObject.put("appkey", message.appkey);
jsonObject.put("msgId", message.msgId);
jsonObject.put("notificationContent", message.notificationContent);
jsonObject.put("notificationAlertType", message.notificationAlertType);
jsonObject.put("notificationTitle", message.notificationTitle);
jsonObject.put("notificationSmallIcon", message.notificationSmallIcon);
jsonObject.put("notificationLargeIcon", message.notificationLargeIcon);
jsonObject.put("notificationExtras", message.notificationExtras);
jsonObject.put("notificationStyle", message.notificationStyle);
jsonObject.put("notificationBuilderId", message.notificationBuilderId);
jsonObject.put("notificationBigText", message.notificationBigText);
jsonObject.put("notificationBigPicPath", message.notificationBigPicPath);
jsonObject.put("notificationInbox", message.notificationInbox);
jsonObject.put("notificationPriority", message.notificationPriority);
jsonObject.put("notificationImportance", message.notificationImportance);
jsonObject.put("notificationCategory", message.notificationCategory);
jsonObject.put("notificationId", message.notificationId);
jsonObject.put("developerArg0", message.developerArg0);
jsonObject.put("platform", message.platform);
jsonObject.put("appId", message.appId);
jsonObject.put("notificationType", message.notificationType);
jsonObject.put("notificationChannelId", message.notificationChannelId);
jsonObject.put("displayForeground", message.displayForeground);
jsonObject.put("_webPagePath", message._webPagePath);
jsonObject.put("isRichPush", message.isRichPush);
jsonObject.put("richType", message.richType);
jsonObject.put("deeplink", message.deeplink);
jsonObject.put("failedAction", message.failedAction);
jsonObject.put("failedLink", message.failedLink);
jsonObject.put("targetPkgName", message.targetPkgName);
jsonObject.put("sspWxAppId", message.sspWxAppId);
jsonObject.put("sspWmOriginId", message.sspWmOriginId);
jsonObject.put("sspWmType", message.sspWmType);
jsonObject.put("isWmDeepLink", message.isWmDeepLink);
jsonObject.put("inAppMsgType", message.inAppMsgType);
jsonObject.put("inAppMsgShowType", message.inAppMsgShowType);
jsonObject.put("inAppMsgShowPos", message.inAppMsgShowPos);
jsonObject.put("inAppMsgTitle", message.inAppMsgTitle);
jsonObject.put("inAppMsgContentBody", message.inAppMsgContentBody);
jsonObject.put("inAppType", message.inAppType);
jsonObject.put("inAppShowTarget", message.inAppShowTarget);
jsonObject.put("inAppClickAction", message.inAppClickAction);
jsonObject.put("inAppExtras", message.inAppExtras);
return jsonObject.toString();
} catch (e) {
Log.e(PushMessageReceiver.TAG, "convertNotificationMessageToJson error: " + e.toString());
return "{}";
}
}
/**
* 将CmdMessage转换为JSON字符串
*/
private convertCmdMessageToJson(cmdMessage: CmdMessage): string {
try {
const jsonObject = new JSONObject();
jsonObject.put("cmd", cmdMessage.cmd);
jsonObject.put("errorCode", cmdMessage.errorCode);
jsonObject.put("msg", cmdMessage.msg);
if (cmdMessage.cmd == 2013) {
const typedExtra = SubscriptionResultCodec.fromBundle(cmdMessage.extra);
jsonObject.put("extra", typedExtra);
jsonObject.put("commandData", typedExtra);
if (typedExtra.has("channels")) jsonObject.put("channels", typedExtra.get("channels"));
} else if (cmdMessage.cmd == 2012) {
// 小米订阅消息需要向 UTS 层透传结构化的 channel 操作结果
jsonObject.put("extra", this.convertBundleToJson(cmdMessage.extra));
} else {
// 保持历史命令的 extra 序列化行为,避免改变既有回调语义
jsonObject.put("extra", cmdMessage.extra);
}
return jsonObject.toString();
} catch (e) {
Log.e(PushMessageReceiver.TAG, "convertCmdMessageToJson error: " + e.toString());
return "{}";
}
}
/**
* 将Bundle转换为JSONObject
*/
private convertBundleToJson(bundle: Bundle | null): JSONObject {
try {
const jsonObject = new JSONObject();
if (bundle != null) {
// 使用 ArrayList 来收集 Bundle 的键,避免 iterator() 歧义
const keySet = bundle.keySet();
const keyList = new ArrayList<string>(keySet);
// 在 Kotlin 中 size 是属性,不是方法,所以直接访问
const size: Int = keyList.size;
for (let i: Int = 0; i < size; i++) {
const key = keyList.get(i);
jsonObject.put(key, bundle.get(key));
}
}
return jsonObject;
} catch (e) {
Log.e(PushMessageReceiver.TAG, "convertBundleToJson error: " + e.toString());
return new JSONObject();
}
}
/**
* 触发事件回调的通用方法
*/
private triggerEventCallback(eventName: string, eventData: string): void {
const event: EventCallBack = {
eventName: eventName,
eventData: eventData
};
eventCallbackManager.triggerCallBack(event);
}
/**
* 收到自定义消息
*/
override onMessage(context: Context, customMessage: CustomMessage): void {
super.onMessage(context, customMessage);
Log.e(PushMessageReceiver.TAG, "[onMessage] ");
// 触发自定义消息回调
this.triggerEventCallback('onCustomMessage', this.convertCustomMessageToJson(customMessage));
}
/**
* 属性操作结果回调
*/
override onPropertyOperatorResult(context: Context, jPushMessage: JPushMessage): void {
super.onPropertyOperatorResult(context, jPushMessage);
Log.e(PushMessageReceiver.TAG, "[onPropertyOperatorResult] ");
// 触发属性操作结果回调
this.triggerEventCallback('onPropertyOperatorResult', this.convertJPushMessageToJson(jPushMessage));
}
/**
* 通知点击回调
*/
override onNotifyMessageOpened(context: Context, message: NotificationMessage): void {
Log.e(PushMessageReceiver.TAG, "[onNotifyMessageOpened] ");
super.onNotifyMessageOpened(context, message);
// 触发通知点击回调
this.triggerEventCallback('onClickMessage', this.convertNotificationMessageToJson(message));
// 官方接收器只分发事件。先缓存点击,再通过系统入口恢复现有任务或冷启动应用。
const launchIntent = context.getPackageManager().getLaunchIntentForPackage(context.getPackageName());
if (launchIntent != null) {
launchIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_RESET_TASK_IF_NEEDED);
context.startActivity(launchIntent);
}
}
/**
* 通知展示回调
*/
override onNotifyMessageArrived(context: Context, message: NotificationMessage): void {
Log.e(PushMessageReceiver.TAG, "[onNotifyMessageArrived] ");
super.onNotifyMessageArrived(context, message);
// 触发通知展示回调
this.triggerEventCallback('onNotifyMessageArrived', this.convertNotificationMessageToJson(message));
}
/**
* 通知被清除回调
*/
override onNotifyMessageDismiss(context: Context, message: NotificationMessage): void {
super.onNotifyMessageDismiss(context, message);
Log.e(PushMessageReceiver.TAG, "[onNotifyMessageDismiss] ");
// 触发通知被清除回调
this.triggerEventCallback('onNotifyMessageDismiss', this.convertNotificationMessageToJson(message));
}
/**
* 注册ID回调
*/
override onRegister(context: Context, registrationId: string): void {
super.onRegister(context, registrationId);
Log.e(PushMessageReceiver.TAG, "[onRegister] " + registrationId);
// 触发注册回调
this.triggerEventCallback('onRegister', registrationId);
}
/**
* 连接状态回调
*/
override onConnected(context: Context, isConnected: boolean): void {
super.onConnected(context, isConnected);
Log.e(PushMessageReceiver.TAG, "[onConnected] " + isConnected);
// 触发连接状态回调
this.triggerEventCallback('onConnected', isConnected.toString());
}
/**
* 命令结果回调
*/
override onCommandResult(context: Context, cmdMessage: CmdMessage): void {
super.onCommandResult(context, cmdMessage);
Log.e(PushMessageReceiver.TAG, "[onCommandResult] ");
// 触发命令结果回调
this.triggerEventCallback('onCommandResult', this.convertCmdMessageToJson(cmdMessage));
}
/**
* 标签操作结果回调
*/
override onTagOperatorResult(context: Context, jPushMessage: JPushMessage): void {
Log.e(PushMessageReceiver.TAG, "[onTagOperatorResult] ");
// TagAliasOperatorHelper.getInstance().onTagOperatorResult(context, jPushMessage);
super.onTagOperatorResult(context, jPushMessage);
// 触发标签操作结果回调
this.triggerEventCallback('onTagOperatorResult', this.convertJPushMessageToJson(jPushMessage));
}
/**
* 检查标签操作结果回调
*/
override onCheckTagOperatorResult(context: Context, jPushMessage: JPushMessage): void {
Log.e(PushMessageReceiver.TAG, "[onCheckTagOperatorResult] ");
// TagAliasOperatorHelper.getInstance().onCheckTagOperatorResult(context, jPushMessage);
super.onCheckTagOperatorResult(context, jPushMessage);
// 触发检查标签操作结果回调
this.triggerEventCallback('onTagOperatorResult', this.convertJPushMessageToJson(jPushMessage));
}
/**
* 别名操作结果回调
*/
override onAliasOperatorResult(context: Context, jPushMessage: JPushMessage): void {
Log.e(PushMessageReceiver.TAG, "[onAliasOperatorResult] ");
// TagAliasOperatorHelper.getInstance().onAliasOperatorResult(context, jPushMessage);
super.onAliasOperatorResult(context, jPushMessage);
// 触发别名操作结果回调
this.triggerEventCallback('onAliasOperatorResult', this.convertJPushMessageToJson(jPushMessage));
}
/**
* 手机号操作结果回调
*/
override onMobileNumberOperatorResult(context: Context, jPushMessage: JPushMessage): void {
super.onMobileNumberOperatorResult(context, jPushMessage);
Log.e(PushMessageReceiver.TAG, "[onMobileNumberOperatorResult] ");
// TagAliasOperatorHelper.getInstance().onMobileNumberOperatorResult(context, jPushMessage);
// 触发手机号操作结果回调
this.triggerEventCallback('onMobileNumberOperatorResult', this.convertJPushMessageToJson(jPushMessage));
}
/**
* 通知设置检查回调
*/
override onNotificationSettingsCheck(context: Context, isOn: boolean, source: Int): void {
super.onNotificationSettingsCheck(context, isOn, source);
Log.e(PushMessageReceiver.TAG, "[onNotificationSettingsCheck] isOn:" + isOn + ",source:" + source);
// 触发通知设置检查回调
try {
const jsonObject = new JSONObject();
jsonObject.put("isOn", isOn);
jsonObject.put("source", source);
this.triggerEventCallback('onNotificationSettingsCheck', jsonObject.toString());
} catch (e) {
Log.e(PushMessageReceiver.TAG, "onNotificationSettingsCheck JSON error: " + e.toString());
this.triggerEventCallback('onNotificationSettingsCheck', '{"isOn":false,"source":0}');
}
}
/**
* 是否需要显示通知
*/
override isNeedShowNotification(context: Context, notificationMessage: NotificationMessage, processName: string): boolean {
return false;
}
/**
* 通知未显示回调
*/
override onNotifyMessageUnShow(context: Context, message: NotificationMessage): void {
super.onNotifyMessageUnShow(context, message);
Log.e(PushMessageReceiver.TAG, "[onNotifyMessageUnShow] message:");
// 触发通知未显示回调
this.triggerEventCallback('onNotifyMessageUnShow', this.convertNotificationMessageToJson(message));
}
/**
* 应用内消息展示回调
*/
override onInAppMessageShow(context: Context, message: NotificationMessage): void {
super.onInAppMessageShow(context, message);
Log.e(PushMessageReceiver.TAG, "[onInAppMessageShow], ");
// 触发应用内消息展示回调
this.triggerEventCallback('onInAppMessageShow', this.convertNotificationMessageToJson(message));
}
/**
* 应用内消息点击回调
*/
override onInAppMessageClick(context: Context, message: NotificationMessage): void {
super.onInAppMessageClick(context, message);
Log.e(PushMessageReceiver.TAG, "[onInAppMessageClick], ");
// 触发应用内消息点击回调
this.triggerEventCallback('onInAppMessageClick', this.convertNotificationMessageToJson(message));
}
/**
* 拉取地理围栏列表的回调
*/
override onGeofenceReceived(context: Context, geofences: string): void {
super.onGeofenceReceived(context, geofences);
Log.e(PushMessageReceiver.TAG, "onGeofenceReceived: " + geofences);
// 触发地理围栏列表回调
this.triggerEventCallback('onGeofenceReceived', geofences);
}
/**
* 多操作按钮点击回调
*/
override onMultiActionClicked(context: Context, intent: Intent): void {
super.onMultiActionClicked(context, intent);
Log.e(PushMessageReceiver.TAG, "[onMultiActionClicked] 用户点击了通知栏按钮");
// 触发多操作按钮点击回调
try {
const jsonObject = new JSONObject();
jsonObject.put("action", intent.getAction());
jsonObject.put("extras", this.convertBundleToJson(intent.getExtras()));
this.triggerEventCallback('onMultiActionClicked', jsonObject.toString());
} catch (e) {
Log.e(PushMessageReceiver.TAG, "onMultiActionClicked JSON error: " + e.toString());
this.triggerEventCallback('onMultiActionClicked', '{"action":"","extras":{}}');
}
}
/**
* 触发地理围栏回调
*/
override onGeofenceRegion(context: Context, geofence: string, longitude: Double, latitude: Double): void {
super.onGeofenceRegion(context, geofence, longitude, latitude);
Log.e(PushMessageReceiver.TAG, "onGeofenceRegion: " + geofence);
// 触发地理围栏回调
try {
const jsonObject = new JSONObject();
jsonObject.put("geofence", geofence);
jsonObject.put("longitude", longitude);
jsonObject.put("latitude", latitude);
this.triggerEventCallback('onGeofenceRegion', jsonObject.toString());
} catch (e) {
Log.e(PushMessageReceiver.TAG, "onGeofenceRegion JSON error: " + e.toString());
this.triggerEventCallback('onGeofenceRegion', '{"geofence":"","longitude":0,"latitude":0}');
}
}
/**
* VOIP 透传消息回调(小米/荣耀/OPPO/VIVO 厂商通道)
*/
override onVoipMessage(context: Context, voipDataMessage: VoipDataMessage): void {
super.onVoipMessage(context, voipDataMessage);
Log.e(PushMessageReceiver.TAG, "[onVoipMessage] ");
try {
const jsonObject = new JSONObject();
jsonObject.put("messageId", voipDataMessage.getMessageId());
jsonObject.put("extraData", voipDataMessage.getExtraData());
jsonObject.put("platform", voipDataMessage.getPlatform());
jsonObject.put("voipSupportStatus", voipDataMessage.getVoipSupportStatus());
this.triggerEventCallback('onVoipMessage', jsonObject.toString());
} catch (e) {
Log.e(PushMessageReceiver.TAG, "onVoipMessage JSON error: " + e.toString());
this.triggerEventCallback('onVoipMessage', '{"messageId":"","extraData":"","platform":0}');
}
}
}
@@ -0,0 +1,17 @@
/**
* PushService.uts
* 极光推送服务类,继承自JCommonService
*/
import JCommonService from 'cn.jpush.android.service.JCommonService';
/**
* 推送服务类
* 继承自极光推送的JCommonService
*/
export class PushService extends JCommonService {
constructor() {
super();
console.log("U-PushService", "constructor called");
}
}
@@ -0,0 +1,40 @@
package uts.sdk.modules.jgJpushU;
import android.os.Bundle;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Array;
import java.util.List;
import java.util.Map;
/** Preserve SDK types for cmd2013 only; legacy command payloads remain unchanged. */
public final class SubscriptionResultCodec {
private SubscriptionResultCodec() {}
public static JSONObject fromBundle(Bundle bundle) throws JSONException { return bundle == null ? new JSONObject() : (JSONObject) encode(bundle, 0); }
private static Object encode(Object value, int depth) throws JSONException {
if (value == null || depth > 16) return JSONObject.NULL;
if (value instanceof Bundle) {
JSONObject result = new JSONObject();
for (String key : ((Bundle) value).keySet()) {
if (!key.startsWith("intent_")) result.put(key, encode(((Bundle) value).get(key), depth + 1));
}
return result;
}
if (value instanceof Map) {
JSONObject result = new JSONObject();
for (Map.Entry<?, ?> entry : ((Map<?, ?>) value).entrySet()) {
if (entry.getKey() instanceof String && !((String) entry.getKey()).startsWith("intent_"))
result.put((String) entry.getKey(), encode(entry.getValue(), depth + 1));
}
return result;
}
if (value instanceof List || value.getClass().isArray()) {
JSONArray result = new JSONArray();
int size = value instanceof List ? ((List<?>) value).size() : Array.getLength(value);
for (int i = 0; i < size; i++) result.put(encode(value instanceof List ? ((List<?>) value).get(i) : Array.get(value, i), depth + 1));
return result;
}
return value instanceof String || value instanceof Boolean || value instanceof Number ? value : JSONObject.NULL;
}
}
@@ -0,0 +1,12 @@
{
"dependencies": [
"cn.jiguang.sdk:jpush:6.3.0"
],
"minSdkVersion": "21",
"project": {
"repositories": [
"google()",
"mavenCentral()"
]
}
}
@@ -0,0 +1,419 @@
import JPushInterface from 'cn.jpush.android.api.JPushInterface'
import JCoreInterface from 'cn.jiguang.api.JCoreInterface'
import JPushConfig from 'cn.jpush.android.data.JPushConfig'
import ArrayList from 'java.util.ArrayList'
export * from './PushMessageReceiver.uts'
export { PushService } from "./PushService.uts"
/* 引入 interface.uts 文件中定义的变量 */
import { EventCallBackParams, EventCallBack } from '../interface.uts';
const TAG = "JPUSH-uni-"
// 事件回调管理类
class EventCallbackManager {
private callBack : EventCallBackParams | null = null
private cachedEvents : Array<EventCallBack> = []
setEventCallBack(param : EventCallBackParams) : void {
console.log(TAG, "setEventCallBack")
this.callBack = param
// 如果有缓存的事件,立即回调
if (this.cachedEvents.length > 0) {
console.log(TAG, "处理缓存事件,数量:", this.cachedEvents.length)
for (let i = 0; i < this.cachedEvents.length; i++) {
this.triggerCallBack(this.cachedEvents[i])
}
this.cachedEvents = []
}
}
triggerCallBack(event : EventCallBack) : void {
const callBack = this.callBack
if (callBack !== null) {
console.log(TAG, "触发回调")
const callback = callBack.callback
if (callback !== null) {
callback(event)
} else {
console.log(TAG, "未设置回调函数")
}
} else {
console.log(TAG, "回调未设置,缓存事件")
this.cachedEvents.push(event)
}
}
getCallBack() : EventCallBackParams | null {
return this.callBack
}
hasCallBack() : boolean {
const callBack = this.callBack
return callBack !== null && callBack.callback !== null
}
}
// 全局事件回调管理器实例
export const eventCallbackManager = new EventCallbackManager()
export const init = function (appKey? : string) {
JPushInterface.setNotificationCallBackEnable(UTSAndroid.getAppContext(),true)
if (appKey !== null) {
console.log(TAG, "init with explicit appKey")
// 创建JPushConfig并设置appKey
const config = new JPushConfig()
config.setjAppKey(appKey)
JPushInterface.init(UTSAndroid.getAppContext(), config)
} else {
console.log(TAG, "init without appKey")
JPushInterface.init(UTSAndroid.getAppContext())
}
}
export const setDebug = function (debug : boolean) {
console.log(TAG, "setDebug", debug)
JPushInterface.setDebugMode(debug)
}
export const resumePush = function () {
console.log(TAG, "resumePush")
JPushInterface.resumePush(UTSAndroid.getAppContext())
}
export const stopPush = function () {
console.log(TAG, "stopPush")
JPushInterface.stopPush(UTSAndroid.getAppContext())
}
export const isPushStopped = function () : boolean {
console.log(TAG, "isPushStopped")
return JPushInterface.isPushStopped(UTSAndroid.getAppContext())
}
export const getPushStatus = function () {
console.log(TAG, "getPushStatus")
return JPushInterface.getPushStatus(UTSAndroid.getAppContext())
}
export const setChannel = function (channel : string) {
console.log(TAG, "setChannel", channel)
JPushInterface.setChannel(UTSAndroid.getAppContext(), channel)
}
export const getRegistrationId = function () : string {
console.log(TAG, "getRegistrationId")
return JPushInterface.getRegistrationID(UTSAndroid.getAppContext())
}
export const setLatestNotificationNumber = function (maxNum : Int) {
console.log(TAG, "setLatestNotificationNumber", maxNum)
JPushInterface.setLatestNotificationNumber(UTSAndroid.getAppContext(), maxNum)
}
export const clearNotificationAll = function () {
console.log(TAG, "clearNotificationAll")
JPushInterface.clearAllNotifications(UTSAndroid.getAppContext())
}
export const clearNotificationById = function (notificationId : Int) {
console.log(TAG, "clearNotificationById", notificationId)
JPushInterface.clearNotificationById(UTSAndroid.getAppContext(), notificationId)
}
export const setTags = function (sequence : Int, tags : string[]) {
console.log(TAG, "setTags", sequence, tags)
// 将string[]转换为Set<string>以适配Android SDK
const tagSet = new Set<string>()
for (let i = 0; i < tags.length; i++) {
tagSet.add(tags[i])
}
JPushInterface.setTags(UTSAndroid.getAppContext(), sequence, tagSet)
}
export const addTags = function (sequence : Int, tags : string[]) {
console.log(TAG, "addTags", sequence, tags)
// 将string[]转换为Set<string>以适配Android SDK
const tagSet = new Set<string>()
for (let i = 0; i < tags.length; i++) {
tagSet.add(tags[i])
}
JPushInterface.addTags(UTSAndroid.getAppContext(), sequence, tagSet)
}
export const deleteTags = function (sequence : Int, tags : string[]) {
console.log(TAG, "deleteTags", sequence, tags)
// 将string[]转换为Set<string>以适配Android SDK
const tagSet = new Set<string>()
for (let i = 0; i < tags.length; i++) {
tagSet.add(tags[i])
}
JPushInterface.deleteTags(UTSAndroid.getAppContext(), sequence, tagSet)
}
export const cleanTags = function (sequence : Int) {
console.log(TAG, "cleanTags", sequence)
JPushInterface.cleanTags(UTSAndroid.getAppContext(), sequence)
}
export const getAllTags = function (sequence : Int) {
console.log(TAG, "getAllTags", sequence)
JPushInterface.getAllTags(UTSAndroid.getAppContext(), sequence)
}
export const checkTagBindState = function (sequence : Int, tag : string) {
console.log(TAG, "checkTagBindState", sequence, tag)
JPushInterface.checkTagBindState(UTSAndroid.getAppContext(), sequence, tag)
}
export const setAlias = function (sequence : Int, alias : string) {
console.log(TAG, "setAlias", sequence, alias)
JPushInterface.setAlias(UTSAndroid.getAppContext(), sequence, alias)
}
export const deleteAlias = function (sequence : Int) {
console.log(TAG, "deleteAlias", sequence)
JPushInterface.deleteAlias(UTSAndroid.getAppContext(), sequence)
}
export const getAlias = function (sequence : Int) {
console.log(TAG, "getAlias", sequence)
JPushInterface.getAlias(UTSAndroid.getAppContext(), sequence)
}
export const setMobileNumber = function (sequence : Int, mobileNumber : string) {
console.log(TAG, "setMobileNumber", sequence, mobileNumber)
JPushInterface.setMobileNumber(UTSAndroid.getAppContext(), sequence, mobileNumber)
}
export const onResume = function () {
console.log(TAG, "onResume")
JPushInterface.onResume(UTSAndroid.getAppContext())
}
export const onPause = function () {
console.log(TAG, "onPause")
JPushInterface.onPause(UTSAndroid.getAppContext())
}
export const onFragmentResume = function (fragmentName : string) {
console.log(TAG, "onFragmentResume", fragmentName)
JPushInterface.onFragmentResume(UTSAndroid.getAppContext(), fragmentName)
}
export const onFragmentPause = function (fragmentName : string) {
console.log(TAG, "onFragmentPause", fragmentName)
JPushInterface.onFragmentPause(UTSAndroid.getAppContext(), fragmentName)
}
export const onKillProcess = function () {
console.log(TAG, "onKillProcess")
JPushInterface.onKillProcess(UTSAndroid.getAppContext())
}
export const requestPermission = function () {
console.log(TAG, "requestPermission")
const activity = UTSAndroid.getUniActivity()
if (activity != null) {
JPushInterface.requestPermission(activity)
} else {
console.log(TAG, "requestPermission: getUniActivity() is null, fallback to getAppContext()")
JPushInterface.requestPermission(UTSAndroid.getAppContext())
}
}
/**
* 申请必须权限(仅 Android,如 POST_NOTIFICATIONS,Android 13+)
* 建议在 Activity 可见时调用(如首屏 onReady),以便正确弹出系统权限框。
*/
export const requestRequiredPermission = function () {
console.log(TAG, "requestRequiredPermission")
const activity = UTSAndroid.getUniActivity()
if (activity != null) {
JPushInterface.requestRequiredPermission(activity)
} else {
console.log(TAG, "requestRequiredPermission: no Activity, skip (call when Activity available)")
}
}
export const isNotificationEnabled = function () : number {
console.log(TAG, "isNotificationEnabled")
return JPushInterface.isNotificationEnabled(UTSAndroid.getAppContext())
}
export const goToAppNotificationSettings = function () {
console.log(TAG, "goToAppNotificationSettings")
JPushInterface.goToAppNotificationSettings(UTSAndroid.getAppContext())
}
export const setBadgeNumber = function (curNum : Int) {
console.log(TAG, "setBadgeNumber", curNum)
JPushInterface.setBadgeNumber(UTSAndroid.getAppContext(), curNum)
}
export const setSmartPushEnable = function (isEnable : boolean) {
console.log(TAG, "setSmartPushEnable", isEnable)
JPushInterface.setSmartPushEnable(UTSAndroid.getAppContext(), isEnable)
}
export const setGeofenceEnable = function (isEnable : boolean) {
console.log(TAG, "setGeofenceEnable", isEnable)
JPushInterface.setGeofenceEnable(UTSAndroid.getAppContext(), isEnable)
}
export const setDataInsightsEnable = function (isEnable : boolean) {
console.log(TAG, "setDataInsightsEnable", isEnable)
JPushInterface.setDataInsightsEnable(UTSAndroid.getAppContext(), isEnable)
}
export const testCountryCode = function (code:string) {
JCoreInterface.testCountryCode(UTSAndroid.getAppContext(), code)
}
export const setCountryCode = function (code:string) {
JCoreInterface.setCountryCode(UTSAndroid.getAppContext(), code)
}
export const setKeepLongConnInBackground = function (keep : boolean) {
console.log(TAG, "setKeepLongConnInBackground", keep)
JPushInterface.setKeepLongConnInBackground(UTSAndroid.getAppContext(), keep)
}
/**
* 请求订阅小米推送消息渠道。
* 仅已集成并注册小米通道的小米设备支持,单次最多处理 3 个 channelId。
* 调用结果通过 onCommandResult 回调返回,cmd 为 2012。
*/
export const requestSubscribeChannel = function (channelIds : string[]) {
console.log(TAG, "requestSubscribeChannel", channelIds)
const channels = new ArrayList<string>()
for (let i = 0; i < channelIds.length; i++) {
channels.add(channelIds[i])
}
JPushInterface.requestSubscribeChannel(UTSAndroid.getAppContext(), channels)
}
@UTSJS.keepAlive
export function setEventCallBack(param : EventCallBackParams) : void {
eventCallbackManager.setEventCallBack(param)
}
// New APIs: each native SDK completion owns only a request ID, never a page callback.
import JPushUPSManager from 'cn.jpush.android.ups.JPushUPSManager'
import UPSTurnCallBack from 'cn.jpush.android.ups.UPSTurnCallBack'
import TokenResult from 'cn.jpush.android.ups.TokenResult'
import Handler from 'android.os.Handler'
import Looper from 'android.os.Looper'
import Runnable from 'java.lang.Runnable'
import AtomicLong from 'java.util.concurrent.atomic.AtomicLong'
import { PushServiceResult, LiveActivityResult, LiveActivityPushTokenParams, LiveActivityPushToStartTokenParams } from '../interface.uts'
type PendingPushReply = { generation: Long, resolve: (value: PushServiceResult) => void, reject: (error: Error) => void }
const pendingPushReplies = new Map<Long, PendingPushReply>()
const requestSequence = new AtomicLong(0)
const upgradeGeneration = new AtomicLong(0)
class MainUpgradeTask implements Runnable {
private action: (() => void) | null
constructor(action: () => void) { this.action = action }
override run(): void { const action = this.action; this.action = null; action?.() }
}
function upgradeOnMain(action: () => void): void {
new Handler(Looper.getMainLooper()).post(new MainUpgradeTask(action))
}
function finishPushReply(id: Long, value: PushServiceResult | null, code: string | null): void {
upgradeOnMain(() => {
const pending = pendingPushReplies.get(id)
if (pending == null) return
pendingPushReplies.delete(id)
if (pending.generation != upgradeGeneration.get()) return
if (code != null) pending.reject(new Error(code))
else if (value != null) pending.resolve(value)
})
}
class UpgradePushCallback implements UPSTurnCallBack {
private request: Long
private enabled: boolean
constructor(request: Long, enabled: boolean) { this.request = request; this.enabled = enabled }
override onResult(result: TokenResult | null): void {
if (result == null) { finishPushReply(this.request, null, 'NATIVE_EXCEPTION'); return }
const value: PushServiceResult = { code: Number.from(result.getReturnCode()) }
if (this.enabled) value.dispatched = true
finishPushReply(this.request, value, null)
}
}
export function clearUpgradeCallbacks(): void {
upgradeGeneration.incrementAndGet()
upgradeOnMain(() => {
const current = upgradeGeneration.get()
const expired = new Array<Long>()
pendingPushReplies.forEach((reply, id) => { if (reply.generation != current) expired.push(id) })
for (const id of expired) { pendingPushReplies.delete(id) }
})
}
UTSAndroid.onAppActivityDestroy(() => { clearUpgradeCallbacks() })
function changePushService(enabled: boolean): Promise<PushServiceResult> {
const generation = upgradeGeneration.get()
return new Promise<PushServiceResult>((resolve, reject) => {
upgradeOnMain(() => {
if (generation != upgradeGeneration.get()) { reject(new Error('BRIDGE_INVALIDATED')); return }
const context = UTSAndroid.getAppContext()
if (context == null) { reject(new Error('NO_CONTEXT')); return }
const id = requestSequence.incrementAndGet()
pendingPushReplies.set(id, { generation: generation, resolve: resolve, reject: reject })
try {
const callback = new UpgradePushCallback(id, enabled)
if (enabled) JPushUPSManager.turnOnPush(context, callback)
else JPushUPSManager.turnOffPush(context, callback)
} catch (error) { finishPushReply(id, null, 'NATIVE_EXCEPTION') }
})
})
}
export function turnOffPush(): Promise<PushServiceResult> { return changePushService(false) }
export function turnOnPush(): Promise<PushServiceResult> { return changePushService(true) }
export function requestSubscribeChannels(channels: string[]): Promise<void> {
if (channels.length < 1 || channels.length > 3) return Promise.reject(new Error('INVALID_ARGUMENT'))
const unique = new Set<string>()
for (const value of channels) {
if (value.trim().length == 0 || unique.has(value)) return Promise.reject(new Error('INVALID_ARGUMENT'))
unique.add(value)
}
const generation = upgradeGeneration.get()
return new Promise<void>((resolve,reject) => {
upgradeOnMain(() => {
if (generation != upgradeGeneration.get()) { reject(new Error('BRIDGE_INVALIDATED')); return }
const activity = UTSAndroid.getUniActivity()
if (activity == null || activity.isFinishing() || activity.isDestroyed() || !activity.hasWindowFocus()) {
reject(new Error('NO_ACTIVITY')); return
}
const list = new ArrayList<string>()
for (const value of channels) list.add(value)
try { JPushInterface.requestSubscribeChannels(activity,list); resolve() }
catch (error) { reject(new Error('NATIVE_EXCEPTION')) }
})
})
}
export function initCrashHandler(): Promise<void> {
return new Promise<void>((resolve,reject) => { upgradeOnMain(() => {
try { JPushInterface.initCrashHandler(UTSAndroid.getAppContext()); resolve() }
catch (error) { reject(new Error('NATIVE_EXCEPTION')) }
}) })
}
export function stopCrashHandler(): Promise<void> {
return new Promise<void>((resolve,reject) => { upgradeOnMain(() => {
try { JPushInterface.stopCrashHandler(UTSAndroid.getAppContext()); resolve() }
catch (error) { reject(new Error('NATIVE_EXCEPTION')) }
}) })
}
export function getRegistrationIdAsync(): Promise<string> { return Promise.resolve(getRegistrationId()) }
export function isPushStoppedAsync(): Promise<boolean> { return Promise.resolve(isPushStopped()) }
export function setLiveActivityTokenReportEnabled(enable: boolean): Promise<void> { return new Promise<void>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
export function registerLiveActivityPushToken(params: LiveActivityPushTokenParams): Promise<LiveActivityResult> { return new Promise<LiveActivityResult>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
export function registerLiveActivityPushToStartToken(params: LiveActivityPushToStartTokenParams): Promise<LiveActivityResult> { return new Promise<LiveActivityResult>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
export function initAsync(): Promise<void> { return new Promise<void>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
@@ -0,0 +1,21 @@
import Foundation
public class JPushUpgradeCodec {
private static let lifecycleLock = NSLock()
private static var lifecycle: Int64 = 0
public static func generation() -> Int64 { lifecycleLock.lock(); defer { lifecycleLock.unlock() }; return lifecycle }
public static func invalidate() { lifecycleLock.lock(); lifecycle += 1; lifecycleLock.unlock() }
public static func validIdentifier(_ value: String) -> Bool { !value.trimmingCharacters(in: .whitespacesAndNewlines).isEmpty }
public static func validSequence(_ number: NSNumber) -> Bool { let value = number.doubleValue; return value.isFinite && value.rounded(.towardZero) == value && value >= Double(Int32.min) && value <= Double(Int32.max) }
public static func validToken(_ value: String?) -> Bool {
guard let value = value else { return true }
return !value.isEmpty && value.utf8.count % 2 == 0 && value.utf8.allSatisfy { (48...57).contains($0) || (65...70).contains($0) || (97...102).contains($0) }
}
public static func decode(_ value: String?) -> Data? {
guard let value = value, validToken(value) else { return nil }
let bytes = Array(value.utf8)
func nibble(_ b: UInt8) -> UInt8 { b <= 57 ? b - 48 : b <= 70 ? b - 55 : b - 87 }
return Data(stride(from: 0, to: bytes.count, by: 2).map { nibble(bytes[$0]) * 16 + nibble(bytes[$0 + 1]) })
}
public static func encode(_ value: Data?) -> String? { value.map { $0.map { String(format: "%02x", $0) }.joined() } }
}
@@ -0,0 +1,19 @@
//
// JGCOREService.h
// JCore
//
// Created by Shuni Huang on 2024/3/19.
// Copyright © 2024 jiguang. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface JGCOREAPI : NSObject
+ (void)ci:(BOOL)enable;
@end
NS_ASSUME_NONNULL_END
@@ -0,0 +1,27 @@
//
// JGInforCollectionAuth.h
// JCore
//
// Created by 豆瓣 on 2021/10/27.
// Copyright © 2021 jiguang. All rights reserved.
//
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
/// 合规接口,是否授权极光采集一定的设备信息
@interface JGInforCollectionAuthItems : NSObject
/// 是否授权,默认YES
@property(nonatomic,assign)BOOL isAuth;
@end
@interface JGInforCollectionAuth : NSObject
/// 设备信息采集授权接口(合规接口)
/// 请务必在调用初始化、功能性接口前调用此接口进行合规授权
/// @param authBlock auth:YES 则极光认为您同意极光采集一定的设备信息
+(void)JCollectionAuth:(void(^_Nullable)(JGInforCollectionAuthItems *authInfo))authBlock;
@end
NS_ASSUME_NONNULL_END
File diff suppressed because it is too large. Load diff
@@ -0,0 +1,76 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>NSPrivacyTrackingDomains</key>
<array/>
<key>NSPrivacyCollectedDataTypes</key>
<array>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeCrashData</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypeDeviceID</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
<dict>
<key>NSPrivacyCollectedDataType</key>
<string>NSPrivacyCollectedDataTypePreciseLocation</string>
<key>NSPrivacyCollectedDataTypeLinked</key>
<false/>
<key>NSPrivacyCollectedDataTypeTracking</key>
<false/>
<key>NSPrivacyCollectedDataTypePurposes</key>
<array>
<string>NSPrivacyCollectedDataTypePurposeAppFunctionality</string>
</array>
</dict>
</array>
<key>NSPrivacyTracking</key>
<false/>
<key>NSPrivacyAccessedAPITypes</key>
<array>
<dict>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>E174.1</string>
</array>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryDiskSpace</string>
</dict>
<dict>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>CA92.1</string>
</array>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryUserDefaults</string>
</dict>
<dict>
<key>NSPrivacyAccessedAPITypeReasons</key>
<array>
<string>C617.1</string>
</array>
<key>NSPrivacyAccessedAPIType</key>
<string>NSPrivacyAccessedAPICategoryFileTimestamp</string>
</dict>
</array>
</dict>
</plist>
@@ -0,0 +1,8 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
</dict>
</plist>
@@ -0,0 +1,20 @@
{
"frameworks": [
"UIKit.framework",
"CFNetwork.framework",
"CoreFoundation.framework",
"CoreTelephony.framework",
"SystemConfiguration.framework",
"CoreGraphics.framework",
"Foundation.framework",
"Security.framework",
"UserNotifications.framework",
"AdSupport.framework",
"WebKit.framework",
"AppTrackingTransparency.framework",
"StoreKit.framework",
"libz.tbd",
"libresolv.tbd"
],
"deploymentTarget": "12.0"
}
@@ -0,0 +1,720 @@
import { Data } from 'Foundation';
import { Notification } from 'Foundation';
import { NSNotification } from 'Foundation';
import { Dictionary, Set } from 'Swift';
import { NSError } from 'Foundation';
import { NSSet } from 'Foundation';
import { UIDevice, UIApplication } from 'UIKit';
import { ATTrackingManager, ATTrackingManagerAuthorizationStatus } from 'AppTrackingTransparency';
import { ASIdentifierManager } from 'AdSupport';
import { NotificationCenter } from 'Foundation';
import { Selector, NSString } from 'Foundation';
import { UNUserNotificationCenter } from 'UserNotifications';
/* 引入 interface.uts 文件中定义的变量 */
import { EventCallBackParams, EventCallBack } from '../interface.uts';
const TAG = "| JIGUANG | JPUSH-uni-"
// 统一日志方法
function log(message : string, ...args : any[]) : void {
// 这里拼接args
let fullMessage = message
if (args != null && args.length > 0) {
for (let arg of args) {
fullMessage += " " + JSON.stringify(arg)!
}
}
// 可以根据需要选择使用console.log或iOS的log
console.log(TAG, fullMessage)
// 如果需要使用iOS的log,可以取消注释下面的代码
// 构建完整的消息字符串
NSLog("%@ %@ ", TAG, fullMessage)
}
// 事件回调管理类
class EventCallbackManager {
private callBack : EventCallBackParams | null = null
private cachedEvents : Array<EventCallBack> = []
setEventCallBack(param : EventCallBackParams) : void {
log("setEventCallBack")
this.callBack = param
// 如果有缓存的事件,立即回调
if (this.cachedEvents.length > 0) {
log("处理缓存事件,数量:", this.cachedEvents.length)
for (let event of this.cachedEvents) {
this.triggerCallBack(event)
}
this.cachedEvents = []
}
}
triggerCallBack(event : EventCallBack) : void {
if (this.callBack !== null) {
log("触发回调")
if (this.callBack!.callback !== null) {
this.callBack!.callback!(event)
} else {
log("未设置回调函数,事件内容:", event)
}
} else {
log("回调未设置,缓存事件")
this.cachedEvents.push(event)
}
}
/**
* 统一处理回调的方法
* @param eventName 事件名称
* @param eventData 事件数据(JSON字符串)
*/
triggerEvent(eventName : string, eventData : string) : void {
const callback : EventCallBack = {
eventName: eventName,
eventData: eventData
}
this.triggerCallBack(callback)
}
getCallBack() : EventCallBackParams | null {
return this.callBack
}
hasCallBack() : boolean {
return this.callBack !== null && this.callBack!.callback !== null
}
}
// 全局事件回调管理器实例
const eventCallbackManager = new EventCallbackManager()
export type InitPushParams = {
appkey : string,
channel : string,
isProduction : boolean,
advertisingId : string
}
/**
* iOS UTS插件实现 - 极光推送
* 对应AppDelegate.m的功能
*/
export class JGPushIOSPlugin implements UTSiOSHookProxy {
// MARK: - 应用程序生命周期回调
/**
* UTS插件创建时的回调
*/
onCreate() : void {
log("JGPushIOSPlugin onCreate")
}
/**
* 应用正常启动时的回调
* 极光推送初始化
*/
applicationDidFinishLaunchingWithOptions(application : UIApplication | null, launchOptions : Map<UIApplication.LaunchOptionsKey, any> | null = null) : boolean {
log("JGPushIOSPlugin applicationDidFinishLaunchingWithOptions")
// 保存启动选项供后续使用
JGPushTool.launchOptions = launchOptions
// 注册方法在DidFinishLaunching方法写一遍,否则点击通知冷启动app不会走系统的通知点击回调反复。
const entity = JPUSHRegisterEntity()
entity.types = 0
JPUSHService.register(forRemoteNotificationConfig = entity, delegate = JGPushTool)
return true
}
/**
* 远程通知注册成功时的回调
* 极光推送:将deviceToken发送给服务端
*/
didRegisterForRemoteNotifications(deviceToken : Data | null) {
log("JGPushIOSPlugin didRegisterForRemoteNotifications")
JGPushTool.registerDeviceToken(deviceToken)
}
/**
* 远程通知注册失败时的回调
*/
didFailToRegisterForRemoteNotifications(error : NSError | null) {
log("JGPushIOSPlugin didFailToRegisterForRemoteNotifications", error)
}
/**
* 收到远程通知时的回调
*/
didReceiveRemoteNotification(userInfo : Map<AnyHashable, any> | null) {
log("JGPushIOSPlugin didReceiveRemoteNotification", userInfo)
}
}
/**
* 极光推送模块实现
*/
class JGPushModule implements JPUSHRegisterDelegate {
launchOptions : Map<UIApplication.LaunchOptionsKey, any> | null = null
/**
* 初始化极光推送
*/
initPush(param : InitPushParams) {
log("JGPushModule initPush", param)
const method = Selector("didReceiveCustomMessage:")
NotificationCenter.default.addObserver(this, selector = method, name = NSNotification.Name.jpfNetworkDidReceiveMessage, object = null)
// NotificationCenter.default.addObserver(this, selector=method, name=NSNotification.Name("kJPUSHNetworkDidReceiveMessageNotification"), object=null)
const method1 = Selector("networkDidLogin:")
NotificationCenter.default.addObserver(this, selector = method1, name = NSNotification.Name.jpfNetworkDidLogin, object = null)
// NotificationCenter.default.addObserver(this, selector=method1, name=NSNotification.Name("kJPFNetworkDidLoginNotification"), object=null)
const method2 = Selector("networkDidClose:")
NotificationCenter.default.addObserver(this, selector = method2, name = NSNotification.Name.jpfNetworkDidClose, object = null)
// 初始化极光推送服务
JPUSHService.setup(withOption = this.launchOptions, appKey = param.appkey, channel = param.channel, apsForProduction = param.isProduction, advertisingIdentifier = param.advertisingId)
// 创建推送注册实体
const entity = JPUSHRegisterEntity()
const types = new JPAuthorizationOptions(rawValue = (JPAuthorizationOptions.alert.rawValue |
JPAuthorizationOptions.sound.rawValue |
JPAuthorizationOptions.badge.rawValue))
entity.types = Int(types.rawValue)
// 注册远程通知配置
JPUSHService.register(forRemoteNotificationConfig = entity, delegate = this)
log("极光推送SDK初始化完成")
}
/**
* 注册设备令牌
*/
registerDeviceToken(token : Data | null) {
log("JGPushModule registerDeviceToken", token)
JPUSHService.registerDeviceToken(token!)
}
/**
* 收到自定义消息回调
*/
@objc didReceiveCustomMessage(notification : Notification) {
log("JGPushModule didReceiveCustomMessage", notification)
const userInfo = notification.userInfo
if (userInfo !== null) {
const jsonString = JSON.stringify(userInfo! as Dictionary<String, Any>)
if (jsonString !== null) {
eventCallbackManager.triggerEvent("onCustomMessage", jsonString!)
}
}
}
/**
* 网络连接成功回调
*/
@objc networkDidLogin(notification : Notification) {
log("JGPushModule networkDidLogin", notification)
eventCallbackManager.triggerEvent("onConnected", "true")
}
/**
* 网络连接关闭回调
*/
@objc networkDidClose(notification : Notification) {
log("JGPushModule networkDidClose", notification)
eventCallbackManager.triggerEvent("onConnected", "false")
}
/**
* iOS 10 Support - 应用在前台时收到通知
*/
jpushNotificationCenter(center : UNUserNotificationCenter, @argumentLabel("willPresent") notification : UNNotification, @argumentLabel("withCompletionHandler") completionHandler : (code : Int) => void) : void {
log("JGPushModule jpushNotificationCenter willPresent")
// Required
const userInfo = notification.request.content.userInfo
if ((notification.request.trigger?.isKind(of = UNPushNotificationTrigger.self)) != null) {
JPUSHService.handleRemoteNotification(userInfo)
}
const u = userInfo as Dictionary<String, Any>;
const jsonString = JSON.stringify(u)
eventCallbackManager.triggerEvent("onNotifyMessageArrived", jsonString!)
completionHandler(Int(UNNotificationPresentationOptions.alert.rawValue) | Int(UNNotificationPresentationOptions.sound.rawValue) | Int(UNNotificationPresentationOptions.badge.rawValue))
}
/**
* iOS 10 Support - 用户点击通知
*/
jpushNotificationCenter(center : UNUserNotificationCenter, @argumentLabel("didReceive") response : UNNotificationResponse, @argumentLabel("withCompletionHandler") completionHandler : () => void) : void {
log("JGPushModule jpushNotificationCenter didReceive")
// Required
const userInfo = response.notification.request.content.userInfo
if ((response.notification.request.trigger?.isKind(of = UNPushNotificationTrigger.self)) != null) {
JPUSHService.handleRemoteNotification(userInfo)
}
const u = userInfo as Dictionary<String, Any>;
const jsonString = JSON.stringify(u)
eventCallbackManager.triggerEvent("onClickMessage", jsonString!)
completionHandler() // 系统要求执行这个方法
}
/**
* iOS 12 Support - 用户从通知设置界面进入应用
*/
jpushNotificationCenter(center : UNUserNotificationCenter, @argumentLabel("openSettingsFor") notification : UNNotification) : void {
log("JGPushModule jpushNotificationCenter openSettingsFor")
if (notification !== null && (notification.request.trigger?.isKind(of = UNPushNotificationTrigger.self)) != null) {
// 从通知界面直接进入应用
log("从通知界面直接进入应用")
} else {
// 从通知设置界面进入应用
log("从通知设置界面进入应用")
}
}
/**
* 通知权限授权回调
*/
jpushNotificationAuthorization(status : JPAuthorizationStatus, @argumentLabel("withInfo") info : Map<AnyHashable, any> | null) : void {
log("JGPushModule jpushNotificationAuthorization", status)
// 处理通知权限状态变化
}
}
// 全局极光推送工具实例
const JGPushTool : JGPushModule = new JGPushModule()
// MARK: - 导出函数
/**
* 添加事件回调
*/
@UTSJS.keepAlive
export function setEventCallBack(param : EventCallBackParams) : void {
log("setEventCallBack", param)
eventCallbackManager.setEventCallBack(param)
}
// MARK: - 极光推送API方法
export function initPush(param : InitPushParams) : void {
log("initPush", param);
JGPushTool.initPush(param);
}
/**
* 设置调试模式
*/
export function setDebug(debug : boolean) : void {
log("setDebug", debug)
if (debug) {
JPUSHService.setDebugMode()
} else {
JPUSHService.setLogOFF()
}
}
/**
* 设置进入后台是否允许长连接
*/
export function setBackgroundEnable(isEnable : boolean) : void {
log("setBackgroundEnable:", isEnable)
if (isEnable) {
JPUSHService.setBackgroundEnable(true)
} else {
JPUSHService.setBackgroundEnable(false)
}
}
/**
* 获取推送是否被停止的状态(iOS 6.0.0+)
* @param callback (code, isStopped) code 为 0 表示成功,isStopped 为 true 表示推送已停止。code 为0 时,isStopped的值才有效。
*/
export function getPushStatus(callback : (code : number, isStopped : boolean) => void) : void {
log("getPushStatus")
const completion = (iResCode : Int, isStopped : Boolean) => {
callback(iResCode as number, isStopped as boolean)
}
JPUSHService.getPushStatus(completion)
}
/**
* 获取RegistrationID
*/
export function getRegistrationId() : string {
log("getRegistrationId")
return JPUSHService.registrationID()
}
/**
* 设置标签
*/
export function setTags(sequence : Int, tags : string[]) : void {
log("setTags", sequence, tags)
// 单独定义回调函数,并明确指定其类型
const callback = (iResCode : Int, iTags : Swift.Set<AnyHashable> | null, seq : Int) => {
const result = {
code: iResCode,
tags: iTags,
sequence: seq
}
log("setTags completion", result)
eventCallbackManager.triggerEvent("onTagOperatorResult", JSON.stringify(result)!)
}
const setTags:Swift.Set<String> = new Swift.Set<String>(tags)
JPUSHService.setTags(setTags, completion = callback, seq = sequence)
}
/**
* 添加标签
*/
export function addTags(sequence : Int, tags : string[]) : void {
log("addTags", sequence, tags)
const callback = (iResCode : Int, iTags : Swift.Set<AnyHashable> | null, seq : Int) => {
const result = {
code: iResCode,
tags: iTags,
sequence: seq
}
log("addTags completion", result)
eventCallbackManager.triggerEvent("onTagOperatorResult", JSON.stringify(result)!)
}
const setTags:Swift.Set<String> = new Swift.Set<String>(tags)
JPUSHService.addTags(setTags, completion = callback, seq = sequence)
}
/**
* 删除标签
*/
export function deleteTags(sequence : Int, tags : string[]) : void {
log("deleteTags", sequence, tags)
const callback = (iResCode : Int, iTags : Swift.Set<AnyHashable> | null, seq : Int) => {
const result = {
code: iResCode,
tags: iTags,
sequence: seq
}
log("deleteTags completion", result)
eventCallbackManager.triggerEvent("onTagOperatorResult", JSON.stringify(result)!)
}
const setTags:Swift.Set<String> = new Swift.Set<String>(tags)
JPUSHService.deleteTags(setTags, completion = callback, seq = sequence)
}
/**
* 清除所有标签
*/
export function cleanTags(sequence : Int) : void {
log("cleanTags", sequence)
const callback = (iResCode : Int, iTags : Swift.Set<AnyHashable> | null, seq : Int) => {
const result = {
code: iResCode,
tags: iTags,
sequence: seq
}
log("cleanTags completion", result)
eventCallbackManager.triggerEvent("onTagOperatorResult", JSON.stringify(result)!)
}
JPUSHService.cleanTags(callback, seq = sequence)
}
/**
* 获取所有标签
*/
export function getAllTags(sequence : Int) : void {
log("getAllTags", sequence)
const callback = (iResCode : Int, iTags : Swift.Set<AnyHashable> | null, seq : Int) => {
const result = {
code: iResCode,
tags: iTags,
sequence: seq
}
log("getAllTags completion", result)
eventCallbackManager.triggerEvent("onTagOperatorResult", JSON.stringify(result)!)
}
JPUSHService.getAllTags(callback, seq = sequence)
}
/**
* 验证标签绑定状态
*/
export function checkTagBindState(sequence : Int, tag : string) : void {
log("checkTagBindState", sequence, tag)
const callback =
(iResCode : Int, iTags : Swift.Set<AnyHashable> | null, seq : Int, isBind : boolean) => {
const result = {
code: iResCode,
tags: iTags,
sequence: seq,
isBind: isBind
}
log("validTag completion", result)
eventCallbackManager.triggerEvent("onTagOperatorResult", JSON.stringify(result)!)
}
// JPUSHService.validTag(tag, completion = callback, seq = sequence)
JPUSHService.validTag(tag, completion = callback, seq = sequence)
}
/**
* 设置别名
*/
export function setAlias(sequence : Int, alias : string) : void {
log("setAlias", sequence, alias)
const callback : (iResCode : Int, iAlias : String | null, seq : Int) => void = (iResCode : Int, iAlias : String | null, seq : Int) => {
const result = {
code: iResCode,
alias: iAlias,
sequence: seq
}
log("setAlias completion", result)
eventCallbackManager.triggerEvent("onAliasOperatorResult", JSON.stringify(result)!)
}
JPUSHService.setAlias(alias, completion = callback, seq = sequence)
}
/**
* 删除别名
*/
export function deleteAlias(sequence : Int) : void {
log("deleteAlias", sequence)
const callback : (iResCode : Int, iAlias : String | null, seq : Int) => void = (iResCode : Int, iAlias : String | null, seq : Int) => {
const result = {
code: iResCode,
alias: iAlias,
sequence: seq
}
log("deleteAlias completion", result)
eventCallbackManager.triggerEvent("onAliasOperatorResult", JSON.stringify(result)!)
}
JPUSHService.deleteAlias(callback, seq = sequence)
}
/**
* 获取别名
*/
export function getAlias(sequence : Int) : void {
log("getAlias", sequence)
const callback : (iResCode : Int, iAlias : String | null, seq : Int) => void = (iResCode : Int, iAlias : String | null, seq : Int) => {
const result = {
code: iResCode,
alias: iAlias,
sequence: seq
}
log("getAlias completion", result)
eventCallbackManager.triggerEvent("onAliasOperatorResult", JSON.stringify(result)!)
}
JPUSHService.getAlias(callback, seq = sequence)
}
/**
* 设置手机号码
*/
export function setMobileNumber(sequence : number, mobileNumber : string) : void {
log("setMobileNumber", mobileNumber)
const callback : (error : NSError | null) => void = (error : NSError | null) => {
if (error !== null) {
log("setMobileNumber error", error);
} else {
log("setMobileNumber success");
}
const result = {
code: error === null ? 0 : (error as NSError).code,
message: error === null ? "success" : error,
mobileNumber:mobileNumber,
sequence:sequence
}
log("setMobileNumber completion", result)
eventCallbackManager.triggerEvent("onMobileNumberOperatorResult", JSON.stringify(result)!)
}
JPUSHService.setMobileNumber(mobileNumber, completion = callback);
}
/**
* 设置角标数量
*/
export function setBadgeNumber(curNum : Int) : void {
log("setBadgeNumber", curNum)
// 调用极光推送接口设置角标
JPUSHService.setBadge(curNum)
// 同时调用系统接口设置角标
if (UTSiOS.available("iOS 16.0, *")) {
// iOS 16 及以上使用 UNUserNotificationCenter
UNUserNotificationCenter.current().setBadgeCount(Int(curNum), withCompletionHandler = (error : NSError | null) => {
if (error != null) {
log("setBadgeCount error:", error)
}
})
} else {
// iOS 16 以下使用 UIApplication
UIApplication.shared.applicationIconBadgeNumber = Int(curNum)
}
}
/**
* 重置角标
*/
export function resetBadge() : void {
log("resetBadge")
JPUSHService.resetBadge()
// 同时调用系统接口重置角标
if (UTSiOS.available("iOS 16.0, *")) {
// iOS 16 及以上使用 UNUserNotificationCenter
UNUserNotificationCenter.current().setBadgeCount(0, withCompletionHandler = (error : NSError | null) => {
if (error != null) {
log("resetBadge setBadgeCount error:", error)
}
})
} else {
// iOS 16 以下使用 UIApplication
UIApplication.shared.applicationIconBadgeNumber = 0
}
}
/**
* 获取应用角标数量
*/
export function getBadgeNumber() : number {
const badgeNumber = UIApplication.shared.applicationIconBadgeNumber
log("getBadgeNumber", badgeNumber)
return Number(badgeNumber)
}
/** 退出业务账号时同步清除系统已展示通知和角标,避免下个账号看到旧消息。 */
export function clearNotificationAll() : void {
UNUserNotificationCenter.current().removeAllDeliveredNotifications()
resetBadge()
}
import { DispatchQueue } from 'Dispatch'
import { PushServiceResult, LiveActivityResult, LiveActivityPushTokenParams, LiveActivityPushToStartTokenParams } from '../interface.uts'
type IOSPushReply = { generation: number, resolve: (value: PushServiceResult) => void, reject: (error: Error) => void }
type IOSTokenReply = { generation: number, resolve: (value: LiveActivityResult) => void, reject: (error: Error) => void }
const iosPushReplies = new Map<number, IOSPushReply>()
const iosTokenReplies = new Map<number, IOSTokenReply>()
let iosRequestSequence: number = 0
export function clearUpgradeCallbacks(): void {
JPushUpgradeCodec.invalidate()
DispatchQueue.main.async(execute = () => {
const current = Number.from(JPushUpgradeCodec.generation())
const expiredPush = new Array<number>()
const expiredToken = new Array<number>()
iosPushReplies.forEach((reply, id) => { if (reply.generation != current) expiredPush.push(id) })
iosTokenReplies.forEach((reply, id) => { if (reply.generation != current) expiredToken.push(id) })
for (const id of expiredPush) { iosPushReplies.delete(id) }
for (const id of expiredToken) { iosTokenReplies.delete(id) }
})
}
function finishIOSPush(id: number, result: PushServiceResult): void {
DispatchQueue.main.async(execute = () => {
const pending = iosPushReplies.get(id)
if (pending == null) return
iosPushReplies.delete(id)
if (pending.generation == Number.from(JPushUpgradeCodec.generation())) pending.resolve(result)
})
}
export function turnOffPush(): Promise<PushServiceResult> {
const generation = Number.from(JPushUpgradeCodec.generation())
return new Promise<PushServiceResult>((resolve,reject) => {
DispatchQueue.main.async(execute = () => {
if (generation != Number.from(JPushUpgradeCodec.generation())) { reject(new Error('BRIDGE_INVALIDATED')); return }
iosRequestSequence += 1
const id = iosRequestSequence
iosPushReplies.set(id, {generation:generation,resolve:resolve,reject:reject})
JPUSHService.turnOffPush((code: Int) => { finishIOSPush(id, {code:Number.from(code)}) })
})
})
}
export function turnOnPush(): Promise<PushServiceResult> {
const generation = Number.from(JPushUpgradeCodec.generation())
return new Promise<PushServiceResult>((resolve,reject) => {
DispatchQueue.main.async(execute = () => { if (generation != Number.from(JPushUpgradeCodec.generation())) { reject(new Error('BRIDGE_INVALIDATED')); return }; JPUSHService.turnOnPush(); resolve({dispatched:true}) })
})
}
export function setLiveActivityTokenReportEnabled(enable: boolean): Promise<void> {
const generation = Number.from(JPushUpgradeCodec.generation())
return new Promise<void>((resolve,reject) => {
DispatchQueue.main.async(execute = () => { if (generation != Number.from(JPushUpgradeCodec.generation())) { reject(new Error('BRIDGE_INVALIDATED')); return }; JPUSHService.setLiveActivityTokenReportEnabled(enable); resolve() })
})
}
function registerLiveToken(identifier: string, token: string | null, sequence: number, start: boolean): Promise<LiveActivityResult> {
if (!JPushUpgradeCodec.validIdentifier(identifier) || !JPushUpgradeCodec.validToken(token) || !JPushUpgradeCodec.validSequence(sequence)) {
return new Promise<LiveActivityResult>((resolve,reject) => { reject(new Error('INVALID_ARGUMENT')) })
}
if (start) {
if (UTSiOS.available("iOS 17.2, *")) { } else { return new Promise<LiveActivityResult>((resolve,reject) => { reject(new Error('UNSUPPORTED_OS')) }) }
} else {
if (UTSiOS.available("iOS 16.1, *")) { } else { return new Promise<LiveActivityResult>((resolve,reject) => { reject(new Error('UNSUPPORTED_OS')) }) }
}
const generation = Number.from(JPushUpgradeCodec.generation())
return new Promise<LiveActivityResult>((resolve,reject) => {
DispatchQueue.main.async(execute = () => {
if (generation != Number.from(JPushUpgradeCodec.generation())) { reject(new Error('BRIDGE_INVALIDATED')); return }
iosRequestSequence += 1
const id = iosRequestSequence
iosTokenReplies.set(id, {generation:generation,resolve:resolve,reject:reject})
const completion = (code: Int, activityId: string | null, resultToken: Data | null, seq: Int) => {
DispatchQueue.main.async(execute = () => {
const pending = iosTokenReplies.get(id)
if (pending == null) return
iosTokenReplies.delete(id)
if (pending.generation != Number.from(JPushUpgradeCodec.generation())) return
pending.resolve({code:Number.from(code), activityId:activityId, token:JPushUpgradeCodec.encode(resultToken), sequence:Number.from(seq)})
})
}
if (start) JPUSHService.registerLiveActivity(identifier, pushToStartToken=JPushUpgradeCodec.decode(token), completion=completion, seq=Int(sequence))
else JPUSHService.registerLiveActivity(identifier, pushToken=JPushUpgradeCodec.decode(token), completion=completion, seq=Int(sequence))
})
})
}
export function registerLiveActivityPushToken(params: LiveActivityPushTokenParams): Promise<LiveActivityResult> {
return registerLiveToken(params.activityId,params.token,params.sequence,false)
}
export function registerLiveActivityPushToStartToken(params: LiveActivityPushToStartTokenParams): Promise<LiveActivityResult> {
return registerLiveToken(params.activityAttributes,params.token,params.sequence,true)
}
export function getRegistrationIdAsync(): Promise<string> { return Promise.resolve(getRegistrationId()) }
export function isPushStoppedAsync(): Promise<boolean> { return new Promise<boolean>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
export function requestSubscribeChannels(channels: string[]): Promise<void> { return new Promise<void>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
export function initCrashHandler(): Promise<void> { return new Promise<void>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
export function stopCrashHandler(): Promise<void> { return new Promise<void>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
export function initAsync(): Promise<void> { return new Promise<void>((resolve,reject) => { reject(new Error('UNSUPPORTED_PLATFORM')) }) }
@@ -0,0 +1,45 @@
/**
* interface.uts
* uts插件接口定义文件,按规范定义接口可以在HBuilderX中更好的做到语法提示
*/
export type EventCallBack = {
eventName: string,
eventData: string
}
export type EventCallBackParams = {
callback?: (res: EventCallBack) => void
}
// /**
// * 错误码
// * 根据uni错误码规范要求,建议错误码以90开头,以下是错误码示例:
// * - 9010001 错误信息1
// * - 9010002 错误信息2
// */
// export type MyApiErrorCode = 9010001 | 9010002;
// /**
// * myApi 的错误回调参数
// */
// export interface MyApiFail extends IUniError {
// errCode : MyApiErrorCode
// };
// /* 异步函数定义 */
// export type MyApi = (options : MyApiOptions) => void
// /* 同步函数定义 */
// export type MyApiSync = (paramA : boolean) => MyApiResult
export type PushServiceResult = { code?: number, msg?: string, dispatched?: boolean }
export type LiveActivityPushTokenParams = { activityId: string, token: string | null, sequence: number }
export type LiveActivityPushToStartTokenParams = { activityAttributes: string, token: string | null, sequence: number }
export type LiveActivityResult = { code: number, activityId: string | null, token: string | null, sequence: number }
export type RequestSubscribeChannels = (channels: string[]) => Promise<void>
export type TurnOffPush = () => Promise<PushServiceResult>
export type TurnOnPush = () => Promise<PushServiceResult>
export type CrashHandlerControl = () => Promise<void>
export type LiveActivityTokenReportControl = (enable: boolean) => Promise<void>
export type RegisterLiveActivityPushToken = (params: LiveActivityPushTokenParams) => Promise<LiveActivityResult>
export type RegisterLiveActivityPushToStartToken = (params: LiveActivityPushToStartTokenParams) => Promise<LiveActivityResult>
@@ -0,0 +1,39 @@
// /* 此规范为 uni 规范,可以按照自己的需要选择是否实现 */
// import { MyApiErrorCode, MyApiFail } from "./interface.uts"
// /**
// * 错误主题
// * 注意:错误主题一般为插件名称,每个组件不同,需要使用时请更改。
// * [可选实现]
// */
// export const UniErrorSubject = 'uts-api';
// /**
// * 错误信息
// * @UniError
// * [可选实现]
// */
// export const MyAPIErrors : Map<MyApiErrorCode, string> = new Map([
// /**
// * 错误码及对应的错误信息
// */
// [9010001, 'custom error mseeage1'],
// [9010002, 'custom error mseeage2'],
// ]);
// /**
// * 错误对象实现
// */
// export class MyApiFailImpl extends UniError implements MyApiFail {
// /**
// * 错误对象构造函数
// */
// constructor(errCode : MyApiErrorCode) {
// super();
// this.errSubject = UniErrorSubject;
// this.errCode = errCode;
// this.errMsg = MyAPIErrors.get(errCode) ?? "";
// }
// }