rns-nativecall 0.3.3 → 0.3.4

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.
@@ -0,0 +1,22 @@
1
+ package com.rnsnativecall
2
+
3
+ import android.content.Intent
4
+ import com.facebook.react.HeadlessJsTaskService
5
+ import com.facebook.react.bridge.Arguments
6
+ import com.facebook.react.jstasks.HeadlessJsTaskConfig
7
+
8
+ class CallHeadlessTask : HeadlessJsTaskService() {
9
+ override fun getTaskConfig(intent: Intent): HeadlessJsTaskConfig? {
10
+ val extras = intent.extras
11
+ return if (extras != null) {
12
+ HeadlessJsTaskConfig(
13
+ "ColdStartCallTask", // This name must match JS registration
14
+ Arguments.fromBundle(extras),
15
+ 5000, // Timeout for the task
16
+ true // Allowed in foreground
17
+ )
18
+ } else {
19
+ null
20
+ }
21
+ }
22
+ }
@@ -3,10 +3,12 @@ package com.rnsnativecall
3
3
  import android.app.ActivityManager
4
4
  import android.content.Context
5
5
  import android.content.Intent
6
+ import android.os.Bundle
6
7
  import android.os.Handler
7
8
  import android.os.Looper
8
9
  import com.google.firebase.messaging.FirebaseMessagingService
9
10
  import com.google.firebase.messaging.RemoteMessage
11
+ import com.facebook.react.HeadlessJsTaskService
10
12
 
