rns-nativecall 0.2.8 → 0.3.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.
@@ -1,14 +1,7 @@
1
1
  package com.rnsnativecall
2
2
 
3
3
  import android.app.NotificationManager
4
- import android.content.ComponentName
5
4
  import android.content.Context
6
- import android.content.Intent
7
- import android.telecom.DisconnectCause
8
- import android.telecom.PhoneAccount
9
- import android.telecom.PhoneAccountHandle
10
- import android.telecom.TelecomManager
11
- import android.widget.Toast
12
5
  import com.facebook.react.bridge.*
13
6
  import com.facebook.react.modules.core.DeviceEventManagerModule
14
7
 
@@ -16,16 +9,12 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
16
9
 
17
10
  init {
18
11
  instance = this
19
- registerPhoneAccount()
20
12
  }
21
13
 
22
14
  override fun getName() = "CallModule"
23
15
 
24
- // ... getPhoneAccountHandle and registerPhoneAccount remain the same ...
25
-
26
16
  @ReactMethod
27
17
  fun getInitialCallData(promise: Promise) {
28
- // Convert our stored simple Map into a WritableMap for JS
29
18
  val data = pendingCallDataMap?.let { map ->
30
19
  val writableMap = Arguments.createMap()
31
20
  map.forEach { (key, value) ->
@@ -33,9 +22,8 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
33
22
  }
34
23
  writableMap
35
24
  }
36
-
37
25
  promise.resolve(data)
38
- pendingCallDataMap = null // Clear after consumption
26
+ pendingCallDataMap = null
39
27
  }
40
28
 
41
29
  @ReactMethod
@@ -55,25 +43,27 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
55
43
 
56
44
  @ReactMethod
57
45
  fun endNativeCall(uuid: String) {
46
+ // Since we aren't using Telecom, we just stop the ringtone and clear notification
58
47
  NativeCallManager.stopRingtone()
59
- pendingCallDataMap = null // Clear any pending data
48
+ pendingCallDataMap = null
60
49
 
61
50
  val notificationManager = reactApplicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
62
51
  notificationManager.cancel(101)
52
+
53
+ // No more ConnectionService to destroy!
54
+ }
63
55
 
64
- val connection = MyConnectionService.getConnection(uuid)
65
- connection?.let {
66
- it.setDisconnected(DisconnectCause(DisconnectCause.MISSED))
67
- it.destroy()
68
- MyConnectionService.removeConnection(uuid)
69
- }
56
+ // This is a dummy now since we don't need PhoneAccount permissions anymore
57
+ @ReactMethod
58
+ fun checkTelecomPermissions(promise: Promise) {
59
+ promise.resolve(true)
70
60
  }
71
61
 
72
- // ... checkTelecomPermissions remains the same ...
62
+ @ReactMethod fun addListener(eventName: String) {}
63
+ @ReactMethod fun removeListeners(count: Int) {}
73
64
 
