@onekeyfe/react-native-jpush 6.7.0-alpha.435 → 6.7.0-alpha.444
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +34 -1
- package/android/build.gradle +1 -0
- package/android/fcm/build.gradle +36 -0
- package/android/fcm/consumer-rules.pro +2 -0
- package/android/fcm/src/main/AndroidManifest.xml +25 -0
- package/android/fcm/src/main/java/com/onekey/jpush/fcm/FcmInitProvider.java +25 -0
- package/android/fcm/src/main/java/com/onekey/jpush/fcm/FcmMessagingService.java +84 -0
- package/android/fcm/src/main/java/com/onekey/jpush/fcm/FcmPushManager.java +69 -0
- package/android/fcm/src/test/java/com/onekey/jpush/fcm/FcmAdapterTest.java +684 -0
- package/android/fcm/src/test/java/com/onekey/jpush/fcm/FcmManifestTest.java +54 -0
- package/android/src/main/java/cn/jiguang/api/utils/JCollectionAuth.java +6 -1
- package/android/src/main/java/cn/jiguang/core/JCoreTcpEngine.java +1 -0
- package/android/src/main/java/cn/jpush/android/api/JPushInterface.java +2 -0
- package/android/src/main/java/cn/jpush/android/api/JThirdPlatFormInterface.java +107 -7
- package/android/src/main/java/cn/jpush/android/local/ActionHelper.java +95 -0
- package/android/src/main/java/cn/jpush/android/service/JPushMessageReceiver.java +2 -1
- package/android/src/test/java/com/margelo/nitro/reactnativejpush/JPushCloudHandshakeTest.java +110 -0
- package/android/src/test/java/com/margelo/nitro/reactnativejpush/JPushHandshakeFailureTest.java +73 -0
- package/android/src/test/java/com/margelo/nitro/reactnativejpush/ReactNativeJpushProtocolTest.java +0 -108
- package/package.json +3 -2
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
package com.onekey.jpush.fcm;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.*;
|
|
4
|
+
|
|
5
|
+
import android.content.Context;
|
|
6
|
+
import android.content.pm.PackageInfo;
|
|
7
|
+
import android.content.pm.PackageManager;
|
|
8
|
+
import android.content.pm.ProviderInfo;
|
|
9
|
+
import android.content.pm.ServiceInfo;
|
|
10
|
+
import android.content.Intent;
|
|
11
|
+
import org.junit.Test;
|
|
12
|
+
import org.junit.runner.RunWith;
|
|
13
|
+
import org.robolectric.RobolectricTestRunner;
|
|
14
|
+
import org.robolectric.RuntimeEnvironment;
|
|
15
|
+
import org.robolectric.annotation.Config;
|
|
16
|
+
|
|
17
|
+
@RunWith(RobolectricTestRunner.class)
|
|
18
|
+
@Config(sdk = 34)
|
|
19
|
+
public class FcmManifestTest {
|
|
20
|
+
@Test
|
|
21
|
+
public void mergedManifestRoutesOnlyToGuardedServiceAndDisablesDelegation() throws Exception {
|
|
22
|
+
Context context = RuntimeEnvironment.getApplication();
|
|
23
|
+
PackageManager packages = context.getPackageManager();
|
|
24
|
+
PackageInfo info = packages.getPackageInfo(context.getPackageName(),
|
|
25
|
+
PackageManager.GET_META_DATA | PackageManager.GET_PROVIDERS | PackageManager.GET_SERVICES);
|
|
26
|
+
assertTrue(info.applicationInfo.metaData.containsKey("firebase_messaging_notification_delegation_enabled"));
|
|
27
|
+
assertFalse(info.applicationInfo.metaData.getBoolean("firebase_messaging_notification_delegation_enabled"));
|
|
28
|
+
assertTrue(info.applicationInfo.metaData.containsKey("firebase_messaging_auto_init_enabled"));
|
|
29
|
+
assertFalse(info.applicationInfo.metaData.getBoolean("firebase_messaging_auto_init_enabled"));
|
|
30
|
+
boolean initializerFound = false;
|
|
31
|
+
for (ProviderInfo provider : info.providers) {
|
|
32
|
+
if (FcmInitProvider.class.getName().equals(provider.name)) {
|
|
33
|
+
initializerFound = true;
|
|
34
|
+
assertFalse(provider.exported);
|
|
35
|
+
}
|
|
36
|
+
}
|
|
37
|
+
assertTrue("The startup delegate cleanup must be installed", initializerFound);
|
|
38
|
+
boolean guardedServiceFound = false;
|
|
39
|
+
for (ServiceInfo service : info.services) {
|
|
40
|
+
assertNotEquals("Unguarded Firebase fallback must not be installed",
|
|
41
|
+
"com.google.firebase.messaging.FirebaseMessagingService", service.name);
|
|
42
|
+
if (FcmMessagingService.class.getName().equals(service.name)) {
|
|
43
|
+
guardedServiceFound = true;
|
|
44
|
+
assertFalse(service.exported);
|
|
45
|
+
assertFalse(service.directBootAware);
|
|
46
|
+
}
|
|
47
|
+
}
|
|
48
|
+
assertTrue("The guarded receive service must be installed", guardedServiceFound);
|
|
49
|
+
android.content.pm.ResolveInfo handler = packages.resolveService(
|
|
50
|
+
new Intent("com.google.firebase.MESSAGING_EVENT").setPackage(context.getPackageName()), 0);
|
|
51
|
+
assertNotNull(handler);
|
|
52
|
+
assertEquals(FcmMessagingService.class.getName(), handler.serviceInfo.name);
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -2,10 +2,15 @@ package cn.jiguang.api.utils;
|
|
|
2
2
|
|
|
3
3
|
import android.content.Context;
|
|
4
4
|
import cn.jiguang.core.JCoreStorage;
|
|
5
|
+
import cn.jpush.android.api.JThirdPlatFormInterface;
|
|
5
6
|
|
|
6
7
|
public class JCollectionAuth {
|
|
7
|
-
public static void setAuth(Context context, boolean auth) {
|
|
8
|
+
public static synchronized void setAuth(Context context, boolean auth) {
|
|
9
|
+
boolean wasAuthorized = JCoreStorage.isCollectionAuth(context);
|
|
8
10
|
JCoreStorage.setCollectionAuth(context, auth);
|
|
11
|
+
if (auth && !wasAuthorized) {
|
|
12
|
+
JThirdPlatFormInterface.initializeFcm(context);
|
|
13
|
+
}
|
|
9
14
|
}
|
|
10
15
|
|
|
11
16
|
public static boolean isAuth(Context context) {
|
|
@@ -1323,6 +1323,7 @@ public final class JCoreTcpEngine {
|
|
|
1323
1323
|
String regId = JCoreStorage.getRegistrationId(context);
|
|
1324
1324
|
ActionHelper.getInstance().dispatchRegisterEvent(context, regId);
|
|
1325
1325
|
ActionHelper.getInstance().dispatchConnectedEvent(context, true);
|
|
1326
|
+
cn.jpush.android.api.JThirdPlatFormInterface.initializeFcm(context);
|
|
1326
1327
|
}
|
|
1327
1328
|
|
|
1328
1329
|
public Bundle handleEvent(Context context, String sdkType, int cmd, String action, Bundle bundle, Object... extras) {
|
|
@@ -81,6 +81,7 @@ public class JPushInterface {
|
|
|
81
81
|
JPushConstants.init(app);
|
|
82
82
|
ActionHelper.getInstance().init(app);
|
|
83
83
|
JCoreManager.init(app);
|
|
84
|
+
JThirdPlatFormInterface.initializeFcm(app);
|
|
84
85
|
}
|
|
85
86
|
|
|
86
87
|
public static void init(Context context, JPushConfig config) {
|
|
@@ -104,6 +105,7 @@ public class JPushInterface {
|
|
|
104
105
|
public static void resumePush(Context context) {
|
|
105
106
|
JCoreStorage.setPushStopped(context, false);
|
|
106
107
|
JCoreManager.init(context);
|
|
108
|
+
JThirdPlatFormInterface.initializeFcm(context);
|
|
107
109
|
ActionHelper.getInstance().setPushStatusWithCallBack(context, 4, 1);
|
|
108
110
|
}
|
|
109
111
|
|
|
@@ -4,11 +4,21 @@ import android.app.Notification;
|
|
|
4
4
|
import android.content.Context;
|
|
5
5
|
import android.os.Bundle;
|
|
6
6
|
import cn.jiguang.core.JCoreCrypto;
|
|
7
|
+
import cn.jiguang.core.JCoreStorage;
|
|
8
|
+
import cn.jiguang.core.JCoreTcpEngine;
|
|
9
|
+
import cn.jiguang.plugins.push.common.JLogger;
|
|
7
10
|
import cn.jpush.android.helper.JCoreHelper;
|
|
8
11
|
import cn.jpush.android.local.ActionHelper;
|
|
12
|
+
import java.io.ByteArrayInputStream;
|
|
13
|
+
import java.io.ByteArrayOutputStream;
|
|
14
|
+
import java.nio.charset.StandardCharsets;
|
|
15
|
+
import java.util.zip.GZIPInputStream;
|
|
9
16
|
import org.json.JSONObject;
|
|
10
17
|
|
|
11
18
|
public abstract class JThirdPlatFormInterface {
|
|
19
|
+
private static JThirdPlatFormInterface fcmPlugin;
|
|
20
|
+
private static boolean fcmRegistered;
|
|
21
|
+
private static final int MAX_MESSAGE_BYTES = 65536;
|
|
12
22
|
public static final String ACTION_NOTIFICATION_SHOW = "action_notification_show";
|
|
13
23
|
public static final String ACTION_NOTIFICATION_ARRIVED = "action_notification_arrived";
|
|
14
24
|
public static final String ACTION_NOTIFICATION_UN_SHOW = "action_notification_unshow";
|
|
@@ -69,6 +79,44 @@ public abstract class JThirdPlatFormInterface {
|
|
|
69
79
|
return false;
|
|
70
80
|
}
|
|
71
81
|
|
|
82
|
+
public static void initializeFcm(final Context context) {
|
|
83
|
+
if (context == null || JCoreStorage.isPushStopped(context) || !JCoreStorage.isCollectionAuth(context)) {
|
|
84
|
+
return;
|
|
85
|
+
}
|
|
86
|
+
JCoreTcpEngine.getInstance().executeAsync(new Runnable() {
|
|
87
|
+
@Override
|
|
88
|
+
public void run() {
|
|
89
|
+
synchronized (JThirdPlatFormInterface.class) {
|
|
90
|
+
if (JCoreStorage.isPushStopped(context) || !JCoreStorage.isCollectionAuth(context)) {
|
|
91
|
+
return;
|
|
92
|
+
}
|
|
93
|
+
try {
|
|
94
|
+
if (fcmPlugin == null) {
|
|
95
|
+
// This optional source module is linked only by Google hosts.
|
|
96
|
+
fcmPlugin = (JThirdPlatFormInterface) Class.forName(
|
|
97
|
+
"com.onekey.jpush.fcm.FcmPushManager"
|
|
98
|
+
).getDeclaredConstructor().newInstance();
|
|
99
|
+
}
|
|
100
|
+
if (!fcmPlugin.isSupport(context)) {
|
|
101
|
+
return;
|
|
102
|
+
}
|
|
103
|
+
if (!fcmRegistered) {
|
|
104
|
+
fcmPlugin.init(context);
|
|
105
|
+
fcmPlugin.register(context, new Bundle());
|
|
106
|
+
fcmRegistered = true;
|
|
107
|
+
}
|
|
108
|
+
fcmPlugin.getToken(context);
|
|
109
|
+
JLogger.i("FCM registration requested");
|
|
110
|
+
} catch (ClassNotFoundException absentPlugin) {
|
|
111
|
+
// Non-Google hosts intentionally do not include the optional plugin.
|
|
112
|
+
} catch (Exception | LinkageError unavailablePlugin) {
|
|
113
|
+
JLogger.w("FCM registration unavailable");
|
|
114
|
+
}
|
|
115
|
+
}
|
|
116
|
+
}
|
|
117
|
+
});
|
|
118
|
+
}
|
|
119
|
+
|
|
72
120
|
public static void onEvent(Thread thread, Throwable error) {
|
|
73
121
|
ActionHelper.getInstance().onEvent(thread, error);
|
|
74
122
|
}
|
|
@@ -84,6 +132,10 @@ public abstract class JThirdPlatFormInterface {
|
|
|
84
132
|
}
|
|
85
133
|
|
|
86
134
|
public static void sendActionByJCore(Context context, Bundle bundle, String action) {
|
|
135
|
+
if (ACTION_PLUGIN_PALTFORM_ON_MESSAGING.equals(action)) {
|
|
136
|
+
ActionHelper.getInstance().doAction(context, action, bundle);
|
|
137
|
+
return;
|
|
138
|
+
}
|
|
87
139
|
JCoreHelper.runActionWithService(context, "JPUSH", action, bundle);
|
|
88
140
|
}
|
|
89
141
|
|
|
@@ -132,16 +184,64 @@ public abstract class JThirdPlatFormInterface {
|
|
|
132
184
|
public static NotificationMessage parseMessage(Context context, String rawJson) {
|
|
133
185
|
NotificationMessage message = new NotificationMessage();
|
|
134
186
|
message.context = context;
|
|
135
|
-
|
|
187
|
+
message.platform = 8;
|
|
188
|
+
message.displayForeground = "0";
|
|
189
|
+
String decoded = decodeMessageJson(rawJson);
|
|
190
|
+
if (decoded != null) {
|
|
136
191
|
try {
|
|
137
|
-
JSONObject json = new JSONObject(
|
|
138
|
-
message.msgId = json.optString("
|
|
139
|
-
message.
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
192
|
+
JSONObject json = new JSONObject(decoded);
|
|
193
|
+
message.msgId = json.optString("_jmsgid_", json.optString("_j_msgid", ""));
|
|
194
|
+
if (message.msgId.isEmpty()) {
|
|
195
|
+
message.msgId = json.optString("msg_id", "");
|
|
196
|
+
}
|
|
197
|
+
String overrideId = json.optString("override_msg_id", "");
|
|
198
|
+
if (!overrideId.isEmpty()) {
|
|
199
|
+
message.msgId = overrideId;
|
|
200
|
+
}
|
|
201
|
+
message.notificationId = getNofiticationID(message.msgId, 0);
|
|
202
|
+
message.notificationTitle = json.optString("n_title", json.optString("title", ""));
|
|
203
|
+
message.notificationContent = json.optString("n_content", json.optString("alert", json.optString("content", "")));
|
|
204
|
+
Object extras = json.opt("n_extras");
|
|
205
|
+
if (extras == null) {
|
|
206
|
+
extras = json.opt("extras");
|
|
207
|
+
}
|
|
208
|
+
message.notificationExtras = extras != null ? extras.toString() : "";
|
|
209
|
+
message.notificationChannelId = json.optString("n_channel_id", "");
|
|
210
|
+
if (!JCoreStorage.isPushStopped(context) && JCoreStorage.isCollectionAuth(context)) {
|
|
211
|
+
message.displayForeground = json.optString("n_foreground", "1");
|
|
212
|
+
}
|
|
213
|
+
} catch (Exception invalidMessage) {
|
|
214
|
+
JLogger.w("FCM payload rejected");
|
|
143
215
|
}
|
|
144
216
|
}
|
|
145
217
|
return message;
|
|
146
218
|
}
|
|
219
|
+
|
|
220
|
+
public static String decodeMessageJson(String rawJson) {
|
|
221
|
+
if (rawJson == null || rawJson.length() > MAX_MESSAGE_BYTES
|
|
222
|
+
|| rawJson.getBytes(StandardCharsets.UTF_8).length > MAX_MESSAGE_BYTES) {
|
|
223
|
+
return null;
|
|
224
|
+
}
|
|
225
|
+
try {
|
|
226
|
+
JSONObject json = new JSONObject(rawJson);
|
|
227
|
+
if (!json.has("jg_c")) {
|
|
228
|
+
return rawJson;
|
|
229
|
+
}
|
|
230
|
+
byte[] compressed = JCoreCrypto.base64Decode(json.getString("jg_c"));
|
|
231
|
+
try (GZIPInputStream input = new GZIPInputStream(new ByteArrayInputStream(compressed));
|
|
232
|
+
ByteArrayOutputStream output = new ByteArrayOutputStream()) {
|
|
233
|
+
byte[] buffer = new byte[2048];
|
|
234
|
+
int count;
|
|
235
|
+
while ((count = input.read(buffer)) != -1) {
|
|
236
|
+
if (output.size() + count > MAX_MESSAGE_BYTES) {
|
|
237
|
+
return null;
|
|
238
|
+
}
|
|
239
|
+
output.write(buffer, 0, count);
|
|
240
|
+
}
|
|
241
|
+
return new String(output.toByteArray(), StandardCharsets.UTF_8);
|
|
242
|
+
}
|
|
243
|
+
} catch (Exception invalidMessage) {
|
|
244
|
+
return null;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
147
247
|
}
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package cn.jpush.android.local;
|
|
2
2
|
|
|
3
3
|
import android.app.Activity;
|
|
4
|
+
import android.app.ActivityManager;
|
|
5
|
+
import android.app.KeyguardManager;
|
|
4
6
|
import android.app.Notification;
|
|
5
7
|
import android.app.NotificationChannel;
|
|
6
8
|
import android.app.NotificationManager;
|
|
@@ -16,6 +18,7 @@ import cn.jiguang.core.JCoreWireCodec;
|
|
|
16
18
|
import cn.jpush.android.api.CmdMessage;
|
|
17
19
|
import cn.jpush.android.api.CustomMessage;
|
|
18
20
|
import cn.jpush.android.api.JPushInterface;
|
|
21
|
+
import cn.jpush.android.api.JThirdPlatFormInterface;
|
|
19
22
|
import cn.jpush.android.api.JPushMessage;
|
|
20
23
|
import cn.jpush.android.api.NotificationCustomButton;
|
|
21
24
|
import cn.jpush.android.api.NotificationMessage;
|
|
@@ -111,6 +114,74 @@ public class ActionHelper {
|
|
|
111
114
|
}
|
|
112
115
|
|
|
113
116
|
public void doAction(Context context, String action, Object data) {
|
|
117
|
+
if (!(data instanceof Bundle) || JCoreStorage.isPushStopped(context) || !JCoreStorage.isCollectionAuth(context)) {
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
Bundle bundle = (Bundle) data;
|
|
121
|
+
if ("third_action".equals(action)) {
|
|
122
|
+
action = bundle.getString("third_key_action", "");
|
|
123
|
+
}
|
|
124
|
+
if (JThirdPlatFormInterface.ACTION_REGISTER_TOKEN.equals(action)) {
|
|
125
|
+
String token = bundle.getString("token", "");
|
|
126
|
+
byte platform = bundle.getByte("platform", (byte) 8);
|
|
127
|
+
if (platform == 8 && !token.isEmpty()) {
|
|
128
|
+
setThirdTokenWithCallBack(context, token, platform, false);
|
|
129
|
+
}
|
|
130
|
+
return;
|
|
131
|
+
}
|
|
132
|
+
if (JThirdPlatFormInterface.ACTION_SEND_EXCEPTION.equals(action)) {
|
|
133
|
+
cn.jiguang.plugins.push.common.JLogger.w("FCM plugin reported an error");
|
|
134
|
+
return;
|
|
135
|
+
}
|
|
136
|
+
String raw = bundle.getString("data", bundle.getString("JMessageExtra", ""));
|
|
137
|
+
String decoded = JThirdPlatFormInterface.decodeMessageJson(raw);
|
|
138
|
+
if (decoded == null) {
|
|
139
|
+
return;
|
|
140
|
+
}
|
|
141
|
+
NotificationMessage message = JThirdPlatFormInterface.parseMessage(context, decoded);
|
|
142
|
+
if (message.msgId == null || message.msgId.isEmpty()) {
|
|
143
|
+
return;
|
|
144
|
+
}
|
|
145
|
+
message.notificationId = bundle.getInt("noti_id", message.notificationId);
|
|
146
|
+
if (JThirdPlatFormInterface.ACTION_PLUGIN_PALTFORM_ON_MESSAGING.equals(action)) {
|
|
147
|
+
try {
|
|
148
|
+
JSONObject json = new JSONObject(decoded);
|
|
149
|
+
if (json.has("message") && message.notificationContent.isEmpty()) {
|
|
150
|
+
CustomMessage custom = new CustomMessage();
|
|
151
|
+
custom.messageId = message.msgId;
|
|
152
|
+
custom.message = json.optString("message", "");
|
|
153
|
+
custom.title = message.notificationTitle;
|
|
154
|
+
custom.extra = message.notificationExtras;
|
|
155
|
+
custom.contentType = json.optString("content_type", "");
|
|
156
|
+
custom.platform = 8;
|
|
157
|
+
dispatchCustomMessageEvent(context, custom);
|
|
158
|
+
} else {
|
|
159
|
+
if ("0".equals(message.displayForeground) && isApplicationForeground(context)) {
|
|
160
|
+
return;
|
|
161
|
+
}
|
|
162
|
+
postSystemNotification(context, message);
|
|
163
|
+
dispatchNotificationEvent(context, "notify_arrived", message);
|
|
164
|
+
}
|
|
165
|
+
} catch (Exception invalidMessage) {
|
|
166
|
+
cn.jiguang.plugins.push.common.JLogger.w("FCM payload rejected");
|
|
167
|
+
}
|
|
168
|
+
} else if (JThirdPlatFormInterface.ACTION_NOTIFICATION_ARRIVED.equals(action)) {
|
|
169
|
+
recordNotificationPosted(context, message.notificationId);
|
|
170
|
+
dispatchNotificationEvent(context, "notify_arrived", message);
|
|
171
|
+
} else if (JThirdPlatFormInterface.ACTION_NOTIFICATION_CLCKED.equals(action)) {
|
|
172
|
+
dispatchNotificationEvent(context, "notify_opened", message);
|
|
173
|
+
broadcastNotificationOpened(context, message);
|
|
174
|
+
}
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
private boolean isApplicationForeground(Context context) {
|
|
178
|
+
KeyguardManager keyguard = (KeyguardManager) context.getSystemService(Context.KEYGUARD_SERVICE);
|
|
179
|
+
if (keyguard != null && keyguard.isKeyguardLocked()) {
|
|
180
|
+
return false;
|
|
181
|
+
}
|
|
182
|
+
ActivityManager.RunningAppProcessInfo process = new ActivityManager.RunningAppProcessInfo();
|
|
183
|
+
ActivityManager.getMyMemoryState(process);
|
|
184
|
+
return process.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND;
|
|
114
185
|
}
|
|
115
186
|
|
|
116
187
|
public void doSingleAction(Context context, String action, Object data) {
|
|
@@ -148,10 +219,33 @@ public class ActionHelper {
|
|
|
148
219
|
return;
|
|
149
220
|
}
|
|
150
221
|
Serializable msg = intent.getSerializableExtra("multi_notification_msg");
|
|
222
|
+
boolean fcmClick = !(msg instanceof NotificationMessage) && intent.hasExtra("JMessageExtra");
|
|
223
|
+
if (fcmClick) {
|
|
224
|
+
if (JCoreStorage.isPushStopped(context) || !JCoreStorage.isCollectionAuth(context)) {
|
|
225
|
+
return;
|
|
226
|
+
}
|
|
227
|
+
NotificationMessage message = JThirdPlatFormInterface.parseMessage(context, intent.getStringExtra("JMessageExtra"));
|
|
228
|
+
if (message.msgId == null || message.msgId.isEmpty()) {
|
|
229
|
+
return;
|
|
230
|
+
}
|
|
231
|
+
msg = message;
|
|
232
|
+
}
|
|
151
233
|
if (msg instanceof NotificationMessage) {
|
|
152
234
|
NotificationMessage notificationMessage = (NotificationMessage) msg;
|
|
235
|
+
if (notificationMessage.platform == 8
|
|
236
|
+
&& (JCoreStorage.isPushStopped(context) || !JCoreStorage.isCollectionAuth(context))) {
|
|
237
|
+
return;
|
|
238
|
+
}
|
|
153
239
|
dispatchNotificationEvent(context, "notify_opened", notificationMessage);
|
|
154
240
|
broadcastNotificationOpened(context, notificationMessage);
|
|
241
|
+
if (fcmClick || notificationMessage.platform == 8) {
|
|
242
|
+
android.content.pm.PackageManager manager = context.getPackageManager();
|
|
243
|
+
Intent launcher = manager != null ? manager.getLaunchIntentForPackage(appPkg) : null;
|
|
244
|
+
if (launcher != null) {
|
|
245
|
+
launcher.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
|
|
246
|
+
context.startActivity(launcher);
|
|
247
|
+
}
|
|
248
|
+
}
|
|
155
249
|
}
|
|
156
250
|
} catch (Throwable ignored) {
|
|
157
251
|
}
|
|
@@ -897,6 +991,7 @@ public class ActionHelper {
|
|
|
897
991
|
if (statusCode == 0) {
|
|
898
992
|
JCoreStorage.saveThirdToken(context, platform, unbind ? "" : token);
|
|
899
993
|
}
|
|
994
|
+
cn.jiguang.plugins.push.common.JLogger.i("Third token result platform=" + platform + " code=" + statusCode);
|
|
900
995
|
Intent intent = buildBaseReceiverIntent(context, "cmd_result", 0, statusCode);
|
|
901
996
|
intent.putExtra("cmd", 10000);
|
|
902
997
|
intent.putExtra("msg", unbind ? "unbind" : "bind");
|
|
@@ -10,6 +10,7 @@ import cn.jpush.android.api.JPushMessage;
|
|
|
10
10
|
import cn.jpush.android.api.NotificationCustomButton;
|
|
11
11
|
import cn.jpush.android.api.NotificationMessage;
|
|
12
12
|
import cn.jpush.android.local.ActionHelper;
|
|
13
|
+
import cn.jiguang.core.JCoreStorage;
|
|
13
14
|
|
|
14
15
|
public abstract class JPushMessageReceiver extends BroadcastReceiver {
|
|
15
16
|
@Override
|
|
@@ -74,7 +75,7 @@ public abstract class JPushMessageReceiver extends BroadcastReceiver {
|
|
|
74
75
|
}
|
|
75
76
|
|
|
76
77
|
public boolean isNeedShowNotification(Context context, NotificationMessage notificationMessage, String processName) {
|
|
77
|
-
return
|
|
78
|
+
return !JCoreStorage.isPushStopped(context) && JCoreStorage.isCollectionAuth(context);
|
|
78
79
|
}
|
|
79
80
|
|
|
80
81
|
public void onInAppMessageShow(Context context, NotificationMessage notificationMessage) {
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
package com.margelo.nitro.reactnativejpush;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.*;
|
|
4
|
+
import cn.jiguang.core.JCoreCrypto;
|
|
5
|
+
import cn.jiguang.core.JCoreWireCodec;
|
|
6
|
+
import java.io.InputStream;
|
|
7
|
+
import java.io.OutputStream;
|
|
8
|
+
import java.net.DatagramPacket;
|
|
9
|
+
import java.net.DatagramSocket;
|
|
10
|
+
import java.net.InetAddress;
|
|
11
|
+
import java.net.InetSocketAddress;
|
|
12
|
+
import java.net.Socket;
|
|
13
|
+
import java.util.Arrays;
|
|
14
|
+
import java.util.Collections;
|
|
15
|
+
import java.util.Set;
|
|
16
|
+
import org.junit.Assume;
|
|
17
|
+
import org.junit.Test;
|
|
18
|
+
|
|
19
|
+
public class JPushCloudHandshakeTest {
|
|
20
|
+
@Test
|
|
21
|
+
public void liveCloudHandshake() throws Exception {
|
|
22
|
+
boolean enabled = "1".equals(System.getenv("JPUSH_LIVE_TESTS"));
|
|
23
|
+
if (!enabled) {
|
|
24
|
+
System.out.println("SKIPPED live Jiguang handshake: set JPUSH_LIVE_TESTS=1 to enable");
|
|
25
|
+
}
|
|
26
|
+
Assume.assumeTrue("External cloud handshake requires JPUSH_LIVE_TESTS=1", enabled);
|
|
27
|
+
String sisJson;
|
|
28
|
+
try (DatagramSocket udp = new DatagramSocket()) {
|
|
29
|
+
String request = JCoreWireCodec.buildSisRequestJson(
|
|
30
|
+
1, ReactNativeJpushProtocolTest.DEMO_TEST_APP_KEY, 0L, "",
|
|
31
|
+
Collections.<String>emptyList(), 1
|
|
32
|
+
);
|
|
33
|
+
byte[] packet = JCoreWireCodec.encodeUdpSisPacket(request, JCoreCrypto.nextPositiveSeed24());
|
|
34
|
+
udp.setSoTimeout(2500);
|
|
35
|
+
udp.send(new DatagramPacket(packet, packet.length, InetAddress.getByName("s.jpush.cn"), 19000));
|
|
36
|
+
DatagramPacket response = new DatagramPacket(new byte[4096], 4096);
|
|
37
|
+
udp.receive(response);
|
|
38
|
+
sisJson = JCoreWireCodec.decodeUdpSisPacket(Arrays.copyOf(response.getData(), response.getLength()));
|
|
39
|
+
}
|
|
40
|
+
assertTrue("SIS response must contain endpoints", sisJson.contains("\"ips\""));
|
|
41
|
+
Set<String> endpoints = JCoreWireCodec.extractJsonStringArray(sisJson, "ips");
|
|
42
|
+
assertFalse("SIS endpoints must not be empty", endpoints.isEmpty());
|
|
43
|
+
String endpoint = endpoints.iterator().next();
|
|
44
|
+
int colon = endpoint.lastIndexOf(':');
|
|
45
|
+
try (Socket tcp = new Socket()) {
|
|
46
|
+
tcp.connect(new InetSocketAddress(endpoint.substring(0, colon), Integer.parseInt(endpoint.substring(colon + 1))), 3000);
|
|
47
|
+
tcp.setSoTimeout(5000);
|
|
48
|
+
performHandshake(tcp.getInputStream(), tcp.getOutputStream());
|
|
49
|
+
}
|
|
50
|
+
System.out.println("Live Jiguang register/login handshake passed");
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
// Shared by the opt-in cloud test and deterministic failure-propagation regressions.
|
|
54
|
+
static void performHandshake(InputStream in, OutputStream out) throws Exception {
|
|
55
|
+
int seed = JCoreCrypto.nextRegisterSeed();
|
|
56
|
+
JCoreWireCodec.setLastRegisterSeed(seed);
|
|
57
|
+
byte[] regBody = JCoreWireCodec.buildRegisterPayload(
|
|
58
|
+
ReactNativeJpushProtocolTest.DEMO_TEST_APP_KEY,
|
|
59
|
+
"developer-default",
|
|
60
|
+
ReactNativeJpushProtocolTest.DEMO_TEST_PACKAGE_NAME,
|
|
61
|
+
"msgbench_auto_001"
|
|
62
|
+
);
|
|
63
|
+
byte[] regFrame = JCoreWireCodec.encodeFrame(
|
|
64
|
+
JCoreWireCodec.CMD_REGISTER,
|
|
65
|
+
JCoreWireCodec.VER_REGISTER,
|
|
66
|
+
101L,
|
|
67
|
+
seed,
|
|
68
|
+
0L,
|
|
69
|
+
regBody
|
|
70
|
+
);
|
|
71
|
+
out.write(regFrame);
|
|
72
|
+
out.flush();
|
|
73
|
+
|
|
74
|
+
JCoreWireCodec.DecodedFrame regRespFrame = JCoreWireCodec.readFrameFromStream(in, 0L);
|
|
75
|
+
assertNotNull("Missing register response", regRespFrame);
|
|
76
|
+
assertEquals("Register command", JCoreWireCodec.CMD_REGISTER, regRespFrame.command);
|
|
77
|
+
assertEquals("Register status", 0, regRespFrame.statusCode);
|
|
78
|
+
JCoreWireCodec.RegisterResponse regResp = JCoreWireCodec.parseRegisterResponse(regRespFrame);
|
|
79
|
+
assertNotNull(regResp);
|
|
80
|
+
assertEquals(0L, (long) regResp.statusCode);
|
|
81
|
+
assertTrue(regResp.uid > 0L);
|
|
82
|
+
assertTrue(regResp.registrationId != null && !regResp.registrationId.isEmpty());
|
|
83
|
+
|
|
84
|
+
byte[] loginBody = JCoreWireCodec.buildLoginPayload(
|
|
85
|
+
regResp.password,
|
|
86
|
+
ReactNativeJpushProtocolTest.DEMO_TEST_APP_KEY,
|
|
87
|
+
regResp.deviceId,
|
|
88
|
+
"CN"
|
|
89
|
+
);
|
|
90
|
+
byte[] loginFrame = JCoreWireCodec.encodeFrame(
|
|
91
|
+
JCoreWireCodec.CMD_LOGIN,
|
|
92
|
+
JCoreWireCodec.VER_LOGIN,
|
|
93
|
+
102L,
|
|
94
|
+
0,
|
|
95
|
+
regResp.uid,
|
|
96
|
+
loginBody
|
|
97
|
+
);
|
|
98
|
+
out.write(loginFrame);
|
|
99
|
+
out.flush();
|
|
100
|
+
|
|
101
|
+
JCoreWireCodec.DecodedFrame loginRespFrame = JCoreWireCodec.readFrameFromStream(in, regResp.uid);
|
|
102
|
+
assertNotNull("Missing login response", loginRespFrame);
|
|
103
|
+
assertEquals("Login command", JCoreWireCodec.CMD_LOGIN, loginRespFrame.command);
|
|
104
|
+
assertEquals("Login status", 0, loginRespFrame.statusCode);
|
|
105
|
+
JCoreWireCodec.LoginResponse loginResp = JCoreWireCodec.parseLoginResponse(loginRespFrame);
|
|
106
|
+
assertNotNull(loginResp);
|
|
107
|
+
assertEquals(0L, (long) loginResp.statusCode);
|
|
108
|
+
assertTrue(loginResp.sessionId != 0);
|
|
109
|
+
}
|
|
110
|
+
}
|
package/android/src/test/java/com/margelo/nitro/reactnativejpush/JPushHandshakeFailureTest.java
ADDED
|
@@ -0,0 +1,73 @@
|
|
|
1
|
+
package com.margelo.nitro.reactnativejpush;
|
|
2
|
+
|
|
3
|
+
import static org.junit.Assert.*;
|
|
4
|
+
import cn.jiguang.core.JCoreWireCodec;
|
|
5
|
+
import java.io.ByteArrayInputStream;
|
|
6
|
+
import java.io.ByteArrayOutputStream;
|
|
7
|
+
import java.io.IOException;
|
|
8
|
+
import java.io.InputStream;
|
|
9
|
+
import java.util.function.Supplier;
|
|
10
|
+
import org.junit.Test;
|
|
11
|
+
|
|
12
|
+
public class JPushHandshakeFailureTest {
|
|
13
|
+
@Test
|
|
14
|
+
public void networkFailureIsNotConvertedToSuccess() {
|
|
15
|
+
InputStream broken = new InputStream() {
|
|
16
|
+
@Override public int read() throws IOException {
|
|
17
|
+
throw new IOException("Synthetic connection loss");
|
|
18
|
+
}
|
|
19
|
+
};
|
|
20
|
+
assertThrows(IOException.class, () -> JPushCloudHandshakeTest.performHandshake(broken, new ByteArrayOutputStream()));
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
@Test
|
|
24
|
+
public void missingResponseAssertionIsNotSwallowed() {
|
|
25
|
+
assertThrows(AssertionError.class, () -> JPushCloudHandshakeTest.performHandshake(
|
|
26
|
+
new ByteArrayInputStream(new byte[0]), new ByteArrayOutputStream()
|
|
27
|
+
));
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
@Test
|
|
31
|
+
public void rejectedRegistrationFailsTheHandshake() {
|
|
32
|
+
AssertionError failure = assertThrows(AssertionError.class, () -> JPushCloudHandshakeTest.performHandshake(
|
|
33
|
+
lazyReply(() -> JCoreWireCodec.encodeResponseFrame(
|
|
34
|
+
JCoreWireCodec.CMD_REGISTER, JCoreWireCodec.VER_REGISTER, 101L,
|
|
35
|
+
(int) JCoreWireCodec.getLastRegisterSeed(), 42L, 1009, new byte[0]
|
|
36
|
+
)), new ByteArrayOutputStream()
|
|
37
|
+
));
|
|
38
|
+
assertTrue(failure.getMessage().contains("Register status"));
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
@Test
|
|
42
|
+
public void rejectedLoginFailsTheHandshake() {
|
|
43
|
+
AssertionError failure = assertThrows(AssertionError.class, () -> JPushCloudHandshakeTest.performHandshake(
|
|
44
|
+
lazyReply(() -> {
|
|
45
|
+
byte[] registration = JCoreWireCodec.encodeResponseFrame(
|
|
46
|
+
JCoreWireCodec.CMD_REGISTER, JCoreWireCodec.VER_REGISTER, 101L,
|
|
47
|
+
(int) JCoreWireCodec.getLastRegisterSeed(), 42L, 0,
|
|
48
|
+
JCoreWireCodec.buildRegisterResponsePayload(42L, "synthetic_password", "synthetic_registration", "synthetic_device")
|
|
49
|
+
);
|
|
50
|
+
byte[] login = JCoreWireCodec.encodeResponseFrame(
|
|
51
|
+
JCoreWireCodec.CMD_LOGIN, JCoreWireCodec.VER_LOGIN, 102L, 0, 42L, 1005, new byte[0]
|
|
52
|
+
);
|
|
53
|
+
byte[] replies = new byte[registration.length + login.length];
|
|
54
|
+
System.arraycopy(registration, 0, replies, 0, registration.length);
|
|
55
|
+
System.arraycopy(login, 0, replies, registration.length, login.length);
|
|
56
|
+
return replies;
|
|
57
|
+
}), new ByteArrayOutputStream()
|
|
58
|
+
));
|
|
59
|
+
assertTrue(failure.getMessage().contains("Login status"));
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
private static InputStream lazyReply(Supplier<byte[]> response) {
|
|
63
|
+
return new InputStream() {
|
|
64
|
+
private ByteArrayInputStream input;
|
|
65
|
+
private ByteArrayInputStream input() {
|
|
66
|
+
if (input == null) input = new ByteArrayInputStream(response.get());
|
|
67
|
+
return input;
|
|
68
|
+
}
|
|
69
|
+
@Override public int read() { return input().read(); }
|
|
70
|
+
@Override public int read(byte[] bytes, int offset, int length) { return input().read(bytes, offset, length); }
|
|
71
|
+
};
|
|
72
|
+
}
|
|
73
|
+
}
|