@qusaieilouti99/call-manager 0.1.185 → 0.1.187

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,5 +1,6 @@
1
1
  package com.margelo.nitro.qusaieilouti99.callmanager
2
2
 
3
+ import android.app.Activity
3
4
  import android.app.ActivityManager
4
5
  import android.app.Notification
5
6
  import android.app.NotificationChannel
@@ -38,6 +39,7 @@ import java.util.concurrent.CopyOnWriteArrayList
38
39
  import java.util.concurrent.atomic.AtomicBoolean
39
40
  import android.app.KeyguardManager
40
41
  import java.util.UUID
42
+ import android.provider.Settings // Import for Settings.canDrawOverlays and ACTION_MANAGE_OVERLAY_PERMISSION
41
43
 
42
44
  /**
43
45
  * Core call‐management engine. Manages self-managed telecom calls,
@@ -252,7 +254,7 @@ object CallEngine {
252
254
 
253
255
  val activeOrHeldCall = activeCalls.values.find {
254
256
  it.state == CallState.ACTIVE || it.state == CallState.HELD
255
- }
257
+ )
256
258
  if (activeOrHeldCall != null && !canMakeMultipleCalls) {
257
259
  Log.d(TAG, "Active/Held call exists when receiving incoming call. Auto-rejecting: $callId")
258
260
  rejectIncomingCallCollision(callId, "Another call is already active or held")
@@ -1042,6 +1044,13 @@ object CallEngine {
1042
1044
  putExtra("LOCK_SCREEN_MODE", true)
1043
1045
  }
1044
1046
 
1047
+ // ONLY CHECK permission, DO NOT REQUEST HERE
1048
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M && !checkOverlayPermissionGranted(context)) {
1049
+ Log.w(TAG, "Cannot show CallActivity overlay without SYSTEM_ALERT_WINDOW permission. Falling back to standard notification.")
1050
+ showStandardNotification(context, callId, callerName, callType, callerPicUrl)
1051
+ return
1052
+ }
1053
+
1045
1054
  try {
1046
1055
  val powerManager = context.getSystemService(Context.POWER_SERVICE) as PowerManager
1047
1056
  val wakeLock = powerManager.newWakeLock(
@@ -1052,7 +1061,7 @@ object CallEngine {
1052
1061
  context.startActivity(overlayIntent)
1053
1062
  Log.d(TAG, "Successfully launched CallActivity overlay")
1054
1063
  } catch (e: Exception) {
1055
- Log.e(TAG, "Overlay failed, falling back to standard notification: ${e.message}")
1064
+ Log.e(TAG, "Overlay failed (after permission check), falling back to standard notification: ${e.message}")
1056
1065
  showStandardNotification(context, callId, callerName, callType, callerPicUrl)
1057
1066
  }
1058
1067
  }
@@ -1362,4 +1371,51 @@ object CallEngine {
1362
1371
  availableCallEndpoints = emptyList()
1363
1372
  wasManuallySetAudioRoute = false
1364
1373
  }
1374
+
1375
+ // --- Refactored SYSTEM_ALERT_WINDOW permission functions ---
1376
+
1377
+ /**
1378
+ * Checks if the SYSTEM_ALERT_WINDOW permission (Draw Over Other Apps) is granted.
1379
+ * This function only checks; it does not launch any UI for permission request.
1380
+ * @param context The application context.
1381
+ * @return True if the permission is granted or not required (API < 23), false otherwise.
1382
+ */
1383
+ fun checkOverlayPermissionGranted(context: Context): Boolean {
1384
+ return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
1385
+ Settings.canDrawOverlays(context)
1386
+ } else {
1387
+ true // Permissions granted at install time for older Android versions
1388
+ }
1389
+ }
1390
+
1391
+ /**
1392
+ * Launches the system settings screen where the user can grant the SYSTEM_ALERT_WINDOW permission.
1393
+ * This function should be called after your app has explained to the user why the permission is needed.
1394
+ * @param context The context to start the activity. Ideally, an Activity context is used,
1395
+ * but if an Application context is used, FLAG_ACTIVITY_NEW_TASK will be added.
1396
+ * @return True if the settings activity was successfully launched, false otherwise.
1397
+ */
1398
+ fun launchOverlayPermissionSettings(context: Context): Boolean {
1399
+ if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
1400
+ Log.d(TAG, "SYSTEM_ALERT_WINDOW permission automatically granted on API < 23. No settings to launch.")
1401
+ return true
1402
+ }
1403
+
1404
+ Log.d(TAG, "Launching SYSTEM_ALERT_WINDOW permission settings.")
1405
+ try {
1406
+ val intent = Intent(
1407
+ Settings.ACTION_MANAGE_OVERLAY_PERMISSION,
1408
+ Uri.parse("package:" + context.packageName)
1409
+ )
1410
+ if (context !is Activity) {
1411
+ intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
1412
+ Log.d(TAG, "Added FLAG_ACTIVITY_NEW_TASK as context is not an Activity.")
1413
+ }
1414
+ context.startActivity(intent)
1415
+ return true // Successfully launched settings
1416
+ } catch (e: Exception) {
1417
+ Log.e(TAG, "Failed to launch SYSTEM_ALERT_WINDOW permission settings: ${e.message}", e)
1418
+ return false // Failed to launch
1419
+ }
1420
+ }
1365
1421
  }
