rns-nativecall 1.0.6 → 1.0.7
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/src/main/java/com/rnsnativecall/CallForegroundService.kt +56 -12
- package/android/src/main/java/com/rnsnativecall/NativeCallManager.kt +48 -31
- package/android/src/main/java/com/rnsnativecall/NotificationOverlayActivity.kt +9 -3
- package/package.json +1 -1
- package/withNativeCallVoip.js +3 -1
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
package com.rnsnativecall
|
|
2
2
|
|
|
3
3
|
import android.app.*
|
|
4
|
+
import android.app.Service
|
|
4
5
|
import android.content.BroadcastReceiver
|
|
5
6
|
import android.content.Context
|
|
6
7
|
import android.content.Intent
|
|
@@ -12,13 +13,14 @@ import android.os.Handler
|
|
|
12
13
|
import android.os.IBinder
|
|
13
14
|
import android.os.Looper
|
|
14
15
|
import androidx.core.app.NotificationCompat
|
|
16
|
+
import androidx.core.content.ContextCompat
|
|
15
17
|
import com.facebook.react.HeadlessJsTaskService
|
|
16
18
|
|
|
17
19
|
class CallForegroundService : Service() {
|
|
18
20
|
private var unlockReceiver: UnlockReceiver? = null // Store reference for unregistering
|
|
19
21
|
|
|
20
22
|
companion object {
|
|
21
|
-
private const val CHANNEL_ID = "
|
|
23
|
+
private const val CHANNEL_ID = "CALL_WAKE_SILENT"
|
|
22
24
|
|
|
23
25
|
fun stop(context: Context) {
|
|
24
26
|
val intent = Intent(context, CallForegroundService::class.java)
|
|
@@ -63,7 +65,7 @@ class CallForegroundService : Service() {
|
|
|
63
65
|
.setContentTitle(name)
|
|
64
66
|
.setContentText("Connecting...")
|
|
65
67
|
.setSmallIcon(applicationInfo.icon)
|
|
66
|
-
.setPriority(NotificationCompat.
|
|
68
|
+
.setPriority(NotificationCompat.PRIORITY_LOW)
|
|
67
69
|
.setCategory(NotificationCompat.CATEGORY_SERVICE)
|
|
68
70
|
.setOngoing(true)
|
|
69
71
|
.build()
|
|
@@ -72,7 +74,7 @@ class CallForegroundService : Service() {
|
|
|
72
74
|
startForeground(
|
|
73
75
|
notificationId,
|
|
74
76
|
notification,
|
|
75
|
-
ServiceInfo.
|
|
77
|
+
ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC,
|
|
76
78
|
)
|
|
77
79
|
} else {
|
|
78
80
|
startForeground(notificationId, notification)
|
|
@@ -97,13 +99,13 @@ class CallForegroundService : Service() {
|
|
|
97
99
|
e.printStackTrace()
|
|
98
100
|
}
|
|
99
101
|
|
|
100
|
-
// Auto-stop after
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
102
|
+
// / Auto - stop after 30 s
|
|
103
|
+
Handler(Looper.getMainLooper()).postDelayed({
|
|
104
|
+
try {
|
|
105
|
+
stopSelf()
|
|
106
|
+
} catch (e: Exception) {
|
|
107
|
+
}
|
|
108
|
+
}, 30000)
|
|
107
109
|
|
|
108
110
|
return START_NOT_STICKY
|
|
109
111
|
}
|
|
@@ -130,12 +132,12 @@ class CallForegroundService : Service() {
|
|
|
130
132
|
NotificationChannel(
|
|
131
133
|
CHANNEL_ID,
|
|
132
134
|
"Call Service",
|
|
133
|
-
NotificationManager.
|
|
135
|
+
NotificationManager.IMPORTANCE_LOW,
|
|
134
136
|
).apply {
|
|
135
137
|
description = "Incoming call connection state"
|
|
136
138
|
setSound(null, null)
|
|
137
139
|
enableVibration(false)
|
|
138
|
-
setBypassDnd(
|
|
140
|
+
setBypassDnd(false)
|
|
139
141
|
lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
|
|
140
142
|
}
|
|
141
143
|
val manager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
@@ -145,3 +147,45 @@ class CallForegroundService : Service() {
|
|
|
145
147
|
|
|
146
148
|
override fun onBind(intent: Intent?): IBinder? = null
|
|
147
149
|
}
|
|
150
|
+
|
|
151
|
+
class CallUiForegroundService : Service() {
|
|
152
|
+
override fun onStartCommand(
|
|
153
|
+
intent: Intent?,
|
|
154
|
+
flags: Int,
|
|
155
|
+
startId: Int,
|
|
156
|
+
): Int {
|
|
157
|
+
val notification =
|
|
158
|
+
NativeCallManager.pendingCallNotification
|
|
159
|
+
?: run {
|
|
160
|
+
stopSelf()
|
|
161
|
+
return START_NOT_STICKY
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
val notificationId =
|
|
165
|
+
NativeCallManager.pendingNotificationId
|
|
166
|
+
?: run {
|
|
167
|
+
stopSelf()
|
|
168
|
+
return START_NOT_STICKY
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
// Inside CallUiForegroundService.onStartCommand
|
|
172
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
173
|
+
startForeground(
|
|
174
|
+
notificationId,
|
|
175
|
+
notification,
|
|
176
|
+
ServiceInfo.FOREGROUND_SERVICE_TYPE_PHONE_CALL,
|
|
177
|
+
)
|
|
178
|
+
} else {
|
|
179
|
+
startForeground(notificationId, notification)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
return START_NOT_STICKY
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
override fun onDestroy() {
|
|
186
|
+
stopForeground(true)
|
|
187
|
+
super.onDestroy()
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
override fun onBind(intent: Intent?): IBinder? = null
|
|
191
|
+
}
|
|
@@ -1,23 +1,32 @@
|
|
|
1
1
|
package com.rnsnativecall
|
|
2
2
|
|
|
3
|
+
import android.app.Notification
|
|
3
4
|
import android.app.NotificationChannel
|
|
4
5
|
import android.app.NotificationManager
|
|
5
6
|
import android.app.PendingIntent
|
|
6
7
|
import android.content.Context
|
|
7
8
|
import android.content.Intent
|
|
9
|
+
import android.content.pm.ServiceInfo
|
|
8
10
|
import android.graphics.Color
|
|
9
11
|
import android.media.AudioAttributes
|
|
10
12
|
import android.media.RingtoneManager
|
|
11
13
|
import android.os.Build
|
|
14
|
+
import android.os.Bundle
|
|
12
15
|
import android.os.Handler
|
|
13
16
|
import android.os.Looper
|
|
14
17
|
import androidx.core.app.NotificationCompat
|
|
15
18
|
import androidx.core.app.Person
|
|
19
|
+
import androidx.core.content.ContextCompat
|
|
16
20
|
|
|
17
21
|
object NativeCallManager {
|
|
18
|
-
const val channelId = "
|
|
22
|
+
const val channelId = "CALL_CHANNEL_V15_URGENT"
|
|
19
23
|
private var currentCallData: Map<String, String>? = null
|
|
20
24
|
|
|
25
|
+
// Change these to internal so the Service can access them
|
|
26
|
+
@JvmStatic internal var pendingCallNotification: android.app.Notification? = null
|
|
27
|
+
|
|
28
|
+
@JvmStatic internal var pendingNotificationId: Int? = null
|
|
29
|
+
|
|
21
30
|
fun getCurrentCallData(): Map<String, String>? = currentCallData
|
|
22
31
|
|
|
23
32
|
fun handleIncomingPush(
|
|
@@ -76,24 +85,22 @@ object NativeCallManager {
|
|
|
76
85
|
|
|
77
86
|
// Setup Channel with System-Managed Sound
|
|
78
87
|
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
notificationManager.createNotificationChannel(channel)
|
|
96
|
-
}
|
|
88
|
+
|
|
89
|
+
val channel =
|
|
90
|
+
NotificationChannel(channelId, "Incoming Calls", NotificationManager.IMPORTANCE_HIGH).apply {
|
|
91
|
+
lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
|
|
92
|
+
enableVibration(true)
|
|
93
|
+
setBypassDnd(true)
|
|
94
|
+
setSound(
|
|
95
|
+
ringtoneUri,
|
|
96
|
+
AudioAttributes
|
|
97
|
+
.Builder()
|
|
98
|
+
.setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
|
|
99
|
+
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
|
|
100
|
+
.build(),
|
|
101
|
+
)
|
|
102
|
+
}
|
|
103
|
+
notificationManager.createNotificationChannel(channel)
|
|
97
104
|
|
|
98
105
|
val caller =
|
|
99
106
|
Person
|
|
@@ -111,6 +118,8 @@ object NativeCallManager {
|
|
|
111
118
|
.setOngoing(true)
|
|
112
119
|
.setAutoCancel(false)
|
|
113
120
|
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
121
|
+
.setWhen(0)
|
|
122
|
+
.setUsesChronometer(false)
|
|
114
123
|
.setContentIntent(contentIntent)
|
|
115
124
|
.setFullScreenIntent(fullScreenPendingIntent, true)
|
|
116
125
|
.setStyle(
|
|
@@ -120,8 +129,19 @@ object NativeCallManager {
|
|
|
120
129
|
.setDeclineButtonColorHint(Color.RED),
|
|
121
130
|
).setForegroundServiceBehavior(NotificationCompat.FOREGROUND_SERVICE_IMMEDIATE)
|
|
122
131
|
|
|
123
|
-
|
|
124
|
-
|
|
132
|
+
val notification = builder.build()
|
|
133
|
+
pendingCallNotification = notification
|
|
134
|
+
pendingNotificationId = notificationId
|
|
135
|
+
|
|
136
|
+
// Relay to UI Service
|
|
137
|
+
val uiIntent = Intent(context, CallUiForegroundService::class.java)
|
|
138
|
+
ContextCompat.startForegroundService(context, uiIntent)
|
|
139
|
+
|
|
140
|
+
// Manual notify ensures the banner pops immediately
|
|
141
|
+
val manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
142
|
+
manager.notify(notificationId, notification)
|
|
143
|
+
|
|
144
|
+
CallForegroundService.stop(context)
|
|
125
145
|
}
|
|
126
146
|
}
|
|
127
147
|
|
|
@@ -129,18 +149,15 @@ object NativeCallManager {
|
|
|
129
149
|
context: Context,
|
|
130
150
|
uuid: String?,
|
|
131
151
|
) {
|
|
132
|
-
|
|
133
|
-
|
|
152
|
+
pendingCallNotification = null
|
|
153
|
+
pendingNotificationId = null
|
|
134
154
|
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
notificationManager.cancel(uuid.hashCode())
|
|
155
|
+
val notificationManager =
|
|
156
|
+
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
138
157
|
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
context.stopService(serviceIntent)
|
|
143
|
-
}
|
|
158
|
+
uuid?.let { notificationManager.cancel(it.hashCode()) }
|
|
159
|
+
|
|
160
|
+
context.stopService(Intent(context, CallUiForegroundService::class.java))
|
|
144
161
|
}
|
|
145
162
|
|
|
146
163
|
fun connecting(
|
|
@@ -1,6 +1,8 @@
|
|
|
1
1
|
package com.rnsnativecall
|
|
2
2
|
|
|
3
3
|
import android.app.Activity
|
|
4
|
+
import android.app.KeyguardManager
|
|
5
|
+
import android.content.Context
|
|
4
6
|
import android.os.Build
|
|
5
7
|
import android.os.Bundle
|
|
6
8
|
import android.view.WindowManager
|
|
@@ -10,17 +12,21 @@ class NotificationOverlayActivity : Activity() {
|
|
|
10
12
|
super.onCreate(savedInstanceState)
|
|
11
13
|
|
|
12
14
|
// These flags allow the notification pill to show over the lockscreen
|
|
15
|
+
|
|
13
16
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
14
17
|
setShowWhenLocked(true)
|
|
15
18
|
setTurnScreenOn(true)
|
|
19
|
+
val km = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
|
20
|
+
km.requestDismissKeyguard(this, null)
|
|
16
21
|
} else {
|
|
17
22
|
@Suppress("DEPRECATION")
|
|
18
23
|
window.addFlags(
|
|
19
24
|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
20
|
-
|
|
21
|
-
|
|
25
|
+
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
26
|
+
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
|
|
27
|
+
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD,
|
|
22
28
|
)
|
|
23
29
|
}
|
|
24
30
|
finish()
|
|
25
31
|
}
|
|
26
|
-
}
|
|
32
|
+
}
|
package/package.json
CHANGED
package/withNativeCallVoip.js
CHANGED
|
@@ -87,6 +87,7 @@ function withAndroidConfig(config) {
|
|
|
87
87
|
'android.permission.VIBRATE',
|
|
88
88
|
'android.permission.FOREGROUND_SERVICE',
|
|
89
89
|
'android.permission.FOREGROUND_SERVICE_PHONE_CALL', // ADDED THIS
|
|
90
|
+
'android.permission.FOREGROUND_SERVICE_DATA_SYNC', // ADDED THIS
|
|
90
91
|
'android.permission.USE_FULL_SCREEN_INTENT', // ADDED THIS
|
|
91
92
|
'android.permission.MANAGE_ONGOING_CALLS', // ADDED THIS
|
|
92
93
|
'android.permission.POST_NOTIFICATIONS',
|
|
@@ -107,7 +108,8 @@ function withAndroidConfig(config) {
|
|
|
107
108
|
|
|
108
109
|
const services = [
|
|
109
110
|
{ name: 'com.rnsnativecall.CallMessagingService', exported: 'false', filter: 'com.google.firebase.MESSAGING_EVENT' },
|
|
110
|
-
{ name: 'com.rnsnativecall.CallForegroundService', type: '
|
|
111
|
+
{ name: 'com.rnsnativecall.CallForegroundService', type: 'dataSync' },
|
|
112
|
+
{ name: 'com.rnsnativecall.CallUiForegroundService', type: 'phoneCall' },
|
|
111
113
|
{ name: 'com.rnsnativecall.CallHeadlessTask' }
|
|
112
114
|
];
|
|
113
115
|
|