完成初始版本(暂不支持华为的厂商通道)

This commit is contained in:
范大德 2023-07-28 18:28:45 +08:00
commit ee29969ddc
9 changed files with 1321 additions and 0 deletions

20
package.json Normal file
View File

@ -0,0 +1,20 @@
{
"name": "cordova-plugin-tpns",
"version": "0.0.1",
"description": "Tencent Push Notification Service",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"repository": {
"type": "git",
"url": "https://m.shuto.cn:8681/public/cordova-plugin-tpns.git"
},
"keywords": [
"cordova",
"tpns",
"android",
"push"
],
"author": "fandd@shuto.cn"
}

59
plugin.xml Normal file
View File

@ -0,0 +1,59 @@
<?xml version='1.0' encoding='utf-8'?>
<plugin id="cordova-plugin-tpns" version="0.0.1"
xmlns="http://apache.org/cordova/ns/plugins/1.0"
xmlns:android="http://schemas.android.com/apk/res/android">
<name>tpns</name>
<js-module name="TpnsPlugin" src="www/tpns.js">
<clobbers target="Tpns" />
</js-module>
<preference name="XG_ACCESS_ID" />
<preference name="XG_ACCESS_KEY" />
<platform name="android">
<config-file parent="/*" target="res/xml/config.xml">
<feature name="tpns">
<param name="android-package" value="com.shuto.plugin.tpns" />
<param name="XG_ACCESS_ID" value="$XG_ACCESS_ID" />
<param name="XG_ACCESS_KEY" value="$XG_ACCESS_ID" />
</feature>
</config-file>
<config-file parent="/manifest" target="AndroidManifest.xml">
<!-- 【必须】 移动推送 TPNS SDK VIP版本所需权限 -->
<permission
android:name="$PACKAGE_NAME.permission.XGPUSH_RECEIVE"
android:protectionLevel="signature" />
<uses-permission android:name="$PACKAGE_NAME.permission.XGPUSH_RECEIVE" />
<!-- 【必须】 移动推送 TPNS SDK 所需权限 -->
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<!-- 【常用】 移动推送 TPNS SDK所需权限 -->
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.RECEIVE_USER_PRESENT" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.GET_TASKS" />
</config-file>
<config-file target="AndroidManifest.xml" parent="/manifest/application">
<uses-library android:name="org.apache.http.legacy" android:required="false"/>
<receiver android:name="com.shuto.plugin.tpns.TpnsReceiver">
<intent-filter>
<!-- 接收消息透传 -->
<action android:name="com.tencent.android.xg.vip.action.PUSH_MESSAGE" />
<!-- 监听注册、反注册、设置/删除标签、通知被点击等处理结果 -->
<action android:name="com.tencent.android.xg.vip.action.FEEDBACK" />
</intent-filter>
</receiver>
</config-file>
<source-file src="src/android/TpnsPlugin.java" target-dir="src/com/shuto/plugin/tpns" />
<source-file src="src/android/TpnsReceiver.java" target-dir="src/com/shuto/plugin/tpns" />
<source-file src="src/android/CordovaEventKit.java" target-dir="src/com/shuto/plugin/tpns" />
<source-file src="src/android/Events.java" target-dir="src/com/shuto/plugin/tpns" />
<source-file src="src/android/Listener.java" target-dir="src/com/shuto/plugin/tpns" />
<framework src="src/android/build-tpns.gradle" custom="true" type="gradleReference" />
</platform>
</plugin>

View File

@ -0,0 +1,52 @@
package com.shuto.plugin.tpns;
import android.util.Log;
import org.apache.cordova.CordovaPlugin;
import org.json.JSONArray;
import org.json.JSONObject;
public class CordovaEventKit {
public static CordovaEventKit kit = null;
private static final String TAG = CordovaEventKit.class.getSimpleName();
private CordovaPlugin plugin;
private CordovaEventKit(CordovaPlugin plugin) {
this.plugin = plugin;
}
public static void init(CordovaPlugin plugin){
Log.d(TAG, "init");
if(CordovaEventKit.kit == null){
CordovaEventKit.kit = new CordovaEventKit(plugin);
}
}
public void fireEvent(String event, JSONArray obj){
this.fireEvent(event,obj == null ? null : obj.toString());
}
public void fireEvent(String event, JSONObject obj){
this.fireEvent(event,obj == null ? null :obj.toString());
}
public void fireEvent(String event, String obj){
Log.d(TAG,"fireEvent --- event:"+event+",obj:"+obj);
if (plugin == null || event == null || obj == null) {
Log.w(TAG,"fireEvent --- plugin:"+plugin);
return;
}
event = event.replace('\'','_');
String format = "window.Tpns.fireEvent('%s',%s);";
final String js = String.format(format,event, obj);
plugin.cordova.getActivity().runOnUiThread(new Runnable() {
@Override
public void run() {
Log.d(TAG,"fireEvent --- code:"+js);
plugin.webView.loadUrl("javascript:" + js);
}
});
}
}

