rns-nativecall 0.4.0 → 0.4.2
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/app.plugin.js +2 -9
- package/package.json +1 -1
- package/withCallNativeConfig.js +1 -0
- package/withCallPermissions.js +2 -1
- package/withNativeCallVoip.js +79 -162
package/app.plugin.js
CHANGED
|
@@ -1,13 +1,6 @@
|
|
|
1
1
|
///app.plugin.js
|
|
2
|
-
const { withPlugins } = require('@expo/config-plugins');
|
|
3
2
|
const withNativeCallVoip = require('./withNativeCallVoip');
|
|
4
|
-
const withCallNativeConfig = require('./withCallNativeConfig');
|
|
5
|
-
const withCallPermissions = require('./withCallPermissions');
|
|
6
3
|
|
|
7
|
-
module.exports = function (config
|
|
8
|
-
return
|
|
9
|
-
[withNativeCallVoip, props],
|
|
10
|
-
[withCallNativeConfig, props],
|
|
11
|
-
[withCallPermissions, props],
|
|
12
|
-
]);
|
|
4
|
+
module.exports = function (config) {
|
|
5
|
+
return withNativeCallVoip(config);
|
|
13
6
|
};
|
package/package.json
CHANGED
package/withCallNativeConfig.js
CHANGED
package/withCallPermissions.js
CHANGED
package/withNativeCallVoip.js
CHANGED
|
@@ -1,140 +1,47 @@
|
|
|
1
1
|
const { withAndroidManifest, withInfoPlist, withPlugins, withMainActivity } = require('@expo/config-plugins');
|
|
2
2
|
|
|
3
|
-
/** 1. ANDROID MAIN ACTIVITY MOD **/
|
|
4
|
-
// function withMainActivityDataFix(config) {
|
|
5
|
-
// return withMainActivity(config, (config) => {
|
|
6
|
-
// let contents = config.modResults.contents;
|
|
7
|
-
|
|
8
|
-
// // 1. Ensure necessary Imports are present
|
|
9
|
-
// if (!contents.includes('import android.content.Intent')) {
|
|
10
|
-
// contents = contents.replace(/package .*/, (match) => `${match}\n\nimport android.content.Intent`);
|
|
11
|
-
// }
|
|
12
|
-
// if (!contents.includes('import android.os.Bundle')) {
|
|
13
|
-
// contents = contents.replace(/package .*/, (match) => `${match}\n\nimport android.os.Bundle`);
|
|
14
|
-
// }
|
|
15
|
-
|
|
16
|
-
// // 2. Define the code blocks
|
|
17
|
-
// const onNewIntentCode = `
|
|
18
|
-
// override fun onNewIntent(intent: Intent) {
|
|
19
|
-
// super.onNewIntent(intent)
|
|
20
|
-
// setIntent(intent)
|
|
21
|
-
// }
|
|
22
|
-
// `;
|
|
23
|
-
|
|
24
|
-
// const onCreateCode = `
|
|
25
|
-
// override fun onCreate(savedInstanceState: Bundle?) {
|
|
26
|
-
// super.onCreate(savedInstanceState)
|
|
27
|
-
// // If woken up silently, move to back to prevent UI flicker
|
|
28
|
-
// if (intent.getBooleanExtra("background_wake", false)) {
|
|
29
|
-
// moveTaskToBack(true)
|
|
30
|
-
// }
|
|
31
|
-
// }
|
|
32
|
-
// `;
|
|
33
|
-
|
|
34
|
-
// // 3. Insert the codes before the last closing brace of the class
|
|
35
|
-
// if (!contents.includes('override fun onNewIntent')) {
|
|
36
|
-
// const lastBraceIndex = contents.lastIndexOf('}');
|
|
37
|
-
// contents = contents.slice(0, lastBraceIndex) + onNewIntentCode + contents.slice(lastBraceIndex);
|
|
38
|
-
// }
|
|
39
|
-
|
|
40
|
-
// if (!contents.includes('override fun onCreate')) {
|
|
41
|
-
// // Re-calculate lastBraceIndex because contents string has changed
|
|
42
|
-
// const lastBraceIndex = contents.lastIndexOf('}');
|
|
43
|
-
// contents = contents.slice(0, lastBraceIndex) + onCreateCode + contents.slice(lastBraceIndex);
|
|
44
|
-
// }
|
|
45
|
-
|
|
46
|
-
// config.modResults.contents = contents;
|
|
47
|
-
// return config;
|
|
48
|
-
// });
|
|
49
|
-
// }
|
|
50
|
-
|
|
51
3
|
/** 1. ANDROID MAIN ACTIVITY MOD **/
|
|
52
4
|
function withMainActivityDataFix(config) {
|
|
53
5
|
return withMainActivity(config, (config) => {
|
|
54
6
|
let contents = config.modResults.contents;
|
|
55
7
|
|
|
56
|
-
//
|
|
57
|
-
const
|
|
8
|
+
// 1. Add required imports
|
|
9
|
+
const imports = [
|
|
58
10
|
'import android.view.WindowManager',
|
|
59
11
|
'import android.os.Build',
|
|
60
|
-
'import android.os.Bundle'
|
|
12
|
+
'import android.os.Bundle',
|
|
13
|
+
'import android.content.Intent'
|
|
61
14
|
];
|
|
62
|
-
|
|
63
|
-
neededImports.forEach(imp => {
|
|
15
|
+
imports.forEach(imp => {
|
|
64
16
|
if (!contents.includes(imp)) {
|
|
65
17
|
contents = contents.replace(/package .*/, (match) => `${match}\n${imp}`);
|
|
66
18
|
}
|
|
67
19
|
});
|
|
68
20
|
|
|
69
|
-
//
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
// // This allows the Activity to appear over the lock screen when Answer is pressed
|
|
78
|
-
// if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
79
|
-
// setShowWhenLocked(true)
|
|
80
|
-
// setTurnScreenOn(true)
|
|
81
|
-
// } else {
|
|
82
|
-
// @Suppress("DEPRECATION")
|
|
83
|
-
// window.addFlags(
|
|
84
|
-
// WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
85
|
-
// WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
86
|
-
// WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
87
|
-
// )
|
|
88
|
-
// }
|
|
89
|
-
// }
|
|
90
|
-
override fun onCreate(savedInstanceState: Bundle?) {
|
|
91
|
-
setTheme(R.style.AppTheme)
|
|
92
|
-
super.onCreate(savedInstanceState)
|
|
93
|
-
|
|
94
|
-
// Only wake the screen/bypass lock if we are coming from a notification interaction
|
|
95
|
-
// Otherwise, let the notification pill handle the UI.
|
|
96
|
-
if (intent?.action?.startsWith("ACTION_SHOW_UI") == true) {
|
|
97
|
-
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
98
|
-
setShowWhenLocked(true)
|
|
99
|
-
setTurnScreenOn(true)
|
|
100
|
-
} else {
|
|
101
|
-
@Suppress("DEPRECATION")
|
|
102
|
-
window.addFlags(
|
|
103
|
-
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
|
|
104
|
-
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
|
|
105
|
-
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
|
|
106
|
-
)
|
|
107
|
-
}
|
|
21
|
+
// 2. Add the Lockscreen / Wake logic inside onCreate
|
|
22
|
+
const wakeLogic = `super.onCreate(savedInstanceState)
|
|
23
|
+
if (intent?.getBooleanExtra("navigatingToCall", false) == true) {
|
|
24
|
+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
|
|
25
|
+
setShowWhenLocked(true)
|
|
26
|
+
setTurnScreenOn(true)
|
|
27
|
+
} else {
|
|
28
|
+
window.addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON)
|
|
108
29
|
}
|
|
109
|
-
}
|
|
110
|
-
`;
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
30
|
+
}`;
|
|
114
31
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
if (contents.match(onCreateRegex)) {
|
|
118
|
-
contents = contents.replace(onCreateRegex, editedOnCreate);
|
|
32
|
+
if (!contents.includes('setShowWhenLocked')) {
|
|
33
|
+
contents = contents.replace(/super\.onCreate\(.*\)/, wakeLogic);
|
|
119
34
|
}
|
|
120
35
|
|
|
121
|
-
//
|
|
122
|
-
// Removing the "object :" and the empty trailing block "{})" to match your edited version
|
|
123
|
-
contents = contents.replace(
|
|
124
|
-
/return ReactActivityDelegateWrapper\([\s\S]*?object : (DefaultReactActivityDelegate\([\s\S]*?\))\{\}\)/,
|
|
125
|
-
'return ReactActivityDelegateWrapper($1)'
|
|
126
|
-
);
|
|
127
|
-
|
|
128
|
-
// --- 4. Ensure onNewIntent exists ---
|
|
129
|
-
const onNewIntentCode = `
|
|
130
|
-
override fun onNewIntent(intent: Intent) {
|
|
131
|
-
super.onNewIntent(intent)
|
|
132
|
-
setIntent(intent)
|
|
133
|
-
}`;
|
|
134
|
-
|
|
36
|
+
// 3. Ensure onNewIntent is present
|
|
135
37
|
if (!contents.includes('override fun onNewIntent')) {
|
|
38
|
+
const onNewIntentCode = `
|
|
39
|
+
override fun onNewIntent(intent: Intent) {
|
|
40
|
+
super.onNewIntent(intent)
|
|
41
|
+
setIntent(intent)
|
|
42
|
+
}\n`;
|
|
136
43
|
const lastBraceIndex = contents.lastIndexOf('}');
|
|
137
|
-
contents = contents.slice(0, lastBraceIndex) + onNewIntentCode +
|
|
44
|
+
contents = contents.slice(0, lastBraceIndex) + onNewIntentCode + contents.slice(lastBraceIndex);
|
|
138
45
|
}
|
|
139
46
|
|
|
140
47
|
config.modResults.contents = contents;
|
|
@@ -145,73 +52,83 @@ function withMainActivityDataFix(config) {
|
|
|
145
52
|
/** 2. ANDROID MANIFEST CONFIG **/
|
|
146
53
|
function withAndroidConfig(config) {
|
|
147
54
|
return withAndroidManifest(config, (config) => {
|
|
148
|
-
const
|
|
149
|
-
const
|
|
55
|
+
const androidManifest = config.modResults.manifest;
|
|
56
|
+
const mainApplication = androidManifest.application[0];
|
|
57
|
+
|
|
58
|
+
// 1. Configure MainActivity flags in Manifest
|
|
59
|
+
const mainActivity = mainApplication.activity.find(a => a.$["android:name"] === ".MainActivity");
|
|
60
|
+
if (mainActivity) {
|
|
61
|
+
mainActivity.$["android:showWhenLocked"] = "true";
|
|
62
|
+
mainActivity.$["android:turnScreenOn"] = "true";
|
|
63
|
+
}
|
|
150
64
|
|
|
151
|
-
//
|
|
65
|
+
// 2. Unified Permissions
|
|
152
66
|
const permissions = [
|
|
153
67
|
'android.permission.USE_FULL_SCREEN_INTENT',
|
|
154
68
|
'android.permission.VIBRATE',
|
|
155
69
|
'android.permission.FOREGROUND_SERVICE',
|
|
156
|
-
'android.permission.FOREGROUND_SERVICE_PHONE_CALL',
|
|
70
|
+
'android.permission.FOREGROUND_SERVICE_PHONE_CALL',
|
|
157
71
|
'android.permission.POST_NOTIFICATIONS',
|
|
158
72
|
'android.permission.WAKE_LOCK',
|
|
159
73
|
'android.permission.DISABLE_KEYGUARD',
|
|
160
|
-
'android.permission.RECEIVE_BOOT_COMPLETED'
|
|
74
|
+
'android.permission.RECEIVE_BOOT_COMPLETED'
|
|
161
75
|
];
|
|
162
76
|
|
|
163
|
-
|
|
77
|
+
androidManifest['uses-permission'] = androidManifest['uses-permission'] || [];
|
|
164
78
|
permissions.forEach((perm) => {
|
|
165
|
-
if (!
|
|
166
|
-
|
|
79
|
+
if (!androidManifest['uses-permission'].some((p) => p.$['android:name'] === perm)) {
|
|
80
|
+
androidManifest['uses-permission'].push({ $: { 'android:name': perm } });
|
|
167
81
|
}
|
|
168
82
|
});
|
|
169
83
|
|
|
170
|
-
//
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
// 3. Service Setup (CRITICAL UPDATES FOR ANDROID 14)
|
|
175
|
-
application.service = application.service || [];
|
|
176
|
-
|
|
177
|
-
// Add Firebase Messaging Service
|
|
178
|
-
const firebaseServiceName = 'com.rnsnativecall.CallMessagingService';
|
|
179
|
-
if (!application.service.some(s => s.$['android:name'] === firebaseServiceName)) {
|
|
180
|
-
application.service.push({
|
|
84
|
+
// 3. AcceptCallActivity Registration
|
|
85
|
+
mainApplication.activity = mainApplication.activity || [];
|
|
86
|
+
if (!mainApplication.activity.some(a => a.$['android:name'] === 'com.rnsnativecall.AcceptCallActivity')) {
|
|
87
|
+
mainApplication.activity.push({
|
|
181
88
|
$: {
|
|
182
|
-
'android:name':
|
|
89
|
+
'android:name': 'com.rnsnativecall.AcceptCallActivity',
|
|
90
|
+
'android:theme': '@android:style/Theme.Translucent.NoTitleBar',
|
|
183
91
|
'android:exported': 'false',
|
|
184
|
-
|
|
185
|
-
'android:
|
|
186
|
-
}
|
|
187
|
-
'intent-filter': [{ action: [{ $: { 'android:name': 'com.google.firebase.MESSAGING_EVENT' } }] }]
|
|
92
|
+
'android:showWhenLocked': 'true',
|
|
93
|
+
'android:turnScreenOn': 'true'
|
|
94
|
+
}
|
|
188
95
|
});
|
|
189
96
|
}
|
|
190
97
|
|
|
191
|
-
//
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
98
|
+
// 4. Service Setup
|
|
99
|
+
mainApplication.service = mainApplication.service || [];
|
|
100
|
+
|
|
101
|
+
const services = [
|
|
102
|
+
{
|
|
103
|
+
name: 'com.rnsnativecall.CallMessagingService',
|
|
104
|
+
intentFilter: 'com.google.firebase.MESSAGING_EVENT'
|
|
105
|
+
},
|
|
106
|
+
{
|
|
107
|
+
name: 'com.rnsnativecall.CallHeadlessTask'
|
|
108
|
+
}
|
|
109
|
+
];
|
|
110
|
+
|
|
111
|
+
services.forEach(svc => {
|
|
112
|
+
if (!mainApplication.service.some(s => s.$['android:name'] === svc.name)) {
|
|
113
|
+
const serviceEntry = {
|
|
114
|
+
$: {
|
|
115
|
+
'android:name': svc.name,
|
|
116
|
+
'android:exported': 'false',
|
|
117
|
+
'android:foregroundServiceType': 'phoneCall'
|
|
118
|
+
}
|
|
119
|
+
};
|
|
120
|
+
if (svc.intentFilter) {
|
|
121
|
+
serviceEntry['intent-filter'] = [{ action: [{ $: { 'android:name': svc.intentFilter } }] }];
|
|
200
122
|
}
|
|
201
|
-
|
|
202
|
-
|
|
123
|
+
mainApplication.service.push(serviceEntry);
|
|
124
|
+
}
|
|
125
|
+
});
|
|
203
126
|
|
|
204
|
-
//
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
$: { 'android:name': receiverName, 'android:exported': 'false' },
|
|
210
|
-
'intent-filter': [{
|
|
211
|
-
action: [
|
|
212
|
-
{ $: { 'android:name': 'android.intent.action.BOOT_COMPLETED' } }
|
|
213
|
-
]
|
|
214
|
-
}]
|
|
127
|
+
// 5. Receiver Setup
|
|
128
|
+
mainApplication.receiver = mainApplication.receiver || [];
|
|
129
|
+
if (!mainApplication.receiver.some(r => r.$['android:name'] === 'com.rnsnativecall.CallActionReceiver')) {
|
|
130
|
+
mainApplication.receiver.push({
|
|
131
|
+
$: { 'android:name': 'com.rnsnativecall.CallActionReceiver', 'android:exported': 'false' }
|
|
215
132
|
});
|
|
216
133
|
}
|
|
217
134
|
|