rns-nativecall 0.7.4 → 0.7.6

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.
@@ -9,132 +9,72 @@ import android.os.Build
9
9
  import android.media.Ringtone
10
10
  import android.media.RingtoneManager
11
11
  import android.graphics.Color
12
-
13
12
  import androidx.core.app.Person
14
13
  import androidx.core.app.NotificationCompat
14
+ import android.app.KeyguardManager
15
15
 
16
16
  object NativeCallManager {
17
17
 
18
18
  private var ringtone: Ringtone? = null
19
19
  const val channelId = "CALL_CHANNEL_ID"
20
20
 
21
- // fun handleIncomingPush(context: Context, data: Map<String, String>) {
22
- // val uuid = data["callUuid"] ?: return
23
- // stopRingtone()
24
-
25
- // val name = data["name"] ?: "Incoming Call"
26
- // val callType = data["callType"] ?: "audio"
27
- // val notificationId = uuid.hashCode()
28
-
29
- // val pendingFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
30
- // PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
31
- // } else {
32
- // PendingIntent.FLAG_UPDATE_CURRENT
33
- // }
34
-
35
- // val noOpIntent = PendingIntent.getActivity(
36
- // context,
37
- // notificationId + 1,
38
- // Intent(),
39
- // pendingFlags
40
- // )
41
-
42
- // val intentToActivity = Intent(context, AcceptCallActivity::class.java).apply {
43
- // this.action = "ACTION_SHOW_UI_$uuid"
44
- // data.forEach { (key, value) -> this.putExtra(key, value) }
45
- // this.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
46
- // }
47
-
48
- // val fullScreenPendingIntent = PendingIntent.getActivity(
49
- // context,
50
- // notificationId,
51
- // intentToActivity,
52
- // pendingFlags
53
- // )
54
-
55
- // val rejectIntent = Intent(context, CallActionReceiver::class.java).apply {
56
- // this.action = "ACTION_REJECT_$uuid"
57
- // this.putExtra("EXTRA_CALL_UUID", uuid)
58
- // data.forEach { (key, value) -> this.putExtra(key, value) }
59
- // }
60
-
61
- // val rejectPendingIntent = PendingIntent.getBroadcast(
62
- // context,
63
- // notificationId,
64
- // rejectIntent,
65
- // pendingFlags
66
- // )
67
-
68
- // val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
69
-
70
- // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
71
- // val channel = NotificationChannel(
72
- // channelId,
73
- // "Incoming Calls",
74
- // NotificationManager.IMPORTANCE_HIGH // NotificationManager.IMPORTANCE_HIGH
75
- // ).apply {
76
- // enableVibration(true)
77
- // vibrationPattern = longArrayOf(0, 500, 500, 500)
78
- // lightColor = Color.GREEN
79
- // setBypassDnd(true)
80
- // lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
81
- // setSound(null, null)
82
- // }
83
- // notificationManager.createNotificationChannel(channel)
84
- // }
85
-
86
- // val builder = NotificationCompat.Builder(context, channelId)
87
- // .setSmallIcon(context.applicationInfo.icon)
88
- // .setContentTitle("Incoming $callType call")
89
- // .setContentText(name)
90
- // .setPriority(NotificationCompat.PRIORITY_MAX) // PRIORITY_HIGH
91
- // .setCategory(NotificationCompat.CATEGORY_CALL) // CATEGORY_CALL
92
- // .setOngoing(true)
93
- // .setAutoCancel(false)
94
- // .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
95
- // .setFullScreenIntent(fullScreenPendingIntent, true)
96
- // .setContentIntent(noOpIntent)
97
- // .addAction(0, "Answer", fullScreenPendingIntent)
98
- // .addAction(0, "Decline", rejectPendingIntent)
21
+ // ADDED: stopRingtone definition
22
+ fun stopRingtone() {
23
+ try {
24
+ ringtone?.let { if (it.isPlaying) it.stop() }
25
+ ringtone = null
26
+ } catch (e: Exception) {
27
+ ringtone = null
28
+ }
29
+ }
99
30
 
100
- // notificationManager.notify(notificationId, builder.build())
31
+ // ✅ ADDED: showMissedCallNotification definition
32
+ fun showMissedCallNotification(context: Context, data: Map<String, String>, uuid: String) {
33
+ val name = data["name"] ?: "Unknown Caller"
34
+ val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
35
+
36
+ val builder = NotificationCompat.Builder(context, channelId)
37
+ .setSmallIcon(context.applicationInfo.icon)
38
+ .setContentTitle("Missed Call")
39
+ .setContentText("Incoming call from $name")
40
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
41
+ .setAutoCancel(true)
101
42
 
102
- // try {
103
- // val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
104
- // ringtone = RingtoneManager.getRingtone(context, ringtoneUri)
105
- // if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P) {
106
- // ringtone?.isLooping = true
107
- // }
108
- // ringtone?.play()
109
- // } catch (e: Exception) {
110
- // e.printStackTrace()
111
- // }
112
- // }
43
+ notificationManager.notify(uuid.hashCode(), builder.build())
44
+ }
113
45
 
114
- fun handleIncomingPush(context: Context, data: Map<String, String>) {
46
+ fun handleIncomingPush(context: Context, data: Map<String, String>) {
115
47
  val uuid = data["callUuid"] ?: return
116
48
  stopRingtone()
117
49
 
118
50
  val name = data["name"] ?: "Incoming Call"
119
51
  val callType = data["callType"] ?: "audio"
120
- val notificationId = uuid.hashCode()
121
52
 
53
+ // --- LOCK SCREEN GATEKEEPER ---
54
+ val keyguardManager = context.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
55
+ if (keyguardManager.isKeyguardLocked) {
56
+ // Device is locked? We bounce it!
57
+ CallState.markCanceled(uuid, context)
58
+ showMissedCallNotification(context, data, uuid)
59
+ return // 🛑 Flow stops here
60
+ }
61
+
62
+ val notificationId = uuid.hashCode()
122
63
  val pendingFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
123
64
  PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_MUTABLE
124
65
  } else {
125
66
  PendingIntent.FLAG_UPDATE_CURRENT
126
67
  }
127
68
 
128
- // 1. Setup the Intents
69
+ val noOpIntent = PendingIntent.getActivity(context, notificationId + 1, Intent(), pendingFlags)
70
+
129
71
  val intentToActivity = Intent(context, AcceptCallActivity::class.java).apply {
130
- this.action = "ACTION_ANSWER_$uuid"
72
+ this.action = "ACTION_SHOW_UI_$uuid"
131
73
  data.forEach { (key, value) -> this.putExtra(key, value) }
132
74
  this.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TOP)
133
75
  }
134
76
 
135
- val fullScreenPendingIntent = PendingIntent.getActivity(
136
- context, notificationId, intentToActivity, pendingFlags
137
- )
77
+ val fullScreenPendingIntent = PendingIntent.getActivity(context, notificationId, intentToActivity, pendingFlags)
138
78
 
139
79
  val rejectIntent = Intent(context, CallActionReceiver::class.java).apply {
140
80
  this.action = "ACTION_REJECT_$uuid"
@@ -142,55 +82,38 @@ object NativeCallManager {
142
82
  data.forEach { (key, value) -> this.putExtra(key, value) }
143
83
  }
144
84
 
145
- // Fix: Define the missing rejectPendingIntent
146
- val rejectPendingIntent = PendingIntent.getBroadcast(
147
- context, notificationId, rejectIntent, pendingFlags
148
- )
149
-
150
- // 2. Create the Person object for CallStyle
151
- val caller = Person.Builder()
152
- .setName(name)
153
- .setImportant(true)
154
- .build()
85
+ val rejectPendingIntent = PendingIntent.getBroadcast(context, notificationId, rejectIntent, pendingFlags)
155
86
 
156
87
  val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
157
88
 
158
- // 3. Setup Channel
159
89
  if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
160
- val channel = NotificationChannel(
161
- channelId,
162
- "Incoming Calls",
163
- NotificationManager.IMPORTANCE_HIGH
164
- ).apply {
90
+ val channel = NotificationChannel(channelId, "Incoming Calls", NotificationManager.IMPORTANCE_HIGH).apply {
165
91
  enableVibration(true)
166
92
  vibrationPattern = longArrayOf(0, 500, 500, 500)
167
93
  lightColor = Color.GREEN
168
94
  setBypassDnd(true)
95
+ lockscreenVisibility = NotificationCompat.VISIBILITY_PUBLIC
169
96
  setSound(null, null)
170
97
  }
171
98
  notificationManager.createNotificationChannel(channel)
172
99
  }
173
100
 
174
- // 4. Build with CallStyle
175
101
  val builder = NotificationCompat.Builder(context, channelId)
176
102
  .setSmallIcon(context.applicationInfo.icon)
103
+ .setContentTitle("Incoming $callType call")
104
+ .setContentText(name)
177
105
  .setPriority(NotificationCompat.PRIORITY_MAX)
178
106
  .setCategory(NotificationCompat.CATEGORY_CALL)
179
107
  .setOngoing(true)
180
108
  .setAutoCancel(false)
181
109
  .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
182
110
  .setFullScreenIntent(fullScreenPendingIntent, true)
183
- .setStyle(
184
- NotificationCompat.CallStyle.forIncomingCall(
185
- caller,
186
- rejectPendingIntent,
187
- fullScreenPendingIntent
188
- )
189
- )
111
+ .setContentIntent(noOpIntent)
112
+ .addAction(0, "Answer", fullScreenPendingIntent)
113
+ .addAction(0, "Decline", rejectPendingIntent)
190
114
 
191
115
  notificationManager.notify(notificationId, builder.build())
192
116
 
193
- // 5. Start Ringtone
194
117
  try {
195
118
  val ringtoneUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
196
119
  ringtone = RingtoneManager.getRingtone(context, ringtoneUri)
@@ -203,53 +126,35 @@ object NativeCallManager {
203
126
  }
204
127
  }
205
128
 
206
-
207
- fun stopRingtone() {
208
- try {
209
- ringtone?.let { if (it.isPlaying) it.stop() }
210
- ringtone = null
211
- } catch (e: Exception) {
212
- ringtone = null
213
- }
129
+ fun connecting(context: Context, uuid: String, name: String, callType: String) {
130
+ val notificationId = uuid.hashCode()
131
+ val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
132
+ val builder = NotificationCompat.Builder(context, channelId)
133
+ .setSmallIcon(context.applicationInfo.icon)
134
+ .setContentTitle("Incoming $callType call")
135
+ .setContentText("Connecting…")
136
+ .setPriority(NotificationCompat.PRIORITY_MAX)
137
+ .setCategory(NotificationCompat.CATEGORY_CALL)
138
+ .setOngoing(true)
139
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
140
+ .setProgress(0, 0, true)
141
+ notificationManager.notify(notificationId, builder.build())
214
142
  }
215
143
 
216
- fun connecting(context: Context, uuid: String, name: String, callType: String) {
217
- val notificationId = uuid.hashCode()
218
- val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
219
-
220
- val builder = NotificationCompat.Builder(context, channelId)
221
- .setSmallIcon(context.applicationInfo.icon)
222
- .setContentTitle("Incoming $callType call")
223
- .setContentText("Connecting…") // ✅ show connecting text
224
- .setSubText("Connecting…") // status line
225
- .setPriority(NotificationCompat.PRIORITY_MAX)
226
- .setCategory(NotificationCompat.CATEGORY_CALL)
227
- .setOngoing(true)
228
- .setAutoCancel(false)
229
- .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
230
- .setProgress(0, 0, true) // ✅ system activity indicator (indeterminate progress bar)
231
-
232
- notificationManager.notify(notificationId, builder.build())
233
- }
234
-
235
- fun aborting(context: Context, uuid: String, name: String, callType: String) {
236
- val notificationId = uuid.hashCode()
237
- val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
238
-
239
- val builder = NotificationCompat.Builder(context, channelId)
240
- .setSmallIcon(context.applicationInfo.icon)
241
- .setContentTitle("Incoming $callType call")
242
- .setContentText("Aborting…") // ✅ show aborting text
243
- .setSubText("Aborting…") // status line
244
- .setPriority(NotificationCompat.PRIORITY_MAX)
245
- .setCategory(NotificationCompat.CATEGORY_CALL)
246
- .setOngoing(true)
247
- .setAutoCancel(false)
248
- .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
249
- .setProgress(0, 0, true) // ✅ indeterminate progress indicator
250
-
251
- notificationManager.notify(notificationId, builder.build())
252
- }
144
+ fun aborting(context: Context, uuid: String, name: String, callType: String) {
145
+ val notificationId = uuid.hashCode()
146
+ val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
147
+ val builder = NotificationCompat.Builder(context, channelId)
148
+ .setSmallIcon(context.applicationInfo.icon)
149
+ .setContentTitle("Incoming $callType call")
150
+ .setContentText("Aborting…")
151
+ .setPriority(NotificationCompat.PRIORITY_MAX)
152
+ .setCategory(NotificationCompat.CATEGORY_CALL)
153
+ .setOngoing(true)
154
+ .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
155
+ .setProgress(0, 0, true)
156
+ notificationManager.notify(notificationId, builder.build())
157
+ }
253
158
 
254
159
  fun dismissIncomingCall(context: Context, uuid: String?) {
255
160
  stopRingtone()
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rns-nativecall",
3
- "version": "0.7.4",
3
+ "version": "0.7.6",
4
4
  "description": "High-performance React Native module for handling native VoIP call UI on Android and iOS.",
5
5
  "main": "index.js",
6
6
  "types": "index.d.ts",