@qusaieilouti99/call-manager 0.1.62 → 0.1.63

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.
@@ -48,8 +48,12 @@ object CallEngine {
48
48
  private const val FOREGROUND_NOTIF_ID = 1001
49
49
 
50
50
  // Core context - initialized once and maintained
51
+ // Improved context management with thread safety
52
+ @Volatile
51
53
  private var appContext: Context? = null
52
- private var isInitialized = AtomicBoolean(false)
54
+ private val isInitialized = AtomicBoolean(false)
55
+ private val initializationLock = Any()
56
+
53
57
 
54
58
  // Audio & Media
55
59
  private var ringtone: android.media.Ringtone? = null
@@ -83,16 +87,25 @@ object CallEngine {
83
87
  fun onLockScreenBypassChanged(shouldBypass: Boolean)
84
88
  }
85
89
 
86
- // --- INITIALIZATION - Fix for context management ---
90
+ // --- INITIALIZATION with better error handling ---
87
91
  fun initialize(context: Context) {
88
- if (isInitialized.compareAndSet(false, true)) {
89
- appContext = context.applicationContext
90
- audioManager = appContext?.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
91
- Log.d(TAG, "CallEngine initialized with context")
92
-
93
- // Initialize foreground service if needed
94
- if (isCallActive()) {
95
- startForegroundService()
92
+ synchronized(initializationLock) {
93
+ if (isInitialized.compareAndSet(false, true)) {
94
+ appContext = context.applicationContext
95
+ audioManager = appContext?.getSystemService(Context.AUDIO_SERVICE) as? AudioManager
96
+ Log.d(TAG, "CallEngine initialized successfully with context: ${context.javaClass.simpleName}")
97
+
98
+ // Verify critical services are available
99
+ if (audioManager == null) {
100
+ Log.w(TAG, "AudioManager is null after initialization")
101
+ }
102
+
103
+ // Initialize foreground service if needed
104
+ if (isCallActive()) {
105
+ startForegroundService()
106
+ }
107
+ } else {
108
+ Log.d(TAG, "CallEngine already initialized, skipping")
96
109
  }
97
110
  }
98
111
  }
@@ -100,7 +113,9 @@ object CallEngine {
100
113
  fun isInitialized(): Boolean = isInitialized.get()
101
114
 
102
115
  private fun requireContext(): Context {
103
- return appContext ?: throw IllegalStateException("CallEngine not initialized. Call initialize() first.")
116
+ return appContext ?: throw IllegalStateException(
117
+ "CallEngine not initialized. Ensure CallEngine.initialize(context) is called in Application.onCreate() before any module usage."
118
+ )
104
119
  }
105
120
 
106
121
  // --- Event System ---
@@ -1,48 +1,26 @@
1
1
  package com.margelo.nitro.qusaieilouti99.callmanager
2
2
 
3
3
  import android.util.Log
4
- import com.facebook.react.bridge.ReactApplicationContext
5
4
  import com.facebook.proguard.annotations.DoNotStrip
6
5
 
7
6
  @DoNotStrip
8
- class CallManager : HybridCallManagerSpec() { // Match the parameterless constructor
7
+ class CallManager : HybridCallManagerSpec() {
9
8
 
10
9
  private val TAG = "CallManager"
11
10
 
12
- // This method ensures CallEngine has a valid context.
13
- // It primarily relies on MainApplication.onCreate, but provides a fallback.
11
+ // Simplified approach - rely on proper Application.onCreate() initialization
12
+ // Remove all fallback context access attempts that don't work with Nitro modules
14
13
  private fun ensureInitialized() {
15
14
  if (!CallEngine.isInitialized()) {
16
- // This log should ideally NOT be seen frequently in production.
17
- // If it appears, it means CallEngine wasn't initialized by MainApplication.
18
- Log.e(TAG, "CallEngine not initialized! Attempting late initialization from CallManager.")
19
- try {
20
- // For React Native modules (including JSI/Nitro ones),
21
- // ReactApplicationContext.getCurrentApplicationContext() provides the
22
- // ReactApplicationContext once the bridge is set up. From there, we get the Application context.
23
- val reactContext = ReactApplicationContext.getCurrentApplicationContext()
24
-
25
- if (reactContext != null) {
26
- val appContext = reactContext.applicationContext
27
- if (appContext != null) {
28
- CallEngine.initialize(appContext)
29
- Log.d(TAG, "CallEngine successfully (late) initialized via ReactApplicationContext.")
30
- } else {
31
- Log.e(TAG, "Error: reactContext.applicationContext is null. Cannot late-initialize CallEngine.")
32
- throw IllegalStateException("CallEngine initialization failed: Application context is null.")
33
- }
34
- } else {
35
- Log.e(TAG, "Error: ReactApplicationContext.getCurrentApplicationContext() returned null. Cannot late-initialize CallEngine.")
36
- throw IllegalStateException("CallEngine initialization failed: ReactApplicationContext not available.")
37
- }
38
- } catch (e: Exception) {
39
- Log.e(TAG, "Exception during CallEngine late initialization: ${e.message}", e)
40
- throw IllegalStateException("CallEngine fatal error during initialization: ${e.message}", e)
41
- }
15
+ Log.e(TAG, "CallEngine not initialized! This should not happen if Application.onCreate() was called properly.")
16
+ throw IllegalStateException(
17
+ "CallEngine must be initialized in Application.onCreate(). " +
18
+ "Make sure MainApplication.onCreate() calls CallEngine.initialize(this) before any native calls."
19
+ )
42
20
  }
43
21
  }
44
22
 
45
- // --- All your overridden methods must call ensureInitialized() first ---
23
+ // --- All methods must call ensureInitialized() first ---
46
24
 
47
25
  override fun endCall(callId: String): Unit {
48
26
  Log.d(TAG, "endCall requested for callId: $callId")
@@ -81,7 +59,7 @@ class CallManager : HybridCallManagerSpec() { // Match the parameterless constru
81
59
  }
82
60
 
83
61
  override fun addListener(listener: (event: CallEventType, payload: String) -> Unit): () -> Unit {
84
- Log.d(TAG, "addListener called with listener: $listener")
62
+ Log.d(TAG, "addListener called")
85
63
  ensureInitialized()
86
64
  CallEngine.setEventHandler(listener)
87
65
  return {
@@ -93,7 +71,6 @@ class CallManager : HybridCallManagerSpec() { // Match the parameterless constru
93
71
  override fun startOutgoingCall(callId: String, callType: String, targetName: String, metadata: String?): Unit {
94
72
  Log.d(TAG, "startOutgoingCall requested: callId=$callId, callType=$callType, targetName=$targetName")
95
73
  ensureInitialized()
96
- // IMPORTANT: The Bundle wrapping fix for TelecomManager must still be in CallEngine.startOutgoingCall
97
74
  CallEngine.startOutgoingCall(callId, callType, targetName, metadata)
98
75
  }
99
76
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@qusaieilouti99/call-manager",
3
- "version": "0.1.62",
3
+ "version": "0.1.63",
4
4
  "description": "Call manager",
5
5
  "main": "./lib/module/index.js",
6
6
  "types": "./lib/typescript/src/index.d.ts",