11
13
  class CallMessagingService : FirebaseMessagingService() {
12
14
 
@@ -15,18 +17,18 @@ class CallMessagingService : FirebaseMessagingService() {
15
17
  val context = applicationContext
16
18
 
17
19
  if (isAppInForeground(context)) {
20
+ // App is visible: Send event to active JS bridge
18
21
  CallModule.sendEventToJS("onCallReceived", data)
19
22
  } else {
20
- // 1. START WAKING THE APP IMMEDIATELY
21
- // We launch the "AcceptCallActivity" with a special flag
22
- // OR just trigger the Bridge via an Intent.
23
- wakeUpReactContext(context, data)
23
+ // App is killed/background: Start the Headless JS Task
24
+ // This wakes up the JS engine and connects your WebSocket
25
+ startHeadlessTask(context, data)
24
26
 
25
- // 2. Start the 18-second "Safety" timer
27
+ // Start the 18-second "System Pill" backup timer
26
28
  val handler = Handler(Looper.getMainLooper())
27
29
  handler.postDelayed({
28
- // Re-check: If the bridge woke up and the user navigated in-app,
29
- // isAppInForeground will now be true.
30
+ // Final safety check: if the user hasn't brought the app to foreground,
31
+ // show the native full-screen notification (The Pill)
30
32
  if (!isAppInForeground(context)) {
31
33
  NativeCallManager.handleIncomingPush(context, data)
32
34
  }
@@ -34,24 +36,17 @@ class CallMessagingService : FirebaseMessagingService() {
34
36
  }
35
37
  }
36
38
 
37
- private fun wakeUpReactContext(context: Context, data: Map<String, String>) {
38
- try {
39
- // We use the Launch Intent to trigger the splash/main activity boot sequence
40
- // but we don't bring it to the front yet (it stays in background process)
41
- val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
42
- launchIntent?.apply {
43
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
44
- // Add a hidden flag so your Splash screen knows it's a "silent boot"
45
- putExtra("silent_wake", true)
46
- data.forEach { (key, value) -> putExtra(key, value) }
47
- }
48
-
49
- // This starts the process and the React Native Bridge
50
- // Note: On Android 10+, this won't show the UI, but it WILL start the process.
51
- context.startActivity(launchIntent)
52
- } catch (e: Exception) {
53
- // Log error
54
- }
39
+ private fun startHeadlessTask(context: Context, data: Map<String, String>) {
40
+ val serviceIntent = Intent(context, CallHeadlessTask::class.java)
41
+ val bundle = Bundle()
42
+
43
+ // Pass all FCM data to the JS task
44
+ data.forEach { (key, value) -> bundle.putString(key, value) }
45
+ serviceIntent.putExtras(bundle)
46
+
47
+ // Start the service. This triggers the 'ColdStartCallTask' in index.js
48
+ context.startService(serviceIntent)
49
+ HeadlessJsTaskService.acquireWakeLockNow(context)
55
50
  }
56
51
 
57
52
  private fun isAppInForeground(context: Context): Boolean {
@@ -60,6 +55,9 @@ class CallMessagingService : FirebaseMessagingService() {
60
55
  val packageName = context.packageName
61
56
 
62
57
  for (appProcess in appProcesses) {
58
+ // IMPORTANCE_FOREGROUND only triggers if a real Activity is on screen.
59
+ // Running a Headless Task counts as IMPORTANCE_VISIBLE or lower,
60
+ // so this check remains accurate.
63
61
  if (appProcess.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND &&
64
62
  appProcess.processName == packageName) {
65
63
  return true
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rns-nativecall",
3
- "version": "0.3.3",
3
+ "version": "0.3.4",
4
4
  "description": "RNS nativecall component with native Android/iOS for handling native call ui, when app is not open or open.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",
@@ -50,37 +50,29 @@ function withAndroidConfig(config) {
50
50
  }
51
51
  });
52
52
 
53
- // 2. Activity Cleanup & Setup
53
+ // 2. Activity Setup
54
54
  application.activity = application.activity || [];
55
55
 
56
- // Remove old/redundant activities
57
- application.activity = application.activity.filter(a =>
58
- a.$['android:name'] !== 'com.rnsnativecall.IncomingCallActivity' &&
59
- a.$['android:name'] !== 'com.rnsnativecall.AcceptCallActivity'
60
- );
61
-
62
- // Add the specific AcceptCallActivity (Trampoline)
63
- application.activity.push({
64
- $: {
65
- 'android:name': 'com.rnsnativecall.AcceptCallActivity',
66
- 'android:theme': '@android:style/Theme.Translucent.NoTitleBar',
67
- 'android:excludeFromRecents': 'true',
68
- 'android:noHistory': 'true',
69
- 'android:exported': 'false',
70
- 'android:launchMode': 'singleInstance',
71
- 'android:showWhenLocked': 'true',
72
- 'android:turnScreenOn': 'true'
73
- }
74
- });
56
+ // Add AcceptCallActivity (The Trampoline)
57
+ if (!application.activity.some(a => a.$['android:name'] === 'com.rnsnativecall.AcceptCallActivity')) {
58
+ application.activity.push({
59
+ $: {
60
+ 'android:name': 'com.rnsnativecall.AcceptCallActivity',
61
+ 'android:theme': '@android:style/Theme.Translucent.NoTitleBar',
62
+ 'android:excludeFromRecents': 'true',
63
+ 'android:noHistory': 'true',
64
+ 'android:exported': 'false',
65
+ 'android:launchMode': 'singleInstance',
66
+ 'android:showWhenLocked': 'true',
67
+ 'android:turnScreenOn': 'true'
68
+ }
69
+ });
70
+ }
75
71
 
76
- // 3. Service Cleanup & Setup (Firebase only)
72
+ // 3. Service Setup (Firebase + Headless Task)
77
73
  application.service = application.service || [];
78
74
 
79
- // Explicitly remove Telecom Service
80
- application.service = application.service.filter(
81
- s => s.$['android:name'] !== 'com.rnsnativecall.MyConnectionService'
82
- );
83
-
75
+ // Add Firebase Messaging Service
84
76
  const firebaseServiceName = 'com.rnsnativecall.CallMessagingService';
85
77
  if (!application.service.some(s => s.$['android:name'] === firebaseServiceName)) {
86
78
  application.service.push({
@@ -92,6 +84,17 @@ function withAndroidConfig(config) {
92
84
  });
93
85
  }
94
86
 
87
+ // Add Headless JS Task Service
88
+ const headlessServiceName = 'com.rnsnativecall.CallHeadlessTask';
89
+ if (!application.service.some(s => s.$['android:name'] === headlessServiceName)) {
90
+ application.service.push({
91
+ $: {
92
+ 'android:name': headlessServiceName,
93
+ 'android:exported': 'false'
94
+ }
95
+ });
96
+ }
97
+
95
98
  // 4. Receiver Setup
96
99
  application.receiver = application.receiver || [];
97
100
  const receiverName = 'com.rnsnativecall.CallActionReceiver';