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
|
-
//
|
|
21
|
-
//
|
|
22
|
-
|
|
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
|
-
//
|
|
27
|
+
// Start the 18-second "System Pill" backup timer
|
|
26
28
|
val handler = Handler(Looper.getMainLooper())
|
|
27
29
|
handler.postDelayed({
|
|
28
|
-
//
|
|
29
|
-
//
|
|
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
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
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
package/withNativeCallVoip.js
CHANGED
|
@@ -50,37 +50,29 @@ function withAndroidConfig(config) {
|
|
|
50
50
|
}
|
|
51
51
|
});
|
|
52
52
|
|
|
53
|
-
// 2. Activity
|
|
53
|
+
// 2. Activity Setup
|
|
54
54
|
application.activity = application.activity || [];
|
|
55
55
|
|
|
56
|
-
//
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
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
|
|
72
|
+
// 3. Service Setup (Firebase + Headless Task)
|
|
77
73
|
application.service = application.service || [];
|
|
78
74
|
|
|
79
|
-
//
|
|
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';
|