rns-nativecall 0.2.7 → 0.3.0
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/build.gradle
CHANGED
|
@@ -35,12 +35,12 @@ android {
|
|
|
35
35
|
}
|
|
36
36
|
|
|
37
37
|
compileOptions {
|
|
38
|
-
sourceCompatibility JavaVersion.
|
|
39
|
-
targetCompatibility JavaVersion.
|
|
38
|
+
sourceCompatibility JavaVersion.VERSION_17
|
|
39
|
+
targetCompatibility JavaVersion.VERSION_17
|
|
40
40
|
}
|
|
41
41
|
|
|
42
42
|
kotlinOptions {
|
|
43
|
-
jvmTarget = '1.8
|
|
43
|
+
jvmTarget = '17' // Changed from 1.8
|
|
44
44
|
}
|
|
45
45
|
|
|
46
46
|
// lintOptions is deprecated in newer AGP, using lint instead
|
package/package.json
CHANGED
package/withNativeCallVoip.js
CHANGED
|
@@ -5,12 +5,10 @@ function withMainActivityDataFix(config) {
|
|
|
5
5
|
return withMainActivity(config, (config) => {
|
|
6
6
|
let contents = config.modResults.contents;
|
|
7
7
|
|
|
8
|
-
// Ensure Intent import exists
|
|
9
8
|
if (!contents.includes('import android.content.Intent')) {
|
|
10
9
|
contents = contents.replace(/package .*/, (match) => `${match}\n\nimport android.content.Intent`);
|
|
11
10
|
}
|
|
12
11
|
|
|
13
|
-
// Add onNewIntent to catch data when app is open
|
|
14
12
|
const onNewIntentCode = `
|
|
15
13
|
override fun onNewIntent(intent: Intent) {
|
|
16
14
|
super.onNewIntent(intent)
|
|
@@ -34,15 +32,15 @@ function withAndroidConfig(config) {
|
|
|
34
32
|
const manifest = config.modResults;
|
|
35
33
|
const application = manifest.manifest.application[0];
|
|
36
34
|
|
|
37
|
-
// 1.
|
|
35
|
+
// 1. Unified Permissions
|
|
38
36
|
const permissions = [
|
|
39
37
|
'android.permission.USE_FULL_SCREEN_INTENT',
|
|
40
38
|
'android.permission.VIBRATE',
|
|
41
39
|
'android.permission.FOREGROUND_SERVICE',
|
|
42
|
-
'android.permission.FOREGROUND_SERVICE_PHONE_CALL',
|
|
43
|
-
'android.permission.POST_NOTIFICATIONS',
|
|
44
|
-
'android.permission.WAKE_LOCK',
|
|
45
|
-
'android.permission.DISABLE_KEYGUARD'
|
|
40
|
+
'android.permission.FOREGROUND_SERVICE_PHONE_CALL',
|
|
41
|
+
'android.permission.POST_NOTIFICATIONS',
|
|
42
|
+
'android.permission.WAKE_LOCK',
|
|
43
|
+
'android.permission.DISABLE_KEYGUARD'
|
|
46
44
|
];
|
|
47
45
|
|
|
48
46
|
manifest.manifest['uses-permission'] = manifest.manifest['uses-permission'] || [];
|
|
@@ -52,51 +50,54 @@ function withAndroidConfig(config) {
|
|
|
52
50
|
}
|
|
53
51
|
});
|
|
54
52
|
|
|
55
|
-
// 2.
|
|
56
|
-
// Added showWhenLocked and turnScreenOn for the "Gate" logic
|
|
53
|
+
// 2. Activity Cleanup & Setup
|
|
57
54
|
application.activity = application.activity || [];
|
|
58
|
-
const acceptActivityName = 'com.rnsnativecall.AcceptCallActivity';
|
|
59
55
|
|
|
60
|
-
// Remove old
|
|
61
|
-
application.activity = application.activity.filter(a =>
|
|
56
|
+
// Remove old/redundant activities
|
|
57
|
+
application.activity = application.activity.filter(a =>
|
|
58
|
+
a.$['android:name'] !== 'com.rnsnativecall.IncomingCallActivity' &&
|
|
59
|
+
a.$['android:name'] !== 'com.rnsnativecall.AcceptCallActivity'
|
|
60
|
+
);
|
|
62
61
|
|
|
62
|
+
// Add the specific AcceptCallActivity (Trampoline)
|
|
63
63
|
application.activity.push({
|
|
64
64
|
$: {
|
|
65
|
-
'android:name':
|
|
65
|
+
'android:name': 'com.rnsnativecall.AcceptCallActivity',
|
|
66
66
|
'android:theme': '@android:style/Theme.Translucent.NoTitleBar',
|
|
67
67
|
'android:excludeFromRecents': 'true',
|
|
68
68
|
'android:noHistory': 'true',
|
|
69
69
|
'android:exported': 'false',
|
|
70
70
|
'android:launchMode': 'singleInstance',
|
|
71
|
-
'android:showWhenLocked': 'true',
|
|
72
|
-
'android:turnScreenOn': 'true'
|
|
71
|
+
'android:showWhenLocked': 'true',
|
|
72
|
+
'android:turnScreenOn': 'true'
|
|
73
73
|
}
|
|
74
74
|
});
|
|
75
75
|
|
|
76
|
-
// 3.
|
|
76
|
+
// 3. Service Cleanup & Setup (Firebase only)
|
|
77
77
|
application.service = application.service || [];
|
|
78
|
-
// Removed MyConnectionService as you are no longer using Telecom
|
|
79
|
-
const services = [
|
|
80
|
-
{ name: 'com.rnsnativecall.CallMessagingService', action: 'com.google.firebase.MESSAGING_EVENT' }
|
|
81
|
-
];
|
|
82
78
|
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
79
|
+
// Explicitly remove Telecom Service
|
|
80
|
+
application.service = application.service.filter(
|
|
81
|
+
s => s.$['android:name'] !== 'com.rnsnativecall.MyConnectionService'
|
|
82
|
+
);
|
|
83
|
+
|
|
84
|
+
const firebaseServiceName = 'com.rnsnativecall.CallMessagingService';
|
|
85
|
+
if (!application.service.some(s => s.$['android:name'] === firebaseServiceName)) {
|
|
86
|
+
application.service.push({
|
|
87
|
+
$: {
|
|
88
|
+
'android:name': firebaseServiceName,
|
|
89
|
+
'android:exported': 'false'
|
|
90
|
+
},
|
|
91
|
+
'intent-filter': [{ action: [{ $: { 'android:name': 'com.google.firebase.MESSAGING_EVENT' } }] }]
|
|
92
|
+
});
|
|
93
|
+
}
|
|
94
94
|
|
|
95
|
-
// 4.
|
|
95
|
+
// 4. Receiver Setup
|
|
96
96
|
application.receiver = application.receiver || [];
|
|
97
|
-
|
|
97
|
+
const receiverName = 'com.rnsnativecall.CallActionReceiver';
|
|
98
|
+
if (!application.receiver.some(r => r.$['android:name'] === receiverName)) {
|
|
98
99
|
application.receiver.push({
|
|
99
|
-
$: { 'android:name':
|
|
100
|
+
$: { 'android:name': receiverName, 'android:exported': 'false' }
|
|
100
101
|
});
|
|
101
102
|
}
|
|
102
103
|
|
|
@@ -109,7 +110,9 @@ function withIosConfig(config) {
|
|
|
109
110
|
return withInfoPlist(config, (config) => {
|
|
110
111
|
const infoPlist = config.modResults;
|
|
111
112
|
if (!infoPlist.UIBackgroundModes) infoPlist.UIBackgroundModes = [];
|
|
112
|
-
['voip', 'audio'].forEach(mode => {
|
|
113
|
+
['voip', 'audio'].forEach(mode => {
|
|
114
|
+
if (!infoPlist.UIBackgroundModes.includes(mode)) infoPlist.UIBackgroundModes.push(mode);
|
|
115
|
+
});
|
|
113
116
|
return config;
|
|
114
117
|
});
|
|
115
118
|
}
|
|
@@ -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
|
-
}
|