59
src/android/Events.java Normal file
View File

@ -0,0 +1,59 @@
package com.shuto.plugin.tpns;
import android.os.Bundle;
import android.util.Log;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class Events {
private static final String TAG = Events.class.getSimpleName();
private static final String PREFIX = "com.tencent.trtc.event";
private static final Map<String, List<Listener>> events = new HashMap();
public static void fireEvent(String event){
fireEvent(event,null);
}
public static void fireEvent(String event, Extra extra){
Log.d(TAG,"fireEvent --- event:"+event+",extra:"+ extra);
if(events.containsKey(PREFIX+event)){
for(Listener listener : events.get(PREFIX+event)){
Bundle bundle = extra == null ? Bundle.EMPTY: new Bundle();
if(extra != null){
extra.extra(bundle);
}
Log.d(TAG,"fireEvent --- event:"+event+",bundle:"+ bundle);
listener.on(extra == null ? Bundle.EMPTY : bundle);
}
}
}
public static void addListener(String eventName,Listener listener){
Log.d(TAG,"addListener --- event:"+eventName+",listener:"+listener.hashCode());
if(!events.containsKey(PREFIX+eventName)){
events.put(PREFIX+eventName,new ArrayList<>());
}
List<Listener> list = events.get(PREFIX+eventName);
if(!list.contains(listener)){
list.add(listener);
}
}
public static void removeListener(String eventName,Listener listener){
Log.d(TAG,"removeListener --- event:"+eventName+",listener:"+listener.hashCode());
if(!events.containsKey(PREFIX+eventName)){
events.put(PREFIX+eventName,new ArrayList<>());
}
List<Listener> list = events.get(PREFIX+eventName);
if(list.contains(listener)){
list.remove(listener);
}
}
public interface Extra{
public void extra(Bundle extra);
}
}

View File

@ -0,0 +1,7 @@
package com.shuto.plugin.tpns;
import android.os.Bundle;
public interface Listener {
void on(Bundle extra);
}

653
src/android/TpnsPlugin.java Normal file
View File