@@ -123,4 +123,20 @@ class CallManager : HybridCallManagerSpec() {
123
123
  metadata
124
124
  )
125
125
  }
126
+
127
+ // --- New Hybrid Method for SYSTEM_ALERT_WINDOW permission CHECK ---
128
+ override fun hasOverlayPermissionAndroid(): Boolean {
129
+ Log.d(TAG, "hasOverlayPermissionAndroid requested (check only)")
130
+ ensureInitialized()
131
+ val context = requireNotNull(CallEngine.getContext()) { "CallEngine must be initialized with context" }
132
+ return CallEngine.checkOverlayPermissionGranted(context)
133
+ }
134
+
135
+ // --- Repurposed Hybrid Method for SYSTEM_ALERT_WINDOW permission LAUNCH ---
136
+ override fun requestOverlayPermissionAndroid(): Boolean {
137
+ Log.d(TAG, "requestOverlayPermissionAndroid requested (launch settings)")
138
+ ensureInitialized()
139
+ val context = requireNotNull(CallEngine.getContext()) { "CallEngine must be initialized with context" }
140
+ return CallEngine.launchOverlayPermissionSettings(context)
141
+ }
126
142
  }
@@ -25,6 +25,9 @@ class CallEngine {
25
25
  // Track video calls that need speaker activation
26
26
  private var videoCallsNeedingSpeaker: Set<String> = []
27
27
 
28
+ // NEW: Track calls being answered via the startCall method
29
+ private var answeringIncomingViaStartCall: Set<String> = [] // NEW
30
+
28
31
  private init() {
29
32
  logger.info("CallEngine singleton created")
30
33
  }
@@ -200,6 +203,30 @@ class CallEngine {
200
203
  metadata: String? = nil)
201
204
  {
202
205
  logger.info("startCall (join ongoing): \(callId), type=\(callType)")
206
+
207
+ // --- MODIFICATION START ---
208
+ // Check if the callId corresponds to an existing incoming call
209
+ if let existingCallInfo = activeCalls[callId], existingCallInfo.state == .incoming {
210
+ logger.info("startCall: Detected attempt to answer existing incoming call \(callId). Redirecting to answer flow.")
211
+
212
+ // Update metadata for the existing incoming call if provided
213
+ if let m = metadata {
214
+ callMetadata[callId] = m
215
+ logger.info("metadata updated for incoming call \(callId)")
216
+ }
217
+
218
+ // Mark this call as one being answered via startCall
219
+ answeringIncomingViaStartCall.insert(callId)
220
+
221
+ // Trigger the CallKit answer action. This will lead to `callKitManager(_:didAnswerCall:)` being called.
222
+ callKitManager.answerCall(callId: callId)
223
+
224
+ // Return early as we've redirected to the answer flow.
225
+ return
226
+ }
227
+ // --- MODIFICATION END ---
228
+
229
+
203
230
  if let m = metadata {
204
231
  callMetadata[callId] = m
205
232
  logger.info("metadata cached for \(callId)")
@@ -447,7 +474,16 @@ class CallEngine {
447
474
 
448
475
  extension CallEngine: CallKitManagerDelegate {
449
476
  func callKitManager(_ manager: CallKitManager, didAnswerCall callId: String) {
450
- coreCallAnswered(callId: callId, isLocalAnswer: true)
477
+ // MODIFICATION START
478
+ if answeringIncomingViaStartCall.contains(callId) {
479
+ logger.info("📞 CallKit answered: \(callId). This was initiated by startCall, treating as non-local answer.")
480
+ answeringIncomingViaStartCall.remove(callId)
481
+ coreCallAnswered(callId: callId, isLocalAnswer: false) // isLocalAnswer: false for OUTGOING_CALL_ANSWERED
482
+ } else {
483
+ logger.info("📞 CallKit answered: \(callId). Standard local answer.")
484
+ coreCallAnswered(callId: callId, isLocalAnswer: true) // isLocalAnswer: true for CALL_ANSWERED
485
+ }
486
+ // MODIFICATION END
451
487
  }
452
488
 
453
489
  func callKitManager(_ manager: CallKitManager, didEndCall callId: String) {
@@ -153,4 +153,14 @@ public class CallManager: HybridCallManagerSpec {
153
153
  logger.info("🎯 hasActiveCall ▶ js → native")
154
154
  return CallEngine.shared.hasActiveCalls()
155
155
  }
156
+
157
+ public func requestOverlayPermissionAndroid() throws -> Bool {
158
+ logger.info("🎯 requestOverlayPermissionAndroid ▶ js → native")
159
+ return true
160
+ }
161
+
162
+ public func hasOverlayPermissionAndroid() throws -> Bool {
163
+ logger.info("🎯 hasOverlayPermissionAndroid ▶ js → native")
164
+ return true
165
+ }
156
166
  }
@@ -1 +1 @@
1
- {"version":3,"names":["NitroModules","CallManagerHybridObject","createHybridObject"],"sourceRoot":"../../src","sources":["CallManager.nitro.ts"],"mappings":";;AAAA;AACA,SAA4BA,YAAY,QAAQ,4BAA4B;;AAG5E;;AAKA;;AAyDA,OAAO,MAAMC,uBAAuB,GAClCD,YAAY,CAACE,kBAAkB,CAAc,aAAa,CAAC","ignoreList":[]}
1
+ {"version":3,"names":["NitroModules","CallManagerHybridObject","createHybridObject"],"sourceRoot":"../../src","sources":["CallManager.nitro.ts"],"mappings":";;AAAA;AACA,SAA4BA,YAAY,QAAQ,4BAA4B;;AAG5E;;AAKA;;AA4DA,OAAO,MAAMC,uBAAuB,GAClCD,YAAY,CAACE,kBAAkB,CAAc,aAAa,CAAC","ignoreList":[]}
@@ -27,6 +27,8 @@ export interface CallManager extends HybridObject<{
27
27
  addListener(listener: (event: CallEventType, payload: string) => void): () => void;
28
28
  registerVoIPTokenListener(listener: (payload: string) => void): () => void;
29
29
  hasActiveCall(): boolean;
30
+ requestOverlayPermissionAndroid(): boolean;
31
+ hasOverlayPermissionAndroid(): boolean;
30
32
  }
31
33
  export declare const CallManagerHybridObject: CallManager;
32
34
  //# sourceMappingURL=CallManager.nitro.d.ts.map
@@ -1 +1 @@
1
- {"version":3,"file":"CallManager.nitro.d.ts","sourceRoot":"","sources":["../../../src/CallManager.nitro.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;IAEzD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,IAAI,IAAI,CAAC;IACxB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAGnC,eAAe,IAAI,eAAe,CAAC;IACnC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAE1C,WAAW,IAAI,IAAI,CAAC;IACpB,iBAAiB,CACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAAC;IACR,SAAS,CACP,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAAC;IACR,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/C,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAGvE,kBAAkB,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAAC;IAGR,WAAW,CAET,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACxD,MAAM,IAAI,CAAC;IAEd,yBAAyB,CAEvB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAClC,MAAM,IAAI,CAAC;IAEd,aAAa,IAAI,OAAO,CAAC;CAC1B;AAED,eAAO,MAAM,uBAAuB,aACyB,CAAC"}
1
+ {"version":3,"file":"CallManager.nitro.d.ts","sourceRoot":"","sources":["../../../src/CallManager.nitro.ts"],"names":[],"mappings":"AACA,OAAO,EAAE,KAAK,YAAY,EAAgB,MAAM,4BAA4B,CAAC;AAC7E,OAAO,KAAK,EAAE,aAAa,EAAE,MAAM,iBAAiB,CAAC;AAGrD,MAAM,WAAW,YAAY;IAC3B,KAAK,EAAE,MAAM,CAAC;CACf;AAGD,MAAM,WAAW,eAAe;IAC9B,OAAO,EAAE,YAAY,EAAE,CAAC;IACxB,YAAY,EAAE,MAAM,CAAC;CACtB;AAED,MAAM,WAAW,WACf,SAAQ,YAAY,CAAC;IAAE,GAAG,EAAE,OAAO,CAAC;IAAC,OAAO,EAAE,QAAQ,CAAA;CAAE,CAAC;IAEzD,OAAO,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAC9B,eAAe,IAAI,IAAI,CAAC;IACxB,YAAY,CAAC,MAAM,EAAE,MAAM,GAAG,IAAI,CAAC;IAGnC,eAAe,IAAI,eAAe,CAAC;IACnC,aAAa,CAAC,KAAK,EAAE,MAAM,GAAG,IAAI,CAAC;IACnC,eAAe,CAAC,SAAS,EAAE,OAAO,GAAG,IAAI,CAAC;IAE1C,WAAW,IAAI,IAAI,CAAC;IACpB,iBAAiB,CACf,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAAC;IACR,SAAS,CACP,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAAC;IACR,SAAS,CAAC,MAAM,EAAE,MAAM,EAAE,MAAM,EAAE,OAAO,GAAG,IAAI,CAAC;IACjD,QAAQ,CAAC,MAAM,EAAE,MAAM,EAAE,KAAK,EAAE,OAAO,GAAG,IAAI,CAAC;IAC/C,4BAA4B,CAAC,MAAM,EAAE,MAAM,EAAE,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAGvE,kBAAkB,CAChB,MAAM,EAAE,MAAM,EACd,QAAQ,EAAE,MAAM,EAChB,UAAU,EAAE,MAAM,EAClB,QAAQ,CAAC,EAAE,MAAM,GAChB,IAAI,CAAC;IAGR,WAAW,CAET,QAAQ,EAAE,CAAC,KAAK,EAAE,aAAa,EAAE,OAAO,EAAE,MAAM,KAAK,IAAI,GACxD,MAAM,IAAI,CAAC;IAEd,yBAAyB,CAEvB,QAAQ,EAAE,CAAC,OAAO,EAAE,MAAM,KAAK,IAAI,GAClC,MAAM,IAAI,CAAC;IAEd,aAAa,IAAI,OAAO,CAAC;IAEzB,+BAA+B,IAAI,OAAO,CAAC;IAC3C,2BAA2B,IAAI,OAAO,CAAC;CACxC;AAED,eAAO,MAAM,uBAAuB,aACyB,CAAC"}
@@ -142,5 +142,15 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
142
142
  auto __result = method(_javaPart);
143
143
  return static_cast<bool>(__result);
144
144
  }
145
+ bool JHybridCallManagerSpec::requestOverlayPermissionAndroid() {
146
+ static const auto method = javaClassStatic()->getMethod<jboolean()>("requestOverlayPermissionAndroid");
147
+ auto __result = method(_javaPart);
148
+ return static_cast<bool>(__result);
149
+ }
150
+ bool JHybridCallManagerSpec::hasOverlayPermissionAndroid() {
151
+ static const auto method = javaClassStatic()->getMethod<jboolean()>("hasOverlayPermissionAndroid");
152
+ auto __result = method(_javaPart);
153
+ return static_cast<bool>(__result);
154
+ }
145
155
 
146
156
  } // namespace margelo::nitro::qusaieilouti99_callmanager
@@ -68,6 +68,8 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
68
68
  std::function<void()> addListener(const std::function<void(CallEventType /* event */, const std::string& /* payload */)>& listener) override;
69
69
  std::function<void()> registerVoIPTokenListener(const std::function<void(const std::string& /* payload */)>& listener) override;
70
70
  bool hasActiveCall() override;
71
+ bool requestOverlayPermissionAndroid() override;
72
+ bool hasOverlayPermissionAndroid() override;
71
73
 
72
74
  private:
73
75
  friend HybridBase;
@@ -113,6 +113,14 @@ abstract class HybridCallManagerSpec: HybridObject() {
113
113
  @DoNotStrip
114
114
  @Keep
115
115
  abstract fun hasActiveCall(): Boolean
116
+
117
+ @DoNotStrip
118
+ @Keep
119
+ abstract fun requestOverlayPermissionAndroid(): Boolean
120
+
121
+ @DoNotStrip
122
+ @Keep
123
+ abstract fun hasOverlayPermissionAndroid(): Boolean
116
124
 
117
125
  private external fun initHybrid(): HybridData
118
126
 
@@ -172,6 +172,22 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
172
172
  auto __value = std::move(__result.value());
173
173
  return __value;
174
174
  }
175
+ inline bool requestOverlayPermissionAndroid() override {
176
+ auto __result = _swiftPart.requestOverlayPermissionAndroid();
177
+ if (__result.hasError()) [[unlikely]] {
178
+ std::rethrow_exception(__result.error());
179
+ }
180
+ auto __value = std::move(__result.value());
181
+ return __value;
182
+ }
183
+ inline bool hasOverlayPermissionAndroid() override {
184
+ auto __result = _swiftPart.hasOverlayPermissionAndroid();
185
+ if (__result.hasError()) [[unlikely]] {
186
+ std::rethrow_exception(__result.error());
187
+ }
188
+ auto __value = std::move(__result.value());
189
+ return __value;
190
+ }
175
191
 
176
192
  private:
177
193
  CallManager::HybridCallManagerSpec_cxx _swiftPart;
@@ -30,6 +30,8 @@ public protocol HybridCallManagerSpec_protocol: HybridObject {
30
30
  func addListener(listener: @escaping (_ event: CallEventType, _ payload: String) -> Void) throws -> () -> Void
31
31
  func registerVoIPTokenListener(listener: @escaping (_ payload: String) -> Void) throws -> () -> Void
32
32
  func hasActiveCall() throws -> Bool
33
+ func requestOverlayPermissionAndroid() throws -> Bool
34
+ func hasOverlayPermissionAndroid() throws -> Bool
33
35
  }
34
36
 
35
37
  /// See ``HybridCallManagerSpec``
@@ -322,4 +322,28 @@ open class HybridCallManagerSpec_cxx {
322
322
  return bridge.create_Result_bool_(__exceptionPtr)
323
323
  }
324
324
  }
325
+
326
+ @inline(__always)
327
+ public final func requestOverlayPermissionAndroid() -> bridge.Result_bool_ {
328
+ do {
329
+ let __result = try self.__implementation.requestOverlayPermissionAndroid()
330
+ let __resultCpp = __result
331
+ return bridge.create_Result_bool_(__resultCpp)
332
+ } catch (let __error) {
333
+ let __exceptionPtr = __error.toCpp()
334
+ return bridge.create_Result_bool_(__exceptionPtr)
335
+ }
336
+ }
337
+
338
+ @inline(__always)
339
+ public final func hasOverlayPermissionAndroid() -> bridge.Result_bool_ {
340
+ do {
341
+ let __result = try self.__implementation.hasOverlayPermissionAndroid()
342
+ let __resultCpp = __result
343
+ return bridge.create_Result_bool_(__resultCpp)
344
+ } catch (let __error) {
345
+ let __exceptionPtr = __error.toCpp()
346
+ return bridge.create_Result_bool_(__exceptionPtr)
347
+ }
348
+ }
325
349
  }
@@ -30,6 +30,8 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
30
30
  prototype.registerHybridMethod("addListener", &HybridCallManagerSpec::addListener);
31
31
  prototype.registerHybridMethod("registerVoIPTokenListener", &HybridCallManagerSpec::registerVoIPTokenListener);
32
32
  prototype.registerHybridMethod("hasActiveCall", &HybridCallManagerSpec::hasActiveCall);
33
+ prototype.registerHybridMethod("requestOverlayPermissionAndroid", &HybridCallManagerSpec::requestOverlayPermissionAndroid);
34
+ prototype.registerHybridMethod("hasOverlayPermissionAndroid", &HybridCallManagerSpec::hasOverlayPermissionAndroid);
33
35
  });
34
36
  }
35
37
 
@@ -71,6 +71,8 @@ namespace margelo::nitro::qusaieilouti99_callmanager {
71
71
  virtual std::function<void()> addListener(const std::function<void(CallEventType /* event */, const std::string& /* payload */)>& listener) = 0;
72
72
  virtual std::function<void()> registerVoIPTokenListener(const std::function<void(const std::string& /* payload */)>& listener) = 0;
73
73
  virtual bool hasActiveCall() = 0;
74
+ virtual bool requestOverlayPermissionAndroid() = 0;
75
+ virtual bool hasOverlayPermissionAndroid() = 0;
74
76
 
75
77
  protected:
76
78
  // Hybrid Setup
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.185",
3
+ "version": "0.1.187",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",
@@ -62,6 +62,9 @@ export interface CallManager
62
62
  ): () => void;
63
63
 
64
64
  hasActiveCall(): boolean; // if there is an active call, no matter ringing, incoming, outgoing, whatever
65
+
66
+ requestOverlayPermissionAndroid(): boolean; // only android
67
+ hasOverlayPermissionAndroid(): boolean; // only android
65
68
  }
66
69
 
67
70
  export const CallManagerHybridObject =