rns-nativecall 0.4.9 → 0.5.1

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.
@@ -23,6 +23,15 @@ class CallMessagingService : FirebaseMessagingService() {
23
23
  private val pendingNotifications = mutableMapOf<String, Runnable>()
24
24
  }
25
25
 
26
+ // Helper to check app state
27
+ private fun isAppInForeground(context: Context): Boolean {
28
+ val activityManager = context.getSystemService(Context.ACTIVITY_SERVICE) as ActivityManager
29
+ val appProcesses = activityManager.runningAppProcesses ?: return false
30
+ return appProcesses.any {
31
+ it.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND && it.processName == context.packageName
32
+ }
33
+ }
34
+
26
35
  override fun onMessageReceived(remoteMessage: RemoteMessage) {
27
36
  val data = remoteMessage.data
28
37
  val context = applicationContext
@@ -42,25 +51,20 @@ class CallMessagingService : FirebaseMessagingService() {
42
51
  if (isAppInForeground(context)) {
43
52
  CallModule.sendEventToJS("onCallReceived", data)
44
53
  } else {
45
- // 1. Show the Full Screen Notification IMMEDIATELY
46
54
  NativeCallManager.handleIncomingPush(context, data)
47
55
 
48
- // 2. Start HeadlessJS Task as a Foreground Service
49
56
  try {
50
57
  val headlessIntent = Intent(context, CallHeadlessTask::class.java).apply {
51
58
  val bundle = Bundle()
52
59
  data.forEach { (k, v) -> bundle.putString(k, v) }
53
60
  putExtras(bundle)
54
61
  }
55
-
56
- // CRITICAL: Must use startForegroundService for background starts on Android 8+
57
62
  ContextCompat.startForegroundService(context, headlessIntent)
58
63
  HeadlessJsTaskService.acquireWakeLockNow(context)
59
64
  } catch (e: Exception) {
60
65
  e.printStackTrace()
61
66
  }
62
67
 
63
- // 3. Backup Safety
64
68
  val showNotificationRunnable = Runnable {
65
69
  if (!isAppInForeground(context)) {
66
70
  NativeCallManager.handleIncomingPush(context, data)
@@ -72,5 +76,41 @@ class CallMessagingService : FirebaseMessagingService() {
72
76
  }
73
77
  }
74
78
 
75
- // ... showMissedCallNotification and isAppInForeground remain the same as your snippet
79
+ private fun showMissedCallNotification(context: Context, data: Map<String, String>, uuid: String) {
80
+ val name = data["name"] ?: "Unknown"
81
+ val callType = data["callType"] ?: "video"
82
+ val channelId = "missed_calls"
83
+ val article = if (callType.startsWith("a", ignoreCase = true)) "an" else "a"
84
+ val appName = context.applicationInfo.loadLabel(context.packageManager).toString()
85
+ val capitalizedAppName = appName.replaceFirstChar { it.uppercase() }
86
+
87
+ val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
88
+
89
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
90
+ val channel = NotificationChannel(channelId, "Missed Calls", NotificationManager.IMPORTANCE_HIGH)
91
+ notificationManager.createNotificationChannel(channel)
92
+ }
93
+
94
+ val launchIntent = context.packageManager.getLaunchIntentForPackage(context.packageName)
95
+ val pendingFlags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
96
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
97
+ } else {
98
+ PendingIntent.FLAG_UPDATE_CURRENT
99
+ }
100
+ val contentIntent = PendingIntent.getActivity(context, uuid.hashCode(), launchIntent, pendingFlags)
101
+
102
+ var iconResId = context.resources.getIdentifier("ic_missed_call", "drawable", context.packageName)
103
+ if (iconResId == 0) iconResId = android.R.drawable.sym_call_missed
104
+
105
+ val builder = NotificationCompat.Builder(context, channelId)
106
+ .setSmallIcon(iconResId)
107
+ .setContentTitle("$capitalizedAppName missed call")
108
+ .setContentText("You missed $article $callType call from $name")
109
+ .setPriority(NotificationCompat.PRIORITY_HIGH)
110
+ .setAutoCancel(true)
111
+ .setContentIntent(contentIntent)
112
+ .setCategory(NotificationCompat.CATEGORY_MISSED_CALL)
113
+
114
+ notificationManager.notify(uuid.hashCode(), builder.build())
115
+ }
76
116
  }
@@ -4,15 +4,15 @@ import android.app.NotificationChannel
4
4
  import android.app.NotificationManager
5
5
  import android.app.PendingIntent
6
6
  import android.content.Context
7
- import android.content.Intent // CRITICAL IMPORT
7
+ import android.content.Intent
8
8
  import android.os.Build
9
- import android.os.Bundle // CRITICAL IMPORT
9
+ import android.os.Bundle
10
10
  import androidx.core.app.NotificationCompat
11
11
  import android.media.Ringtone
12
12
  import android.media.RingtoneManager
13
13
  import android.graphics.Color
14
14
  import androidx.core.app.Person
15
- import androidx.core.app.NotificationCompat.CallStyle
15
+ import androidx.core.graphics.drawable.IconCompat
16
16
 
17
17
  object NativeCallManager {
18
18
 
@@ -32,7 +32,7 @@ object NativeCallManager {
32
32
  PendingIntent.FLAG_UPDATE_CURRENT
33
33
  }
34
34
 
35
- // 1. Full Screen / UI Intent
35
+ // 1. UI Intent
36
36
  val intentToActivity = Intent(context, AcceptCallActivity::class.java).apply {
37
37
  action = "ACTION_SHOW_UI_$uuid"
38
38
  data.forEach { (key, value) -> putExtra(key, value) }
@@ -52,9 +52,9 @@ object NativeCallManager {
52
52
  context, uuid.hashCode() + 1, rejectIntent, pendingFlags
53
53
  )
54
54
 
55
- // 3. Answer Intent (Using your CallActionReceiver)
55
+ // 3. Answer Intent
56
56
  val answerIntent = Intent(context, CallActionReceiver::class.java).apply {
57
- action = "ACTION_ACCEPT_$uuid" // Changed to match your Receiver logic
57
+ action = "ACTION_ACCEPT_$uuid"
58
58
  putExtra("EXTRA_CALL_UUID", uuid)
59
59
  data.forEach { (key, value) -> putExtra(key, value) }
60
60
  }
@@ -74,14 +74,15 @@ object NativeCallManager {
74
74
  notificationManager.createNotificationChannel(channel)
75
75
  }
76
76
 
77
+ // FIX: Use IconCompat.createWithResource instead of raw Int
77
78
  val caller = Person.Builder()
78
79
  .setName(name)
79
80
  .setImportant(true)
80
- .setIcon(context.applicationInfo.icon)
81
+ .setIcon(IconCompat.createWithResource(context, context.applicationInfo.icon))
81
82
  .build()
82
83
 
83
84
  val builder = NotificationCompat.Builder(context, CALL_CHANNEL_ID)
84
- //.setSmallIcon(context.applicationInfo.icon)
85
+ .setSmallIcon(context.applicationInfo.icon) // Ensure small icon is set
85
86
  .setContentTitle("Incoming $callType call")
86
87
  .setContentText(name)
87
88
  .setPriority(NotificationCompat.PRIORITY_MAX)
@@ -94,8 +95,8 @@ object NativeCallManager {
94
95
  .setStyle(
95
96
  NotificationCompat.CallStyle.forIncomingCall(
96
97
  caller,
97
- answerPendingIntent
98
- rejectPendingIntent,
98
+ answerPendingIntent, // Slot 2: Answer
99
+ rejectPendingIntent, // Slot 1: Decline
99
100
  )
100
101
  )
101
102
 
@@ -117,7 +118,6 @@ object NativeCallManager {
117
118
  ringtone = null
118
119
  } catch (e: Exception) {
119
120
  e.printStackTrace()
120
- ringtone = null
121
121
  }
122
122
  }
123
123
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rns-nativecall",
3
- "version": "0.4.9",
3
+ "version": "0.5.1",
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",