@ -0,0 +1,653 @@
package com.shuto.plugin.tpns;
import android.content.Context;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import com.tencent.android.tpush.XGIOperateCallback;
import com.tencent.android.tpush.XGLocalMessage;
import com.tencent.android.tpush.XGPushConfig;
import com.tencent.android.tpush.XGPushManager;
import org.apache.cordova.CordovaPlugin;
import org.apache.cordova.CallbackContext;
import org.apache.cordova.CordovaWebView;
import org.apache.cordova.CordovaInterface;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
import java.lang.reflect.Method;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Iterator;
import java.util.List;
import java.util.Set;
/**
* This class echoes a string called from JavaScript.
*/
public class TpnsPlugin extends CordovaPlugin {
private static final String TAG = TpnsPlugin.class.getSimpleName();
private Context mContext;
@Override
public void initialize(CordovaInterface cordova, CordovaWebView webView) {
super.initialize(cordova, webView);
mContext = cordova.getActivity().getApplicationContext();
CordovaEventKit.init(this);
Log.d(TAG,"initialize plugin");
}
@Override
public boolean execute(String action, JSONArray args, CallbackContext callbackContext) throws JSONException {
cordova.getThreadPool().execute(new Runnable() {
@Override
public void run() {
try {
Method method = TpnsPlugin.class.getDeclaredMethod(action, JSONArray.class, CallbackContext.class);
method.invoke(TpnsPlugin.this, args, callbackContext);
} catch (Exception e) {
Log.e(TAG, e.toString());
callbackContext.error(e.getLocalizedMessage());
}
}
});
return true;
}
private void enableDebug(JSONArray data, CallbackContext callbackContext) {
boolean mode;
try {
mode = data.getBoolean(0);
XGPushConfig.enableDebug(mContext,mode);
callbackContext.success();
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 关闭联合保活能力1.1.6.1+
* @param data
* @param callbackContext
*/
private void enablePullUpOtherApp(JSONArray data, CallbackContext callbackContext) {
boolean mode;
try {
mode = data.getBoolean(0);
XGPushConfig.enablePullUpOtherApp(mContext,mode);
callbackContext.success();
} catch (JSONException e) {
e.printStackTrace();
}
}
/**
* 获取设备 Token
* @param data
* @param callbackContext
*/
private void getToken(JSONArray data, CallbackContext callbackContext) {
callbackContext.success(XGPushConfig.getToken(mContext));
}
/**
* 获取第三方厂商 Token
* @param data
* @param callbackContext
*/
private void getOtherPushToken(JSONArray data, CallbackContext callbackContext) {
callbackContext.success(XGPushConfig.getOtherPushToken(mContext));
}
private void registerPush(JSONArray data, CallbackContext callbackContext) {
try{
JSONObject params = data.optJSONObject(0);
if(params !=null){
XGPushConfig.enableOtherPush(mContext, true);
Iterator<String> keys = params.keys();
while (keys.hasNext()) {
String type = keys.next();
JSONObject value = params.getJSONObject(type);
switch (type){
case "MZ":
XGPushConfig.setMzPushAppId(mContext, value.getString("APP_ID"));
XGPushConfig.setMzPushAppKey(mContext, value.getString("APP_KEY"));
break;
case "OPPO":
XGPushConfig.setOppoPushAppId(mContext, value.getString("appKey"));
XGPushConfig.setOppoPushAppKey(mContext, value.getString("appSecret"));
break;
case "MI":
XGPushConfig.setMiPushAppId(mContext, value.getString("APPID"));
XGPushConfig.setMiPushAppKey(mContext, value.getString("APPKEY"));
break;
case "HW":
break;
case "RY":
break;
}
}
}
} catch (JSONException e){
Log.e(TAG,e.getLocalizedMessage());
}
XGPushManager.registerPush(mContext, new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int flag) {
Log.d(TAG, "注册成功设备token为" + data);
callbackContext.success((String)data);
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "注册失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
}
private void unregisterPush(JSONArray data, CallbackContext callbackContext) {
XGPushManager.unregisterPush(mContext, new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "反注册成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "反注册失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
}
private void createNotificationChannel(JSONArray data, CallbackContext callbackContext){
JSONObject param;
try {
param = data.getJSONObject(0);
XGPushManager.createNotificationChannel(mContext,
param.getString("channelId"), param.getString("channelName"),
param.optBoolean("enableVibration"), param.optBoolean("enableLights"),
param.optBoolean("enableSound"), Uri.parse(param.optString("soundUri")));
callbackContext.success();
} catch (JSONException e) {
e.printStackTrace();
callbackContext.error(e.getLocalizedMessage());
}
}
private void addLocalNotification(JSONArray data, CallbackContext callbackContext){
try{
JSONObject param = data.getJSONObject(0);
//新建本地通知
XGLocalMessage local_msg = new XGLocalMessage();
//设置本地消息类型1:通知2:消息
local_msg.setType(param.optInt("type",1));
// 设置消息标题
local_msg.setTitle(param.getString("title"));
//设置消息内容
local_msg.setContent(param.getString("content"));
//设置消息日期格式为20140502
local_msg.setDate(param.optString("date",new SimpleDateFormat("yyyyMMdd ").format(new Date())));
//设置消息触发的小时(24小时制)例如22代表晚上10点
local_msg.setHour(param.optString("hour",new SimpleDateFormat("HH").format(new Date())));
//获取消息触发的分钟例如05代表05分
local_msg.setMin(param.optString("min",new SimpleDateFormat("mm").format(new Date())));
//设置消息样式默认为0或不设置
local_msg.setBuilderId(param.optInt("builderId",0));
//设置动作类型1打开activity或App本身2打开浏览器3打开Intent 4通过包名打开应用
int actionType = param.getInt("actionType");
local_msg.setAction_type(actionType);
switch (actionType){
case 1:
//设置拉起应用页面
local_msg.setActivity( param.getString("activity"));
break;
case 2:
// 设置URL
local_msg.setUrl(param.getString("url"));
break;
case 3:
// 设置Intent
local_msg.setIntent(param.getString("intent"));
break;
}
// 是否覆盖原先build_id的保存设置1覆盖0不覆盖
local_msg.setStyle_id(param.optInt("styleId",1));
// 设置音频资源
local_msg.setRing_raw(param.optString("ringRaw"));
JSONObject body = param.optJSONObject("data");
// 设置key,value
HashMap<String, Object> map = new HashMap<String, Object>();
if(data!=null){
Iterator<String> keys = body.keys();
while (keys.hasNext()){
String key = keys.next();
map.put(key,body.opt(key));
}
}
local_msg.setCustomContent(map);
//添加通知到本地
XGPushManager.addLocalNotification(mContext,local_msg);
callbackContext.success();
} catch (JSONException e){
e.printStackTrace();
callbackContext.error(e.getLocalizedMessage());
}
}
private void clearLocalNotifications(JSONArray data, CallbackContext callbackContext){
XGPushManager.clearLocalNotifications(mContext);
callbackContext.success();
}
/**
* 对一个或多个账号类型的账号进行解绑SDK 1.2.3.0+
* eg:[1001,1002]
* @param data
*/
private void delAccounts(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "delAccounts | params: " + data);
try {
Set<Integer> accountInfos = new HashSet<>();
JSONArray accInfoArr = data.getJSONArray(0);
for(int i=0; i < accInfoArr.length(); i++) {
int accountType = accInfoArr.optInt(i,0);
accountInfos.add(accountType);
}
XGPushManager.delAccounts(mContext, accountInfos,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "对一个或多个账号类型的账号进行解绑成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "对一个或多个账号类型的账号进行解绑失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 对的所有已绑定账号进行解绑
* @param data
*/
private void clearAccounts(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "clearAccounts | params: " + data);
XGPushManager.clearAccounts(mContext,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "对的所有已绑定账号进行解绑成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "对的所有已绑定账号进行解绑失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
}
/**
* 添加或更新账号若原来没有该类型账号则添加若原来有则覆盖可以同时添加多个账号一个账号对应一个账号类型
* eg:[{"account":elva, "accountType":1001}, {"account":jay, "accountType":1002}]
* @param data
*/
private void upsertAccounts(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "upsertAccounts | params: " + data);
try {
List<XGPushManager.AccountInfo> accountInfos = new ArrayList<>();
JSONArray accInfoArr = data.getJSONArray(0);
for(int i=0; i < accInfoArr.length(); i++) {
JSONObject accInfoJo = accInfoArr.optJSONObject(i);
if(accInfoJo == null) {
continue;
}
String account = accInfoJo.optString("account","");
int accountType = accInfoJo.optInt("accountType", 0);
XGPushManager.AccountInfo info = new XGPushManager.AccountInfo(accountType, account);
accountInfos.add(info);
}
XGPushManager.upsertAccounts(mContext, accountInfos,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "添加或更新账号成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "添加或更新账号失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 覆盖多个标签 一次设置多个标签会覆盖这个设备之前设置的标签
*/
private void clearAndAppendTags(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "clearAndAppendTags | params: " + data);
try {
Set<String> tags = new HashSet<>();
String operateName = data.getString(0);
JSONArray accInfoArr = data.getJSONArray(1);
for(int i=0; i < accInfoArr.length(); i++) {
String tag = accInfoArr.optString(i);
tags.add(tag);
}
XGPushManager.clearAndAppendTags(mContext,operateName, tags,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "覆盖多个标签成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "覆盖多个标签失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 新增多个标签
* 如果新覆盖的标签都带有 : 例如 test:2, level:2则会删除这个设备已绑定的所有 test:* level:* 标签再新增 test:2 level:2
* 如果新增的标签有部分不带 : 例如 test:2 level则会删除这个设备的全部历史标签再新增 test:2 level 标签
*/
private void appendTags(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "appendTags | params: " + data);
try {
Set<String> tags = new HashSet<>();
String operateName = data.getString(0);
JSONArray accInfoArr = data.getJSONArray(1);
for(int i=0; i < accInfoArr.length(); i++) {
String tag = accInfoArr.optString(i);
tags.add(tag);
}
XGPushManager.appendTags(mContext,operateName, tags,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "新增多个标签成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "新增多个标签失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 一次删除多个标签
*/
private void delTags(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "delTags | params: " + data);
try {
Set<String> tags = new HashSet<>();
String operateName = data.getString(0);
JSONArray accInfoArr = data.getJSONArray(1);
for(int i=0; i < accInfoArr.length(); i++) {
String tag = accInfoArr.optString(i);
tags.add(tag);
}
XGPushManager.delTags(mContext,operateName, tags,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "一次删除多个标签成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "一次删除多个标签失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 清除这个设备的所有标签
*/
private void clearTags(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "clearTags | params: " + data);
try {
String operateName = data.getString(0);
XGPushManager.clearTags(mContext,operateName,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "清除这个设备的所有标签成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "清除这个设备的所有标签失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 获取这个设备的标签
*/
private void queryTags(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "queryTags | params: " + data);
try {
String operateName = data.getString(0);
int start = data.optInt(1,0);
int size = data.optInt(2,100);
Events.addListener("queryTags." + operateName, new Listener() {
@Override
public void on(Bundle extra) {
Log.d(TAG,"接收到查询标签结果");
callbackContext.success(msg(extra.getInt("code"),extra.getString("data")));
Events.removeListener("queryTags." + operateName,this);
}
});
XGPushManager.queryTags(mContext,operateName,start,size,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "清除这个设备的所有标签成功");
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "清除这个设备的所有标签失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 添加属性带回调有则覆盖无则添加
*/
private void upsertAttributes(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "upsertAttributes | params: " + data);
try {
String operateName = data.getString(0);
JSONObject body = data.optJSONObject(1);
HashMap<String, String> map = new HashMap<>();
if(data!=null){
Iterator<String> keys = body.keys();
while (keys.hasNext()){
String key = keys.next();
map.put(key,body.optString(key));
}
}
XGPushManager.upsertAttributes(mContext,operateName,map,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "添加属性成功");
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "添加属性失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 更新用户属性
*/
private void clearAndAppendAttributes(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "clearAndAppendAttributes | params: " + data);
try {
String operateName = data.getString(0);
JSONObject body = data.optJSONObject(1);
HashMap<String, String> map = new HashMap<>();
if(data!=null){
Iterator<String> keys = body.keys();
while (keys.hasNext()){
String key = keys.next();
map.put(key,body.optString(key));
}
}
XGPushManager.clearAndAppendAttributes(mContext,operateName,map,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "更新用户属性成功");
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "更新用户属性失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 删除指定的属性
*
*/
private void delAttributes(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "delAttributes | params: " + data);
try {
String operateName = data.getString(0);
Set<String> attrs = new HashSet<>();
JSONArray accInfoArr = data.getJSONArray(1);
for(int i=0; i < accInfoArr.length(); i++) {
String tag = accInfoArr.optString(i);
attrs.add(tag);
}
XGPushManager.delAttributes(mContext,operateName, attrs,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "删除指定的属性成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "删除指定的属性失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
* 删除已设置的所有属性
*/
private void clearAttributes(JSONArray data, CallbackContext callbackContext) {
Log.d(TAG, "clearAttributes | params: " + data);
try {
String operateName = data.getString(0);
XGPushManager.clearAttributes(mContext,operateName,new XGIOperateCallback() {
@Override
public void onSuccess(Object data, int i) {
Log.d(TAG, "删除已设置的所有属性成功");
callbackContext.success();
}
@Override
public void onFail(Object data, int errCode, String msg) {
Log.d(TAG, "删除已设置的所有属性失败,错误码:" + errCode + ",错误信息:" + msg);
callbackContext.error(msg(errCode,msg));
}
});
} catch (JSONException e) {
Log.d(TAG, "setAccount exception : " + e.getMessage());
callbackContext.error(e.getLocalizedMessage());
}
}
/**
*
* @param data
* @param callbackContext
*/
private void cancelAllNotifaction(JSONArray data, CallbackContext callbackContext){
XGPushManager.cancelAllNotifaction(mContext);
callbackContext.success();
}
private JSONObject msg(int code, String msg){
JSONObject obj = new JSONObject();
try {
obj.put("code",code);
obj.put("message",msg);
}catch (JSONException e){
Log.e(TAG,e.getMessage());
}finally {
return obj;
}
}
}

View File

@ -0,0 +1,125 @@
// ~ Copyright (c) 2023 Beijing Shuto Technology Co,. Ltd. All rights reserved.
package com.shuto.plugin.tpns;
import android.content.Context;
import android.os.Bundle;
import android.util.Log;
import com.tencent.android.tpush.NotificationAction;
import com.tencent.android.tpush.XGPushBaseReceiver;
import com.tencent.android.tpush.XGPushClickedResult;
import com.tencent.android.tpush.XGPushRegisterResult;
import com.tencent.android.tpush.XGPushShowedResult;
import com.tencent.android.tpush.XGPushTextMessage;
import org.json.JSONException;
import org.json.JSONObject;
public abstract class TpnsReceiver extends XGPushBaseReceiver {
private static final String TAG = TpnsPlugin.class.getSimpleName();
/**
* 消息透传处理
* @param context
* @param message 解析自定义的 JSON
*/
@Override
public void onTextMessage(Context context, XGPushTextMessage message) {
String text = "收到消息:" + message.toString();
// APP自主处理消息的过程...
JSONObject obj = null;
if(message !=null){
try{
obj = new JSONObject();
obj.put("content",message.getContent());
obj.put("customContent",message.getCustomContent());
obj.put("msgId",message.getMsgId());
obj.put("channel",message.getPushChannel());
obj.put("templateId",message.getTemplateId());
obj.put("title",message.getTitle());
obj.put("traceId",message.getTraceId());
}catch (JSONException e){
Log.e(TAG,e.getLocalizedMessage());
}
}
CordovaEventKit.kit.fireEvent("onTextMessage",obj);
Log.d(TAG, text);
}
@Override
public void onNotificationShowedResult(Context context, XGPushShowedResult notifiShowedRlt){
JSONObject obj = null;
if(notifiShowedRlt !=null){
try{
obj = new JSONObject();
obj.put("activity",notifiShowedRlt.getActivity());
obj.put("content",notifiShowedRlt.getContent());
obj.put("customContent",notifiShowedRlt.getCustomContent());
obj.put("msgId",notifiShowedRlt.getMsgId());
obj.put("notifactionId",notifiShowedRlt.getNotifactionId());
obj.put("actionType",notifiShowedRlt.getNotificationActionType());
obj.put("channel",notifiShowedRlt.getPushChannel());
obj.put("templateId",notifiShowedRlt.getTemplateId());
obj.put("title",notifiShowedRlt.getTitle());
obj.put("traceId",notifiShowedRlt.getTraceId());
}catch (JSONException e){
Log.e(TAG,e.getLocalizedMessage());
}
}
CordovaEventKit.kit.fireEvent("onNotificationShowedResult",obj);
}
// 通知点击回调actionType=0 为该消息被点击actionType=2 为该消息被清除
@Override
public void onNotificationClickedResult(Context context, XGPushClickedResult message) {
if (context == null || message == null) {
return;
}
String text = "";
if (message.getActionType() == NotificationAction.clicked.getType()) {
// 通知在通知栏被点击
// APP自己处理点击的相关动作
text = "通知被打开 :" + message;
} else if (message.getActionType() == NotificationAction.delete.getType()) {
// 通知被清除
// APP自己处理通知被清除后的相关动作
text = "通知被清除 :" + message;
}
JSONObject obj = null;
if(message !=null){
try{
obj = new JSONObject();
obj.put("activity",message.getActivityName());
obj.put("content",message.getContent());
obj.put("customContent",message.getCustomContent());
obj.put("msgId",message.getMsgId());
obj.put("actionType",message.getNotificationActionType());
obj.put("channel",message.getPushChannel());
obj.put("templateId",message.getTemplateId());
obj.put("title",message.getTitle());
obj.put("traceId",message.getTraceId());
}catch (JSONException e){
Log.e(TAG,e.getLocalizedMessage());
}
}
CordovaEventKit.kit.fireEvent("onNotificationClickedResult",obj);
// APP自主处理的过程
Log.d(TAG, "广播接收到通知:" + text);
}
@Override
public void onQueryTagsResult(Context context, int errorCode, String data, String operateName) {
Log.i(TAG, "action - onQueryTagsResult, errorCode:" + errorCode + ", operateName:" + operateName + ", data: " + data);
Events.fireEvent("queryTags." + operateName, new Events.Extra() {
@Override
public void extra(Bundle extra) {
extra.putInt("code",errorCode);
extra.putString("data",data);
}
});
}
}

View File

@ -0,0 +1,53 @@
def getConfigPreference(name) {
name = name.toLowerCase()
def xml = file("src/main/res/xml/config.xml").getText()
// Disable namespace awareness since Cordova doesn't use them properly
def root = new XmlParser(false, false).parseText(xml)
def ret, defaultValue
root.feature.each { it ->
def attrName = it.attribute("name")
if (attrName && attrName.toLowerCase() == "tpns") {
it.param.each { p ->
def pName = p.attribute("name")
if (p.attribute('default') != null) {
defaultValue = p.attribute('default');
} else {
ret = p.attribute("value")
}
}
}
}
return ret ? ret : defaultValue
}
android {
defaultConfig {
applicationId getConfigPreference("PACKAGE_NAME")
ndk {
abiFilters 'armeabi', 'armeabi-v7a', 'arm64-v8a'
}
manifestPlaceholders = [
XG_ACCESS_ID : getConfigPreference("XG_ACCESS_ID"),
XG_ACCESS_KEY : getConfigPreference("XG_ACCESS_KEY"),
]
}
}
dependencies {
//
implementation 'com.tencent.tpns:tpns:1.4.0.1-release'
// TPNS [VERSION] SDK 2
implementation 'com.tencent.tpns:honor:1.4.0.1-release' //耀
implementation 'com.tencent.tpns:meizu:1.4.0.1-release' //
implementation 'com.tencent.tpns:xiaomi:1.4.0.1-release'// [VERSION] SDK Android SDK
implementation 'com.tencent.tpns:vivo:1.4.0.1-release' // vivo [VERSION] SDK , Android SDK
// OPPO SDK[VERSION] SDK Android SDK
implementation 'com.tencent.tpns:oppo:1.4.0.1-release'
// SDK 1.3.2.0 OPPO
implementation 'com.google.code.gson:gson:2.6.2'
implementation 'commons-codec:commons-codec:1.15'
}

293
www/tpns.js Normal file
View File

@ -0,0 +1,293 @@
var exec = require('cordova/exec');
var TpnsPlugin = function () { };
// private plugin function
TpnsPlugin.prototype.receiveMessage = {};
TpnsPlugin.prototype.openNotification = {};
TpnsPlugin.prototype.receiveNotification = {};
TpnsPlugin.prototype.isPlatformIOS = function () {
return (
device.platform === "iPhone" ||
device.platform === "iPad" ||
device.platform === "iPod touch" ||
device.platform === "iOS"
);
};
TpnsPlugin.prototype.errorCallback = function (msg) {
console.log("JPush Callback Error: " + msg);
};
TpnsPlugin.prototype.fireEvent = function(event,extra) {
cordova.fireDocumentEvent("tpns."+event, extra);
};
TpnsPlugin.prototype.Constant = {
EVENT_ON_TEXT_MESSAGE :'tpns.onTextMessage',
EVENT_ON_NOTIFICATION_SHOWED_RESULT :'tpns.onNotificationShowedResult',
EVENT_ON_NOTIFICATION_CLICKED_RESULT :'tpns.onNotificationClickedResult',
};
TpnsPlugin.prototype.callNative = function (
name,
args,
successCallback,
errorCallback
) {
if (this.isPlatformIOS()) {
console.log("tnps android plugin skip ios platform.");
if (successCallback) {
successCallback();
}
return;
}
if (errorCallback) {
cordova.exec(successCallback, errorCallback, "TpnsPlugin", name, args);
} else {
cordova.exec(
successCallback,
this.errorCallback,
"JPushPlugin",
name,
args
);
}
};
/**
* 启用调试
*/
TpnsPlugin.prototype.enableDebug = function(enable) {
this.callNative("enableDebug", [enable], null);
};
/**
* 关闭联合保活能力1.1.6.1+
* */
TpnsPlugin.prototype.enablePullUpOtherApp = function(enable) {
this.callNative("enablePullUpOtherApp", [enable], null);
};
/**
* 获取设备 Token
*/
TpnsPlugin.prototype.getToken = function(successCallback,errorCallback){
this.callNative("getToken", [], successCallback,errorCallback);
};
/**
* 获取第三方厂商 Token
*/
TpnsPlugin.prototype.getOtherPushToken = function(successCallback,errorCallback){
this.callNative("getOtherPushToken", [], successCallback,errorCallback);
};
/**
* 注册消息推送
* @param {*} other 厂商通道? 为空时不开启 格式如下:
* {
* "MZ":{"APP_ID":魅族APP_ID,"APP_KEY":魅族APP_KEY},
* "OPPO":{"appKey":OPPO appKey,"appSecret": OPPO appSecret},
* "MI":{"APPID":小米APPID,"APPKEY":小米APPKEY},
* "HW":{},"RY":{}
* }
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.registerPush = function(other,successCallback,errorCallback){
this.callNative("registerPush", other?[other]:[],successCallback,errorCallback);
}
/**
* 取消注册消息推送
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.unregisterPush = function(successCallback,errorCallback){
this.callNative("unregisterPush", [],successCallback,errorCallback);
}
/**
* 添加本地消息通知
* @param {*} data 消息通知内容
* {
* channelId:通道id,channelName:通道名称,enableVibration:是否震动,enableLights:是否闪光,enableSound:是否铃声,soundUri:铃声文件地址
* }
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.createNotificationChannel =function(data,successCallback,errorCallback){
this.callNative("createNotificationChannel", [data],successCallback,errorCallback);
}
/**
* 创建消息通道
* @param {*} data 消息通道信息
* {
* type?: 本地消息类型1:通知2:消息,
* title: 消息标题,
* content: 消息内容,
* date?: 消息日期格式为20140502,
* hour?: 消息触发的小时(24小时制)例如22代表晚上10点,
* min? :消息触发的分钟例如05代表05分,
* builderId?: 消息样式默认为0或不设置,
* actionType: 设置动作类型1打开activity或App本身2打开浏览器3打开Intent 4通过包名打开应用,
* activity?:拉起应用页面,
* url?: URL,
* intent?: intent
* styleId?: 是否覆盖原先build_id的保存设置1覆盖0不覆盖,
* ringRaw?: 音频资源
* data?: {} 自定义内容列表
* }
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.addLocalNotification =function(data,successCallback,errorCallback){
this.callNative("addLocalNotification", [data],successCallback,errorCallback);
}
/**
* 清除本地消息通知
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.clearLocalNotifications = function(successCallback,errorCallback){
this.callNative("clearLocalNotifications", [],successCallback,errorCallback);
}
/**
* 对一个或多个账号类型的账号进行解绑SDK 1.2.3.0+
* @param {*} params 账户类型数组 [1001,1002]
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.delAccounts = function(params,successCallback,errorCallback){
this.callNative("delAccounts", [params],successCallback,errorCallback);
}
/**
* 对的所有已绑定账号进行解绑
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.clearAccounts = function(successCallback,errorCallback){
this.callNative("clearAccounts", [],successCallback,errorCallback);
}
/**
* 添加或更新账号若原来没有该类型账号则添加若原来有则覆盖可以同时添加多个账号一个账号对应一个账号类型
* @param {*} params 账户数组[{"account":elva, "accountType":1001}, {"account":jay, "accountType":1002}]
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.upsertAccounts = function(params,successCallback,errorCallback){
this.callNative("upsertAccounts", [params],successCallback,errorCallback);
}
/**
* 覆盖多个标签 一次设置多个标签会覆盖这个设备之前设置的标签
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} tags 标签数组["tag1","tag2"]
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.clearAndAppendTags = function(operateName,tags,successCallback,errorCallback){
this.callNative("clearAndAppendTags", [operateName,tags],successCallback,errorCallback);
}
/**
* 新增多个标签
* 如果新覆盖的标签都带有 : 例如 test:2, level:2则会删除这个设备已绑定的所有 test:* level:* 标签再新增 test:2 level:2
* 如果新增的标签有部分不带 : 例如 test:2 level则会删除这个设备的全部历史标签再新增 test:2 level 标签
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} tags 标签数组["tag1","tag2"]
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.appendTags = function(operateName,tags,successCallback,errorCallback){
this.callNative("appendTags", [operateName,tags],successCallback,errorCallback);
}
/**
* 一次删除多个标签
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} tags 标签数组["tag1","tag2"]
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.delTags = function(operateName,tags,successCallback,errorCallback){
this.callNative("delTags", [operateName,tags],successCallback,errorCallback);
}
/**
* 清除这个设备的所有标签
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.clearTags = function(operateName,successCallback,errorCallback){
this.callNative("clearTags", [operateName],successCallback,errorCallback);
}
/**
* 获取这个设备的标签
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} offset 开始位置
* @param {*} limit 取值数量 最大100
* @param {*} successCallback 返回标签数组字符串
* @param {*} errorCallback
*/
TpnsPlugin.prototype.queryTags = function(operateName,offset,limit,successCallback,errorCallback){
this.callNative("queryTags", [operateName,offset,limit],successCallback,errorCallback);
}
/**
* 添加属性带回调有则覆盖无则添加
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} attrs 属性对象 {"属性名1":"属性值1","属性名2":"属性值2"}
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.upsertAttributes = function(operateName,attrs,successCallback,errorCallback){
this.callNative("upsertAttributes", [operateName,attrs],successCallback,errorCallback);
}
/**
* 更新用户属性
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} attrs 属性对象 {"属性名1":"属性值1","属性名2":"属性值2"}
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.clearAndAppendAttributes = function(operateName,attrs,successCallback,errorCallback){
this.callNative("clearAndAppendAttributes", [operateName,attrs],successCallback,errorCallback);
}
/**
* 删除指定的属性
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} attrs 属性名数组 ["属性名1","属性名2"]
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.delAttributes = function(operateName,attrs,successCallback,errorCallback){
this.callNative("delAttributes", [operateName,attrs],successCallback,errorCallback);
}
/**
* 删除已设置的所有属性
* @param {*} operateName 操作名称 全局唯一,类似于全局序列
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.clearAttributes = function(operateName,successCallback,errorCallback){
this.callNative("clearAttributes", [operateName],successCallback,errorCallback);
}
/**
* 取消全部消息通知
* @param {*} successCallback
* @param {*} errorCallback
*/
TpnsPlugin.prototype.cancelAllNotifaction = function(successCallback,errorCallback){
this.callNative("cancelAllNotifaction", [],successCallback,errorCallback);
}
module.exports = new TpnsPlugin();