rns-nativecall 0.7.1 → 0.7.3
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/AcceptCallActivity.kt +33 -20
- package/android/src/main/java/com/rnsnativecall/CallMessagingService.kt +7 -17
- package/android/src/main/java/com/rnsnativecall/CallModule.kt +9 -7
- package/android/src/main/java/com/rnsnativecall/CallState.kt +36 -9
- package/android/src/main/java/com/rnsnativecall/NativeCallManager.kt +143 -77
- package/package.json +1 -1
|
@@ -13,7 +13,6 @@ class AcceptCallActivity : Activity() {
|
|
|
13
13
|
override fun onCreate(savedInstanceState: Bundle?) {
|
|
14
14
|
super.onCreate(savedInstanceState)
|
|
15
15
|
|
|
16
|
-
// Ensure we show over the lockscreen
|
|
17
16
|
window.addFlags(
|
|
18
17
|
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
19
18
|
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
@@ -23,6 +22,14 @@ class AcceptCallActivity : Activity() {
|
|
|
23
22
|
val keyguardManager = getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
|
|
24
23
|
keyguardManager.requestDismissKeyguard(this, null)
|
|
25
24
|
|
|
25
|
+
// Check: Did the user actually press "Answer" or did the system auto-launch?
|
|
26
|
+
// If the action is null or doesn't match your Answer action,
|
|
27
|
+
// it means the system is just "preparing" the activity.
|
|
28
|
+
if (intent.action?.startsWith("ACTION_ANSWER") != true) {
|
|
29
|
+
// If it's just an auto-launch, we don't fire the JS event!
|
|
30
|
+
// We can either finish() or show a tiny "Swipe to Answer" UI.
|
|
31
|
+
return
|
|
32
|
+
}
|
|
26
33
|
processCallIntent(intent)
|
|
27
34
|
}
|
|
28
35
|
|
|
@@ -35,30 +42,36 @@ class AcceptCallActivity : Activity() {
|
|
|
35
42
|
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
36
43
|
uuid?.let { notificationManager.cancel(it.hashCode()) }
|
|
37
44
|
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
extras.get(key)?.let { dataMap[key] = it.toString() }
|
|
41
|
-
}
|
|
42
|
-
|
|
43
|
-
// 1. Set the data for JS (Cold start support)
|
|
44
|
-
CallModule.setPendingCallData("onCallAccepted_pending", dataMap)
|
|
45
|
-
|
|
46
|
-
// 2. Fire event immediately if JS is alive
|
|
47
|
-
if (CallModule.isReady()) {
|
|
48
|
-
CallModule.sendEventToJS("onCallAccepted", dataMap)
|
|
49
|
-
}
|
|
50
|
-
|
|
51
|
-
// 3. Bring the Main App to the front
|
|
45
|
+
// ✅ WE STOP SENDING THE JS EVENT HERE.
|
|
46
|
+
// Instead, we pass the intent to MainActivity with a specific ACTION.
|
|
52
47
|
openMainApp(extras)
|
|
53
48
|
finish()
|
|
54
49
|
}
|
|
55
50
|
|
|
56
51
|
private fun openMainApp(extras: Bundle?) {
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
52
|
+
try {
|
|
53
|
+
// Get the actual MainActivity class name (e.g., com.yourapp.MainActivity)
|
|
54
|
+
val mainActivityClassName = "${packageName}.MainActivity"
|
|
55
|
+
|
|
56
|
+
val intent = Intent().apply {
|
|
57
|
+
setClassName(packageName, mainActivityClassName)
|
|
58
|
+
action = "com.rnsnativecall.ACTION_ANSWER"
|
|
59
|
+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
60
|
+
|
|
61
|
+
// Ensure extras are carried over
|
|
62
|
+
extras?.let { putExtras(it) }
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
startActivity(intent)
|
|
66
|
+
} catch (e: Exception) {
|
|
67
|
+
// Fallback: If explicit mapping fails, try the launch intent but force the action
|
|
68
|
+
val launchIntent = packageManager.getLaunchIntentForPackage(packageName)
|
|
69
|
+
launchIntent?.apply {
|
|
70
|
+
action = "com.rnsnativecall.ACTION_ANSWER"
|
|
71
|
+
addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_SINGLE_TOP)
|
|
72
|
+
extras?.let { putExtras(it) }
|
|
73
|
+
startActivity(this)
|
|
74
|
+
}
|
|
62
75
|
}
|
|
63
76
|
}
|
|
64
77
|
}
|
|
@@ -24,28 +24,18 @@ class CallMessagingService : FirebaseMessagingService() {
|
|
|
24
24
|
|
|
25
25
|
val uuid = data["callUuid"] ?: return
|
|
26
26
|
val type = data["type"] ?: ""
|
|
27
|
-
|
|
27
|
+
|
|
28
28
|
if (type == "CANCEL") {
|
|
29
29
|
NativeCallManager.stopRingtone()
|
|
30
|
-
|
|
30
|
+
// Pass context here to persist the cancellation
|
|
31
|
+
CallState.markCanceled(uuid, context)
|
|
31
32
|
|
|
32
|
-
try {
|
|
33
|
-
// Direct disk-level cleanup of AsyncStorage
|
|
34
|
-
val prefs = context.getSharedPreferences("RKStorage", Context.MODE_PRIVATE)
|
|
35
|
-
prefs.edit()
|
|
36
|
-
.remove("pending_call_uuid")
|
|
37
|
-
.remove("offer_$uuid")
|
|
38
|
-
.apply()
|
|
39
|
-
|
|
40
|
-
// Kill the 'Connecting...' service if it's visible
|
|
41
|
-
context.stopService(Intent(context, CallForegroundService::class.java))
|
|
42
|
-
} catch (e: Exception) {
|
|
43
|
-
e.printStackTrace()
|
|
44
|
-
}
|
|
45
|
-
|
|
46
33
|
if (CallState.getCurrent() == uuid) {
|
|
47
|
-
CallState.clear(uuid)
|
|
34
|
+
CallState.clear(uuid, context)
|
|
48
35
|
}
|
|
36
|
+
|
|
37
|
+
// Dismiss the "Connecting..." or "Incoming Call" UI
|
|
38
|
+
NativeCallManager.dismissIncomingCall(context, uuid)
|
|
49
39
|
showMissedCallNotification(context, data, uuid)
|
|
50
40
|
return
|
|
51
41
|
}
|
|
@@ -50,6 +50,7 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
50
50
|
promise.reject("CALL_ERROR", e.message)
|
|
51
51
|
}
|
|
52
52
|
}
|
|
53
|
+
|
|
53
54
|
|
|
54
55
|
/**
|
|
55
56
|
* Combined Validity Check:
|
|
@@ -57,13 +58,14 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
|
|
|
57
58
|
*/
|
|
58
59
|
@ReactMethod
|
|
59
60
|
fun checkCallValidity(uuid: String, promise: Promise) {
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
61
|
+
// Pass context so it can check the persistent disk storage
|
|
62
|
+
val isValid = CallState.shouldProceed(uuid, reactApplicationContext)
|
|
63
|
+
val isCanceled = CallState.isCanceled(uuid, reactApplicationContext)
|
|
64
|
+
|
|
65
|
+
val map = Arguments.createMap().apply {
|
|
66
|
+
putBoolean("isValid", isValid)
|
|
67
|
+
putBoolean("isCanceled", isCanceled)
|
|
68
|
+
}
|
|
67
69
|
promise.resolve(map)
|
|
68
70
|
}
|
|
69
71
|
|
|
@@ -1,9 +1,17 @@
|
|
|
1
1
|
package com.rnsnativecall
|
|
2
2
|
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.SharedPreferences
|
|
5
|
+
|
|
3
6
|
object CallState {
|
|
4
7
|
@Volatile private var currentUuid: String? = null
|
|
5
8
|
@Volatile private var canceledUuids = mutableSetOf<String>()
|
|
6
9
|
|
|
10
|
+
// Helper to access persistent storage
|
|
11
|
+
private fun getPrefs(context: Context): SharedPreferences {
|
|
12
|
+
return context.getSharedPreferences("RNS_CALL_STATE_INTERNAL", Context.MODE_PRIVATE)
|
|
13
|
+
}
|
|
14
|
+
|
|
7
15
|
@Synchronized
|
|
8
16
|
fun isBusy(): Boolean = currentUuid != null
|
|
9
17
|
|
|
@@ -19,37 +27,56 @@ object CallState {
|
|
|
19
27
|
fun getCurrent(): String? = currentUuid
|
|
20
28
|
|
|
21
29
|
@Synchronized
|
|
22
|
-
fun markCanceled(uuid: String) {
|
|
30
|
+
fun markCanceled(uuid: String, context: Context? = null) {
|
|
23
31
|
canceledUuids.add(uuid)
|
|
24
32
|
if (currentUuid == uuid) {
|
|
25
33
|
currentUuid = null
|
|
26
34
|
}
|
|
35
|
+
// PERSISTENCE: Save to disk so Splash screen can see it after app restart
|
|
36
|
+
context?.let {
|
|
37
|
+
getPrefs(it).edit().putBoolean("canceled_$uuid", true).apply()
|
|
38
|
+
}
|
|
27
39
|
}
|
|
28
40
|
|
|
29
|
-
// ✅ Fixes the "Unresolved reference 'isCanceled'" error
|
|
30
41
|
@Synchronized
|
|
31
|
-
fun isCanceled(uuid: String?): Boolean {
|
|
42
|
+
fun isCanceled(uuid: String?, context: Context? = null): Boolean {
|
|
32
43
|
if (uuid == null) return false
|
|
33
|
-
|
|
44
|
+
// Check memory first
|
|
45
|
+
if (canceledUuids.contains(uuid)) return true
|
|
46
|
+
|
|
47
|
+
// PERSISTENCE: Check disk if memory was wiped (App was killed)
|
|
48
|
+
return context?.let {
|
|
49
|
+
getPrefs(it).getBoolean("canceled_$uuid", false)
|
|
50
|
+
} ?: false
|
|
34
51
|
}
|
|
35
52
|
|
|
36
53
|
@Synchronized
|
|
37
|
-
fun clear(uuid: String?) {
|
|
54
|
+
fun clear(uuid: String?, context: Context? = null) {
|
|
38
55
|
if (uuid == null) return
|
|
39
56
|
if (currentUuid == uuid) currentUuid = null
|
|
40
57
|
canceledUuids.remove(uuid)
|
|
58
|
+
|
|
59
|
+
// PERSISTENCE: Cleanup disk entry
|
|
60
|
+
context?.let {
|
|
61
|
+
getPrefs(it).edit().remove("canceled_$uuid").apply()
|
|
62
|
+
}
|
|
41
63
|
}
|
|
42
64
|
|
|
43
65
|
@Synchronized
|
|
44
|
-
fun shouldProceed(uuid: String?): Boolean {
|
|
66
|
+
fun shouldProceed(uuid: String?, context: Context? = null): Boolean {
|
|
45
67
|
if (uuid == null) return false
|
|
46
|
-
|
|
68
|
+
|
|
69
|
+
// A call should proceed if it is the current UUID AND it hasn't been canceled
|
|
70
|
+
// We use the context-aware isCanceled to check the disk if necessary
|
|
71
|
+
val canceled = isCanceled(uuid, context)
|
|
72
|
+
return (currentUuid == uuid || currentUuid == null) && !canceled
|
|
47
73
|
}
|
|
48
74
|
|
|
49
75
|
@Synchronized
|
|
50
76
|
fun clearAll() {
|
|
51
77
|
currentUuid = null
|
|
52
78
|
canceledUuids.clear()
|
|
79
|
+
// Note: clearAll usually doesn't have context,
|
|
80
|
+
// specific UUIDs are usually cleared via the clear(uuid, context) method
|
|
53
81
|
}
|
|
54
|
-
}
|
|
55
|
-
|
|
82
|
+
}
|
|
@@ -11,92 +11,158 @@ import android.media.Ringtone
|
|
|
11
11
|
import android.media.RingtoneManager
|
|
12
12
|
import android.graphics.Color
|
|
13
13
|
|
|
14
|
+
import androidx.core.app.Person
|
|
15
|
+
import androidx.core.app.NotificationCompat
|
|
16
|
+
|
|
14
17
|
object NativeCallManager {
|
|
15
18
|
|
|
16
19
|
private var ringtone: Ringtone? = null
|
|
17
20
|
const val channelId = "CALL_CHANNEL_ID"
|
|
18
21
|
|
|
19
|
-
fun handleIncomingPush(context: Context, data: Map<String, String>) {
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
22
|
+
// fun handleIncomingPush(context: Context, data: Map<String, String>) {
|
|
23
|
+
// val uuid = data["callUuid"] ?: return
|
|
24
|
+
// stopRingtone()
|
|
25
|
+
|
|
26
|
+
// val name = data["name"] ?: "Incoming Call"
|
|
27
|
+
// val callType = data["callType"] ?: "audio"
|
|
28
|
+
// val notificationId = uuid.hashCode()
|
|
29
|
+
|
|
30
|
+
// val pendingFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
|
|
31
|
+
// PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
|
|
32
|
+
// } else {
|
|
33
|
+
// PendingIntent.FLAG_UPDATE_CURRENT
|
|
34
|
+
// }
|
|
35
|
+
|
|
36
|
+
// val noOpIntent = PendingIntent.getActivity(
|
|
37
|
+
// context,
|
|
38
|
+
// notificationId + 1,
|
|
39
|
+
// Intent(),
|
|
40
|
+
// pendingFlags
|
|
41
|
+
// )
|
|
42
|
+
|
|
43
|
+
// val intentToActivity = Intent(context, AcceptCallActivity::class.java).apply {
|
|
44
|
+
// this.action = "ACTION_SHOW_UI_$uuid"
|
|
45
|
+
// data.forEach { (key, value) -> this.putExtra(key, value) }
|
|
46
|
+
// this.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
47
|
+
// }
|
|
48
|
+
|
|
49
|
+
// val fullScreenPendingIntent = PendingIntent.getActivity(
|
|
50
|
+
// context,
|
|
51
|
+
// notificationId,
|
|
52
|
+
// intentToActivity,
|
|
53
|
+
// pendingFlags
|
|
54
|
+
// )
|
|
55
|
+
|
|
56
|
+
// val rejectIntent = Intent(context, CallActionReceiver::class.java).apply {
|
|
57
|
+
// this.action = "ACTION_REJECT_$uuid"
|
|
58
|
+
// this.putExtra("EXTRA_CALL_UUID", uuid)
|
|
59
|
+
// data.forEach { (key, value) -> this.putExtra(key, value) }
|
|
60
|
+
// }
|
|
61
|
+
|
|
62
|
+
// val rejectPendingIntent = PendingIntent.getBroadcast(
|
|
63
|
+
// context,
|
|
64
|
+
// notificationId,
|
|
65
|
+
// rejectIntent,
|
|
66
|
+
// pendingFlags
|
|
67
|
+
// )
|
|
68
|
+
|
|
69
|
+
// val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
70
|
+
|
|
71
|
+
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
|
|
72
|
+
// val channel = NotificationChannel(
|
|
73
|
+
// channelId,
|
|
74
|
+
// "Incoming Calls",
|
|
75
|
+
// NotificationManager.IMPORTANCE_HIGH // NotificationManager.IMPORTANCE_HIGH
|
|
76
|
+
// ).apply {
|
|
77
|
+
// enableVibration(true)
|
|
78
|
+
// vibrationPattern = longArrayOf(0, 500, 500, 500)
|
|
79
|
+
// lightColor = Color.GREEN
|
|
80
|
+
// setBypassDnd(true)
|
|
81
|
+
// lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
|
|
82
|
+
// setSound(null, null)
|
|
83
|
+
// }
|
|
84
|
+
// notificationManager.createNotificationChannel(channel)
|
|
85
|
+
// }
|
|
86
|
+
|
|
87
|
+
// val builder = NotificationCompat.Builder(context, channelId)
|
|
88
|
+
// .setSmallIcon(context.applicationInfo.icon)
|
|
89
|
+
// .setContentTitle("Incoming $callType call")
|
|
90
|
+
// .setContentText(name)
|
|
91
|
+
// .setPriority(NotificationCompat.PRIORITY_MAX) // PRIORITY_HIGH
|
|
92
|
+
// .setCategory(NotificationCompat.CATEGORY_CALL) // CATEGORY_CALL
|
|
93
|
+
// .setOngoing(true)
|
|
94
|
+
// .setAutoCancel(false)
|
|
95
|
+
// .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
96
|
+
// .setFullScreenIntent(fullScreenPendingIntent, true)
|
|
97
|
+
// .setContentIntent(noOpIntent)
|
|
98
|
+
// .addAction(0, "Answer", fullScreenPendingIntent)
|
|
99
|
+
// .addAction(0, "Decline", rejectPendingIntent)
|
|
100
|
+
|
|
101
|
+
// notificationManager.notify(notificationId, builder.build())
|
|
102
|
+
|
|
103
|
+
// try {
|
|
104
|
+
// val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
|
|
105
|
+
// ringtone = RingtoneManager.getRingtone(context, ringtoneUri)
|
|
106
|
+
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
|
|
107
|
+
// ringtone?.isLooping = true
|
|
108
|
+
// }
|
|
109
|
+
// ringtone?.play()
|
|
110
|
+
// } catch (e: Exception) {
|
|
111
|
+
// e.printStackTrace()
|
|
112
|
+
// }
|
|
113
|
+
// }
|
|
114
|
+
|
|
115
|
+
|
|
116
|
+
fun handleIncomingPush(context: Context, data: Map<String, String>) {
|
|
117
|
+
val uuid = data["callUuid"] ?: return
|
|
118
|
+
stopRingtone()
|
|
119
|
+
|
|
120
|
+
val name = data["name"] ?: "Incoming Call"
|
|
121
|
+
val callType = data["callType"] ?: "audio"
|
|
122
|
+
val notificationId = uuid.hashCode()
|
|
45
123
|
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
124
|
+
// 1. Create the Person object (Required for CallStyle)
|
|
125
|
+
val caller = Person.Builder()
|
|
126
|
+
.setName(name)
|
|
127
|
+
.setImportant(true)
|
|
128
|
+
.build()
|
|
129
|
+
|
|
130
|
+
// 2. Intents (Keep your existing intent logic)
|
|
131
|
+
val intentToActivity = Intent(context, AcceptCallActivity::class.java).apply {
|
|
132
|
+
this.action = "ACTION_ANSWER_$uuid"
|
|
133
|
+
data.forEach { (key, value) -> this.putExtra(key, value) }
|
|
134
|
+
this.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
|
|
135
|
+
}
|
|
52
136
|
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
137
|
+
val fullScreenPendingIntent = PendingIntent.getActivity(
|
|
138
|
+
context, notificationId, intentToActivity,
|
|
139
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S)
|
|
140
|
+
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
|
|
141
|
+
else PendingIntent.FLAG_UPDATE_CURRENT
|
|
142
|
+
)
|
|
58
143
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
144
|
+
// 3. Build the Notification with CallStyle
|
|
145
|
+
val builder = NotificationCompat.Builder(context, channelId)
|
|
146
|
+
.setSmallIcon(context.applicationInfo.icon)
|
|
147
|
+
.setPriority(NotificationCompat.PRIORITY_MAX)
|
|
148
|
+
.setCategory(NotificationCompat.CATEGORY_CALL)
|
|
149
|
+
.setOngoing(true)
|
|
150
|
+
.setAutoCancel(false)
|
|
151
|
+
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
152
|
+
// This makes it show on the lock screen WITHOUT auto-launching the activity
|
|
153
|
+
.setFullScreenIntent(fullScreenPendingIntent, true)
|
|
154
|
+
.setStyle(
|
|
155
|
+
NotificationCompat.CallStyle.forIncomingCall(
|
|
156
|
+
caller,
|
|
157
|
+
rejectPendingIntent, // Use your existing rejectIntent
|
|
158
|
+
fullScreenPendingIntent
|
|
159
|
+
)
|
|
64
160
|
)
|
|
65
161
|
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
channelId,
|
|
71
|
-
"Incoming Calls",
|
|
72
|
-
NotificationManager.IMPORTANCE_HIGH // NotificationManager.IMPORTANCE_HIGH
|
|
73
|
-
).apply {
|
|
74
|
-
enableVibration(true)
|
|
75
|
-
vibrationPattern = longArrayOf(0, 500, 500, 500)
|
|
76
|
-
lightColor = Color.GREEN
|
|
77
|
-
setBypassDnd(true)
|
|
78
|
-
lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
|
|
79
|
-
setSound(null, null)
|
|
80
|
-
}
|
|
81
|
-
notificationManager.createNotificationChannel(channel)
|
|
82
|
-
}
|
|
83
|
-
|
|
84
|
-
val builder = NotificationCompat.Builder(context, channelId)
|
|
85
|
-
.setSmallIcon(context.applicationInfo.icon)
|
|
86
|
-
.setContentTitle("Incoming $callType call")
|
|
87
|
-
.setContentText(name)
|
|
88
|
-
.setPriority(NotificationCompat.PRIORITY_MAX) // PRIORITY_HIGH
|
|
89
|
-
.setCategory(NotificationCompat.CATEGORY_CALL) // CATEGORY_CALL
|
|
90
|
-
.setOngoing(true)
|
|
91
|
-
.setAutoCancel(false)
|
|
92
|
-
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
|
|
93
|
-
.setFullScreenIntent(fullScreenPendingIntent, true)
|
|
94
|
-
.setContentIntent(noOpIntent)
|
|
95
|
-
.addAction(0, "Answer", fullScreenPendingIntent)
|
|
96
|
-
.addAction(0, "Decline", rejectPendingIntent)
|
|
97
|
-
|
|
98
|
-
notificationManager.notify(notificationId, builder.build())
|
|
99
|
-
|
|
162
|
+
val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
|
|
163
|
+
// ... ensure channel is created ...
|
|
164
|
+
notificationManager.notify(notificationId, builder.build())
|
|
165
|
+
|
|
100
166
|
try {
|
|
101
167
|
val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
|
|
102
168
|
ringtone = RingtoneManager.getRingtone(context, ringtoneUri)
|
|
@@ -107,7 +173,7 @@ object NativeCallManager {
|
|
|
107
173
|
} catch (e: Exception) {
|
|
108
174
|
e.printStackTrace()
|
|
109
175
|
}
|
|
110
|
-
|
|
176
|
+
}
|
|
111
177
|
|
|
112
178
|
fun stopRingtone() {
|
|
113
179
|
try {
|