74
65
  companion object {
75
66
  private var instance: CallModule? = null
76
- // Use a standard Map to store data so we don't depend on React Context being alive
77
67
  private var pendingCallDataMap: Map<String, String>? = null
78
68
 
79
69
  @JvmStatic
@@ -85,7 +75,6 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
85
75
  fun sendEventToJS(eventName: String, params: Any?) {
86
76
  val reactContext = instance?.reactApplicationContext
87
77
 
88
- // Convert params to WritableMap
89
78
  val bridgeData = when (params) {
90
79
  is Map<*, *> -> {
91
80
  val map = Arguments.createMap()
@@ -102,7 +91,6 @@ class CallModule(reactContext: ReactApplicationContext) : ReactContextBaseJavaMo
102
91
  .getJSModule(DeviceEventManagerModule.RCTDeviceEventEmitter::class.java)
103
92
  ?.emit(eventName, bridgeData)
104
93
  } else if (eventName == "onCallAccepted" && params is Map<*, *>) {
105
- // FALLBACK: Store data for polling if JS isn't ready
106
94
  setPendingCallData(params as Map<String, String>)
107
95
  }
108
96
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "rns-nativecall",
3
- "version": "0.2.8",
3
+ "version": "0.3.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",
@@ -1,93 +0,0 @@
1
- package com.rnsnativecall
2
-
3
- import android.app.*
4
- import android.content.Context
5
- import android.content.Intent
6
- import android.media.AudioAttributes
7
- import android.media.MediaPlayer
8
- import android.media.RingtoneManager
9
- import android.os.Build
10
- import androidx.core.app.NotificationCompat
11
-
12
- object NativeCallManager {
13
- private var mediaPlayer: MediaPlayer? = null
14
- private const val CHANNEL_ID = "incoming_calls"
15
- private const val NOTIFICATION_ID = 101
16
-
17
- fun handleIncomingPush(context: Context, data: Map<String, String>) {
18
- startRingtone(context)
19
- showIncomingCallNotification(context, data)
20
- }
21
-
22
- private fun startRingtone(context: Context) {
23
- if (mediaPlayer != null) return
24
- try {
25
- val uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
26
- mediaPlayer = MediaPlayer().apply {
27
- setDataSource(context, uri)
28
- setAudioAttributes(AudioAttributes.Builder()
29
- .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
30
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
31
- .build())
32
- isLooping = true
33
- prepare()
34
- start()
35
- }
36
- } catch (e: Exception) { e.printStackTrace() }
37
- }
38
-
39
- fun stopRingtone() {
40
- mediaPlayer?.stop()
41
- mediaPlayer?.release()
42
- mediaPlayer = null
43
- }
44
-
45
- private fun showIncomingCallNotification(context: Context, data: Map<String, String>) {
46
- val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
47
-
48
- // Create Channel for Android O+
49
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
50
- val channel = NotificationChannel(CHANNEL_ID, "Incoming Calls", NotificationManager.IMPORTANCE_HIGH).apply {
51
- lockscreenVisibility = Notification.VISIBILITY_PUBLIC
52
- enableVibration(true)
53
- setSound(null, null) // We handle sound manually via MediaPlayer
54
- }
55
- notificationManager.createNotificationChannel(channel)
56
- }
57
-
58
- // 1. Full Screen Intent (To wake up the screen)
59
- val fullScreenIntent = Intent(context, AcceptCallActivity::class.java).apply {
60
- data.forEach { (k, v) -> putExtra(k, v) }
61
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_NO_USER_ACTION)
62
- }
63
- val fullScreenPendingIntent = PendingIntent.getActivity(context, 0, fullScreenIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
64
-
65
- // 2. Answer Action
66
- val answerIntent = Intent(context, CallActionReceiver::class.java).apply {
67
- action = "ACTION_ACCEPT"
68
- data.forEach { (k, v) -> putExtra(k, v) }
69
- }
70
- val answerPendingIntent = PendingIntent.getBroadcast(context, 1, answerIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
71
-
72
- // 3. Reject Action
73
- val rejectIntent = Intent(context, CallActionReceiver::class.java).apply {
74
- action = "ACTION_REJECT"
75
- data.forEach { (k, v) -> putExtra(k, v) }
76
- }
77
- val rejectPendingIntent = PendingIntent.getBroadcast(context, 2, rejectIntent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
78
-
79
- val builder = NotificationCompat.Builder(context, CHANNEL_ID)
80
- .setSmallIcon(context.applicationInfo.icon)
81
- .setContentTitle("Incoming Call")
82
- .setContentText(data["name"] ?: "Unknown Caller")
83
- .setPriority(NotificationCompat.PRIORITY_MAX)
84
- .setCategory(NotificationCompat.CATEGORY_CALL)
85
- .setAutoCancel(true)
86
- .setOngoing(true)
87
- .setFullScreenIntent(fullScreenPendingIntent, true)
88
- .addAction(0, "Answer", answerPendingIntent)
89
- .addAction(0, "Decline", rejectPendingIntent)
90
-
91
- notificationManager.notify(NOTIFICATION_ID, builder.build())
92
- }
93
- }
@@ -1,101 +0,0 @@
1
- package com.rnsnativecall
2
-
3
- import android.app.*
4
- import android.content.Context
5
- import android.content.Intent
6
- import android.media.AudioAttributes
7
- import android.media.MediaPlayer
8
- import android.media.RingtoneManager
9
- import android.os.Build
10
- import androidx.core.app.NotificationCompat
11
-
12
- object NativeCallManager {
13
- private var mediaPlayer: MediaPlayer? = null
14
- private const val CHANNEL_ID = "incoming_calls"
15
- private const val NOTIFICATION_ID = 101
16
-
17
- fun handleIncomingPush(context: Context, data: Map<String, String>) {
18
- startRingtone(context)
19
- showNotification(context, data)
20
- }
21
-
22
- private fun startRingtone(context: Context) {
23
- if (mediaPlayer != null) return
24
- try {
25
- val uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_RINGTONE)
26
- mediaPlayer = MediaPlayer().apply {
27
- setDataSource(context, uri)
28
- setAudioAttributes(AudioAttributes.Builder()
29
- .setUsage(AudioAttributes.USAGE_NOTIFICATION_RINGTONE)
30
- .setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
31
- .build())
32
- isLooping = true
33
- prepare()
34
- start()
35
- }
36
- } catch (e: Exception) { e.printStackTrace() }
37
- }
38
-
39
- fun stopRingtone() {
40
- mediaPlayer?.stop()
41
- mediaPlayer?.release()
42
- mediaPlayer = null
43
- }
44
-
45
- private fun showNotification(context: Context, data: Map<String, String>) {
46
- val notificationManager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
47
-
48
- if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
49
- val channel = NotificationChannel(CHANNEL_ID, "Calls", NotificationManager.IMPORTANCE_HIGH).apply {
50
- description = "Incoming call notifications"
51
- setSound(null, null)
52
- enableVibration(true)
53
- }
54
- notificationManager.createNotificationChannel(channel)
55
- }
56
-
57
- // 1. Full Screen Intent (Wakes up screen & goes to AcceptCallActivity)
58
- val fullScreenIntent = Intent(context, AcceptCallActivity::class.java).apply {
59
- data.forEach { (k, v) -> putExtra(k, v) }
60
- addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
61
- }
62
- val fullScreenPendingIntent = PendingIntent.getActivity(
63
- context, 0, fullScreenIntent,
64
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
65
- )
66
-
67
- // 2. Answer Button
68
- val answerIntent = Intent(context, CallActionReceiver::class.java).apply {
69
- action = "ACTION_ACCEPT"
70
- data.forEach { (k, v) -> putExtra(k, v) }
71
- }
72
- val answerPendingIntent = PendingIntent.getBroadcast(
73
- context, 1, answerIntent,
74
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
75
- )
76
-
77
- // 3. Reject Button
78
- val rejectIntent = Intent(context, CallActionReceiver::class.java).apply {
79
- action = "ACTION_REJECT"
80
- data.forEach { (k, v) -> putExtra(k, v) }
81
- }
82
- val rejectPendingIntent = PendingIntent.getBroadcast(
83
- context, 2, rejectIntent,
84
- PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
85
- )
86
-
87
- val builder = NotificationCompat.Builder(context, CHANNEL_ID)
88
- .setSmallIcon(android.R.drawable.ic_menu_call) // Replace with your app icon
89
- .setContentTitle("Incoming Call")
90
- .setContentText(data["name"] ?: "Raiidr User")
91
- .setPriority(NotificationCompat.PRIORITY_MAX)
92
- .setCategory(NotificationCompat.CATEGORY_CALL)
93
- .setFullScreenIntent(fullScreenPendingIntent, true)
94
- .setOngoing(true)
95
- .setAutoCancel(true)
96
- .addAction(0, "Answer", answerPendingIntent)
97
- .addAction(0, "Decline", rejectPendingIntent)
98
-
99
- notificationManager.notify(NOTIFICATION_ID, builder.build())
100
- }
101
- }