@onekeyfe/react-native-jpush 6.7.0-23 → 6.7.0-25
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/android/fcm/src/test/java/com/onekey/jpush/fcm/FcmAdapterTest.java +212 -0
- package/android/src/main/cpp/cpp-adapter.cpp +41 -1
- package/android/src/main/java/cn/jiguang/core/JCoreCrypto.java +6 -9
- package/android/src/main/java/cn/jiguang/core/JCoreStorage.java +14 -2
- package/android/src/main/java/cn/jiguang/core/JCoreTcpEngine.java +476 -348
- package/android/src/main/java/cn/jiguang/core/JCoreWireCodec.java +1 -0
- package/android/src/main/java/cn/jiguang/plugins/core/JCoreModule.java +13 -2
- package/android/src/main/java/cn/jiguang/plugins/push/JPushModule.java +38 -2
- package/android/src/main/java/cn/jiguang/plugins/push/helper/JPushHelper.java +46 -15
- package/android/src/main/java/cn/jiguang/plugins/push/receiver/JPushModuleReceiver.java +0 -3
- package/android/src/main/java/cn/jpush/android/api/JPushInterface.java +0 -1
- package/android/src/main/java/cn/jpush/android/local/ActionHelper.java +223 -272
- package/android/src/main/java/cn/jpush/android/service/JNotifyActivity.java +1 -1
- package/android/src/main/java/com/margelo/nitro/reactnativejpush/ReactNativeJpush.kt +51 -16
- package/android/src/test/java/com/margelo/nitro/reactnativejpush/ReactNativeJpushProtocolTest.java +76 -32
- package/ios/bridge/RCTJPushModule.m +215 -150
- package/ios/jcore/JCOREConfiguration.h +5 -0
- package/ios/jcore/JCOREConfiguration.m +44 -4
- package/ios/jcore/JCORECrypto.m +10 -12
- package/ios/jcore/JCORETcpSession.m +197 -45
- package/ios/jcore/JCOREWireProtocol.m +20 -7
- package/ios/jpush/JPUSHNotificationManager.m +7 -1
- package/ios/jpush/JPUSHService.m +7 -9
- package/package.json +2 -2
|
@@ -22,7 +22,7 @@ public class JNotifyActivity extends Activity {
|
|
|
22
22
|
|
|
23
23
|
private void handleIntent(Intent intent) {
|
|
24
24
|
if (intent != null) {
|
|
25
|
-
ActionHelper.getInstance().handleNotificationIntent(
|
|
25
|
+
ActionHelper.getInstance().handleNotificationIntent(this, intent);
|
|
26
26
|
}
|
|
27
27
|
}
|
|
28
28
|
}
|
|
@@ -5,6 +5,8 @@ import android.app.NotificationManager
|
|
|
5
5
|
import android.content.Context
|
|
6
6
|
import android.net.Uri
|
|
7
7
|
import android.os.Build
|
|
8
|
+
import androidx.annotation.Keep
|
|
9
|
+
import com.facebook.jni.HybridData
|
|
8
10
|
import com.facebook.proguard.annotations.DoNotStrip
|
|
9
11
|
import com.facebook.react.bridge.ReactApplicationContext
|
|
10
12
|
import com.margelo.nitro.NitroModules
|
|
@@ -25,26 +27,56 @@ import org.json.JSONObject
|
|
|
25
27
|
|
|
26
28
|
@DoNotStrip
|
|
27
29
|
class ReactNativeJpush : HybridReactNativeJpushSpec() {
|
|
30
|
+
private val listenerLock = Any()
|
|
31
|
+
private val ownedListenerIds = mutableSetOf<Int>()
|
|
32
|
+
private var released = false
|
|
33
|
+
private var ownedContext: ReactApplicationContext? = null
|
|
34
|
+
|
|
35
|
+
@Keep
|
|
36
|
+
@DoNotStrip
|
|
37
|
+
protected class OwnedCxxPart(javaPart: ReactNativeJpush) : CxxPart(javaPart) {
|
|
38
|
+
external override fun initHybrid(): HybridData
|
|
39
|
+
}
|
|
40
|
+
|
|
41
|
+
override fun createCxxPart(): CxxPart = OwnedCxxPart(this)
|
|
42
|
+
|
|
43
|
+
override fun dispose() {
|
|
44
|
+
releaseOwnedListeners()
|
|
45
|
+
super.dispose()
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
@Keep
|
|
49
|
+
@DoNotStrip
|
|
50
|
+
fun releaseOwnedListeners() {
|
|
51
|
+
val ids: Set<Int>
|
|
52
|
+
val context: ReactApplicationContext?
|
|
53
|
+
synchronized(listenerLock) {
|
|
54
|
+
if (released) return
|
|
55
|
+
released = true
|
|
56
|
+
ids = ownedListenerIds.toSet()
|
|
57
|
+
ownedListenerIds.clear()
|
|
58
|
+
context = ownedContext
|
|
59
|
+
ownedContext = null
|
|
60
|
+
}
|
|
61
|
+
ids.forEach(JPushHelper::unregisterNitroListener)
|
|
62
|
+
if (context != null) JPushModule.releaseReactContext(context)
|
|
63
|
+
}
|
|
64
|
+
|
|
28
65
|
init {
|
|
29
66
|
getReactContext()
|
|
30
67
|
}
|
|
31
68
|
|
|
32
69
|
private fun getReactContext(): ReactApplicationContext? {
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
if (JPushModule.reactContext == null) {
|
|
41
|
-
JPushModule.reactContext = ctx
|
|
42
|
-
}
|
|
43
|
-
if (JCoreModule.reactContext == null) {
|
|
44
|
-
JCoreModule.reactContext = ctx
|
|
70
|
+
synchronized(listenerLock) {
|
|
71
|
+
if (released) return null
|
|
72
|
+
ownedContext?.let { return it }
|
|
73
|
+
val ctx = NitroModules.applicationContext ?: JPushModule.reactContext ?: JCoreModule.reactContext
|
|
74
|
+
if (ctx != null) {
|
|
75
|
+
ownedContext = ctx
|
|
76
|
+
JPushModule.retainReactContext(ctx)
|
|
45
77
|
}
|
|
78
|
+
return ctx
|
|
46
79
|
}
|
|
47
|
-
return ctx
|
|
48
80
|
}
|
|
49
81
|
|
|
50
82
|
private fun getAppContext(): Context? {
|
|
@@ -443,13 +475,16 @@ class ReactNativeJpush : HybridReactNativeJpushSpec() {
|
|
|
443
475
|
override fun addEventListener(
|
|
444
476
|
callback: (eventName: String, payloadJson: String) -> Unit
|
|
445
477
|
): Double {
|
|
446
|
-
|
|
447
|
-
|
|
478
|
+
synchronized(listenerLock) { if (released) return 0.0 }
|
|
479
|
+
val id = JPushHelper.registerNitroListener { eventName, payloadJson -> callback(eventName, payloadJson) }
|
|
480
|
+
synchronized(listenerLock) {
|
|
481
|
+
if (released) JPushHelper.unregisterNitroListener(id) else ownedListenerIds.add(id)
|
|
448
482
|
}
|
|
449
483
|
return id.toDouble()
|
|
450
484
|
}
|
|
451
485
|
|
|
452
486
|
override fun removeEventListener(id: Double) {
|
|
453
|
-
|
|
487
|
+
val owned = synchronized(listenerLock) { ownedListenerIds.remove(id.toInt()) }
|
|
488
|
+
if (owned) JPushHelper.unregisterNitroListener(id.toInt())
|
|
454
489
|
}
|
|
455
490
|
}
|
package/android/src/test/java/com/margelo/nitro/reactnativejpush/ReactNativeJpushProtocolTest.java
CHANGED
|
@@ -347,28 +347,60 @@ public class ReactNativeJpushProtocolTest {
|
|
|
347
347
|
JCoreTcpEngine.getInstance().stop(null);
|
|
348
348
|
JCoreStorage.setPushStopped(null, false);
|
|
349
349
|
|
|
350
|
-
// 2f. Verify
|
|
351
|
-
ActionHelper.getInstance()
|
|
352
|
-
|
|
353
|
-
|
|
354
|
-
|
|
355
|
-
|
|
356
|
-
|
|
357
|
-
|
|
358
|
-
|
|
359
|
-
|
|
360
|
-
|
|
361
|
-
|
|
362
|
-
|
|
363
|
-
|
|
364
|
-
|
|
365
|
-
|
|
366
|
-
|
|
367
|
-
|
|
368
|
-
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
350
|
+
// 2f. Verify Java scheduler ownership/cancellation; plain android.jar cannot prove Intent delivery or OS display.
|
|
351
|
+
final ActionHelper localHelper = ActionHelper.getInstance();
|
|
352
|
+
localHelper.clearActiveNotificationIds();
|
|
353
|
+
java.lang.reflect.Field pendingField = ActionHelper.class.getDeclaredField("pendingLocalNotifications");
|
|
354
|
+
pendingField.setAccessible(true);
|
|
355
|
+
@SuppressWarnings("unchecked")
|
|
356
|
+
Map<Integer, java.util.concurrent.ScheduledFuture<?>> pendingLocal =
|
|
357
|
+
(Map<Integer, java.util.concurrent.ScheduledFuture<?>>) pendingField.get(localHelper);
|
|
358
|
+
java.lang.reflect.Field schedulerField = ActionHelper.class.getDeclaredField("localNotificationScheduler");
|
|
359
|
+
schedulerField.setAccessible(true);
|
|
360
|
+
java.util.concurrent.ScheduledExecutorService scheduler =
|
|
361
|
+
(java.util.concurrent.ScheduledExecutorService) schedulerField.get(localHelper);
|
|
362
|
+
final CountDownLatch schedulerHeld = new CountDownLatch(1), releaseScheduler = new CountDownLatch(1);
|
|
363
|
+
scheduler.execute(new Runnable() {
|
|
364
|
+
@Override public void run() {
|
|
365
|
+
schedulerHeld.countDown();
|
|
366
|
+
try { releaseScheduler.await(); }
|
|
367
|
+
catch (InterruptedException interrupted) { Thread.currentThread().interrupt(); }
|
|
368
|
+
}
|
|
369
|
+
});
|
|
370
|
+
try {
|
|
371
|
+
assertTrue(schedulerHeld.await(1000L, TimeUnit.MILLISECONDS));
|
|
372
|
+
JPushLocalNotification cancelledLn = new JPushLocalNotification();
|
|
373
|
+
cancelledLn.setNotificationId(77001L);
|
|
374
|
+
cancelledLn.setTitle("CancelledTitle");
|
|
375
|
+
cancelledLn.setContent("CancelledContent");
|
|
376
|
+
cancelledLn.setBroadcastTime(300L);
|
|
377
|
+
JPushInterface.addLocalNotification(null, cancelledLn);
|
|
378
|
+
java.util.concurrent.ScheduledFuture<?> cancelledFuture = pendingLocal.get(Integer.valueOf(77001));
|
|
379
|
+
assertNotNull(cancelledFuture);
|
|
380
|
+
assertTrue(!cancelledFuture.isDone());
|
|
381
|
+
JPushInterface.removeLocalNotification(null, 77001L);
|
|
382
|
+
assertTrue(cancelledFuture.isCancelled());
|
|
383
|
+
assertTrue(!pendingLocal.containsKey(Integer.valueOf(77001)));
|
|
384
|
+
|
|
385
|
+
JPushLocalNotification firedLn = new JPushLocalNotification();
|
|
386
|
+
firedLn.setNotificationId(77002L);
|
|
387
|
+
firedLn.setTitle("FiredTitle");
|
|
388
|
+
firedLn.setContent("FiredContent");
|
|
389
|
+
firedLn.setBroadcastTime(70L);
|
|
390
|
+
JPushInterface.addLocalNotification(null, firedLn);
|
|
391
|
+
java.util.concurrent.ScheduledFuture<?> firedFuture = pendingLocal.get(Integer.valueOf(77002));
|
|
392
|
+
assertNotNull(firedFuture);
|
|
393
|
+
assertTrue(!firedFuture.isDone());
|
|
394
|
+
releaseScheduler.countDown();
|
|
395
|
+
long schedulerDeadline = System.nanoTime() + TimeUnit.MILLISECONDS.toNanos(1000L);
|
|
396
|
+
while (!firedFuture.isDone() && System.nanoTime() < schedulerDeadline) Thread.sleep(5L);
|
|
397
|
+
assertTrue(firedFuture.isDone() && !firedFuture.isCancelled());
|
|
398
|
+
assertTrue(!pendingLocal.containsKey(Integer.valueOf(77002)));
|
|
399
|
+
assertTrue(cancelledFuture.isCancelled());
|
|
400
|
+
} finally {
|
|
401
|
+
releaseScheduler.countDown();
|
|
402
|
+
localHelper.clearActiveNotificationIds();
|
|
403
|
+
}
|
|
372
404
|
|
|
373
405
|
// 2g. Verify ActionHelper server response parsing (getAlias, getAllTags, checkTagBindState)
|
|
374
406
|
// and rollback on non-zero statusCode for Tag/Alias/Property/MobileNumber
|
|
@@ -406,6 +438,7 @@ public class ReactNativeJpushProtocolTest {
|
|
|
406
438
|
if (req == null) {
|
|
407
439
|
break;
|
|
408
440
|
}
|
|
441
|
+
int sequence = JCoreWireCodec.extractJsonInt(JCoreWireCodec.parseJsonCommandPayload(req.body), "seq", -1);
|
|
409
442
|
if (req.command == JCoreWireCodec.CMD_HEARTBEAT) {
|
|
410
443
|
out.write(JCoreWireCodec.encodeResponseFrame(
|
|
411
444
|
JCoreWireCodec.CMD_HEARTBEAT,
|
|
@@ -418,7 +451,7 @@ public class ReactNativeJpushProtocolTest {
|
|
|
418
451
|
));
|
|
419
452
|
out.flush();
|
|
420
453
|
} else if (req.command == JCoreWireCodec.CMD_ALIAS_OP) {
|
|
421
|
-
if (
|
|
454
|
+
if (sequence == 301) {
|
|
422
455
|
byte[] body = JCoreWireCodec.buildJsonCommandPayload("{\"alias\":\"srv_alias_301\"}");
|
|
423
456
|
out.write(JCoreWireCodec.encodeResponseFrame(
|
|
424
457
|
JCoreWireCodec.CMD_ALIAS_OP,
|
|
@@ -443,7 +476,7 @@ public class ReactNativeJpushProtocolTest {
|
|
|
443
476
|
}
|
|
444
477
|
out.flush();
|
|
445
478
|
} else if (req.command == JCoreWireCodec.CMD_TAG_OP) {
|
|
446
|
-
if (
|
|
479
|
+
if (sequence == 303) {
|
|
447
480
|
byte[] body = JCoreWireCodec.buildJsonCommandPayload("{\"tags\":[\"srv_t1\",\"srv_t2\"]}");
|
|
448
481
|
out.write(JCoreWireCodec.encodeResponseFrame(
|
|
449
482
|
JCoreWireCodec.CMD_TAG_OP,
|
|
@@ -454,7 +487,7 @@ public class ReactNativeJpushProtocolTest {
|
|
|
454
487
|
0,
|
|
455
488
|
body
|
|
456
489
|
));
|
|
457
|
-
} else if (
|
|
490
|
+
} else if (sequence == 305) {
|
|
458
491
|
byte[] body = JCoreWireCodec.buildJsonCommandPayload("{\"bind\":true}");
|
|
459
492
|
out.write(JCoreWireCodec.encodeResponseFrame(
|
|
460
493
|
JCoreWireCodec.CMD_TAG_OP,
|
|
@@ -485,7 +518,7 @@ public class ReactNativeJpushProtocolTest {
|
|
|
485
518
|
req.requestId,
|
|
486
519
|
6601,
|
|
487
520
|
opUid,
|
|
488
|
-
6002,
|
|
521
|
+
sequence >= 401 && sequence <= 403 ? 0 : 6002,
|
|
489
522
|
new byte[0]
|
|
490
523
|
));
|
|
491
524
|
out.flush();
|
|
@@ -576,19 +609,22 @@ public class ReactNativeJpushProtocolTest {
|
|
|
576
609
|
|
|
577
610
|
JPushHelper.unregisterNitroListener(opListenerId);
|
|
578
611
|
JPushHelper.clearNitroListeners();
|
|
579
|
-
JCoreTcpEngine.getInstance().setRequireServerAckForOperations(false);
|
|
580
|
-
JCoreTcpEngine.getInstance().setCustomEndpoint("", 0);
|
|
581
|
-
JCoreTcpEngine.getInstance().stop(null);
|
|
582
|
-
JCoreStorage.clearRegistration(null);
|
|
583
612
|
|
|
584
|
-
// 2h. Verify
|
|
613
|
+
// 2h. Verify acknowledged property mutations commit before their TagAliasEvent with pros
|
|
585
614
|
// via JPushModuleReceiver.onPropertyOperatorResult, and JPushBroadcastReceiver ignores intents with
|
|
586
615
|
// "jpush_already_dispatched" == true while JPushModuleReceiver.onNotifyMessageOpened clears stale NOTIFICATION_BUNDLE.
|
|
587
|
-
final List<String> propEvents = new java.util.ArrayList<String>();
|
|
616
|
+
final List<String> propEvents = java.util.Collections.synchronizedList(new java.util.ArrayList<String>());
|
|
617
|
+
final CountDownLatch setPropertyAck = new CountDownLatch(1);
|
|
618
|
+
final CountDownLatch deletePropertyAck = new CountDownLatch(1);
|
|
619
|
+
final CountDownLatch cleanPropertyAck = new CountDownLatch(1);
|
|
588
620
|
int propListenerId = JPushHelper.registerNitroListener(new JPushHelper.NitroEventListener() {
|
|
589
621
|
@Override
|
|
590
622
|
public void onEvent(String eventName, String payloadJson) {
|
|
623
|
+
if (!"TagAliasEvent".equals(eventName)) return;
|
|
591
624
|
propEvents.add(eventName + ":" + payloadJson);
|
|
625
|
+
if (payloadJson.contains("401")) setPropertyAck.countDown();
|
|
626
|
+
if (payloadJson.contains("402")) deletePropertyAck.countDown();
|
|
627
|
+
if (payloadJson.contains("403")) cleanPropertyAck.countDown();
|
|
592
628
|
}
|
|
593
629
|
});
|
|
594
630
|
ActionHelper.getInstance().registerReceiver(receiver);
|
|
@@ -596,16 +632,19 @@ public class ReactNativeJpushProtocolTest {
|
|
|
596
632
|
setPropsInput.put("region", "apac");
|
|
597
633
|
setPropsInput.put("plan", "enterprise");
|
|
598
634
|
JPushInterface.setProperties(null, 401, setPropsInput);
|
|
635
|
+
assertTrue(setPropertyAck.await(3000L, TimeUnit.MILLISECONDS));
|
|
599
636
|
assertEquals("apac", JCoreStorage.getProperties(null).get("region"));
|
|
600
637
|
assertEquals("enterprise", JCoreStorage.getProperties(null).get("plan"));
|
|
601
638
|
|
|
602
639
|
Map<String, Object> delPropsInput = new LinkedHashMap<String, Object>();
|
|
603
640
|
delPropsInput.put("region", "");
|
|
604
641
|
JPushInterface.deleteProperties(null, 402, delPropsInput);
|
|
642
|
+
assertTrue(deletePropertyAck.await(3000L, TimeUnit.MILLISECONDS));
|
|
605
643
|
assertTrue(!JCoreStorage.getProperties(null).containsKey("region"));
|
|
606
644
|
assertEquals("enterprise", JCoreStorage.getProperties(null).get("plan"));
|
|
607
645
|
|
|
608
646
|
JPushInterface.cleanProperties(null, 403);
|
|
647
|
+
assertTrue(cleanPropertyAck.await(3000L, TimeUnit.MILLISECONDS));
|
|
609
648
|
assertTrue(JCoreStorage.getProperties(null).isEmpty());
|
|
610
649
|
|
|
611
650
|
assertEquals(3L, (long) propEvents.size());
|
|
@@ -614,6 +653,11 @@ public class ReactNativeJpushProtocolTest {
|
|
|
614
653
|
assertTrue(propEvents.get(2).startsWith("TagAliasEvent:") && propEvents.get(2).contains("403"));
|
|
615
654
|
JPushHelper.unregisterNitroListener(propListenerId);
|
|
616
655
|
JPushHelper.clearNitroListeners();
|
|
656
|
+
JCoreTcpEngine.getInstance().setRequireServerAckForOperations(false);
|
|
657
|
+
JCoreTcpEngine.getInstance().setCustomEndpoint("", 0);
|
|
658
|
+
JCoreTcpEngine.getInstance().stop(null);
|
|
659
|
+
JCoreStorage.clearRegistration(null);
|
|
660
|
+
|
|
617
661
|
|
|
618
662
|
android.os.Bundle staleBundle = new android.os.Bundle();
|
|
619
663
|
cn.jiguang.plugins.push.receiver.JPushBroadcastReceiver.NOTIFICATION_BUNDLE = staleBundle;
|