11package com.appsflyer.reactnative
22
3+ import android.app.Activity
34import android.os.Handler
45import android.os.Looper
56import com.facebook.react.bridge.*
67import com.facebook.react.modules.core.DeviceEventManagerModule
78import com.appsflyer.pluginbridge.handler.AppsFlyerRpcHandler
89import com.appsflyer.pluginbridge.model.RpcResponse
9- import kotlinx.coroutines.CoroutineScope
10- import kotlinx.coroutines.Dispatchers
11- import kotlinx.coroutines.SupervisorJob
12- import kotlinx.coroutines.launch
10+ import org.json.JSONArray
11+ import org.json.JSONException
1312import org.json.JSONObject
1413
15- class RNAppsFlyerRPCModule (private val reactContext : ReactApplicationContext ) :
14+ class RNAppsFlyerRPCModule (reactContext : ReactApplicationContext ) :
1615 ReactContextBaseJavaModule (reactContext) {
1716
18- private val rpcHandler: AppsFlyerRpcHandler
17+ private var rpcHandler: AppsFlyerRpcHandler ? = null
1918 private val mainHandler = Handler (Looper .getMainLooper())
2019
21- init {
22- val context = reactContext.applicationContext
23- rpcHandler = AppsFlyerRpcHandler (
24- context = context,
20+ override fun invalidate () {
21+ mainHandler.removeCallbacksAndMessages(null )
22+ rpcHandler = null
23+ }
24+
25+ private fun getOrCreateHandler (): AppsFlyerRpcHandler {
26+ val handler = rpcHandler
27+ if (handler != null ) {
28+ return handler
29+ }
30+
31+ val activity = getCurrentActivity() ? : throw IllegalStateException (" Activity is required but not available. Make sure the React Native app is fully initialized." )
32+
33+ val newHandler = AppsFlyerRpcHandler (
34+ context = activity,
2535 pluginNotifier = { jsonEvent ->
2636 emitEventToJavaScript(jsonEvent)
2737 }
2838 )
39+ rpcHandler = newHandler
40+ return newHandler
2941 }
3042
3143 override fun getName (): String = " RNAppsFlyerRPC"
3244
3345 @ReactMethod
3446 fun executeJson (jsonRequest : String , promise : Promise ) {
47+ if (jsonRequest.isBlank()) {
48+ promise.reject(" INVALID_REQUEST" , " JSON request cannot be empty" , null )
49+ return
50+ }
51+
3552 try {
36- val response = rpcHandler.execute(jsonRequest)
53+ val handler = getOrCreateHandler()
54+ val response = handler.execute(jsonRequest)
3755 val jsonResponse = convertResponseToJson(response)
3856 promise.resolve(jsonResponse)
57+ } catch (e: IllegalStateException ) {
58+ android.util.Log .e(" RNAppsFlyerRPC" , " [Android] Activity context not available: ${e.message} " , e)
59+ promise.reject(" CONTEXT_UNAVAILABLE" , e.message ? : " Activity context is required" , e)
60+ } catch (e: IllegalArgumentException ) {
61+ android.util.Log .e(" RNAppsFlyerRPC" , " [Android] Invalid RPC request: ${e.message} " , e)
62+ promise.reject(" INVALID_REQUEST" , e.message ? : " Invalid request" , e)
3963 } catch (e: Exception ) {
4064 android.util.Log .e(" RNAppsFlyerRPC" , " [Android] executeJson error: ${e.message} " , e)
4165 promise.reject(" RPC_EXECUTION_ERROR" , e.message ? : " Unknown error" , e)
@@ -47,19 +71,17 @@ class RNAppsFlyerRPCModule(private val reactContext: ReactApplicationContext) :
4771 is RpcResponse .VoidSuccess -> {
4872 JSONObject ().apply {
4973 put(" jsonrpc" , " 2.0" )
50- // Use JSONObject.NULL instead of null to ensure the key is included in the JSON string
5174 put(" result" , JSONObject .NULL )
5275 }.toString()
5376 }
5477 is RpcResponse .Success <* > -> {
5578 JSONObject ().apply {
5679 put(" jsonrpc" , " 2.0" )
57- // Handle null result values properly
5880 val resultValue = response.result
5981 if (resultValue == null ) {
6082 put(" result" , JSONObject .NULL )
6183 } else {
62- put(" result" , resultValue)
84+ put(" result" , convertToJsonValue( resultValue) )
6385 }
6486 }.toString()
6587 }
@@ -75,9 +97,45 @@ class RNAppsFlyerRPCModule(private val reactContext: ReactApplicationContext) :
7597 }
7698 }
7799
100+ private fun convertToJsonValue (value : Any? ): Any {
101+ return when (value) {
102+ null -> JSONObject .NULL
103+ is String -> value
104+ is Boolean -> value
105+ is Int -> value
106+ is Long -> value
107+ is Double -> value
108+ is Float -> value.toDouble()
109+ is Short -> value.toInt()
110+ is Byte -> value.toInt()
111+ is Map <* , * > -> {
112+ val jsonObject = JSONObject ()
113+ value.forEach { (k, v) ->
114+ val key = k?.toString() ? : " null"
115+ jsonObject.put(key, convertToJsonValue(v))
116+ }
117+ jsonObject
118+ }
119+ is List <* > -> {
120+ val jsonArray = JSONArray ()
121+ value.forEach { item ->
122+ jsonArray.put(convertToJsonValue(item))
123+ }
124+ jsonArray
125+ }
126+ else -> value.toString()
127+ }
128+ }
129+
78130 private fun emitEventToJavaScript (jsonEvent : String ) {
79- val context = reactContext
80- if (context == null || ! context.hasActiveReactInstance()) {
131+ val reactApplicationContext = reactApplicationContext
132+ if (! reactApplicationContext.hasActiveReactInstance()) {
133+ return
134+ }
135+
136+ val activity = getCurrentActivity()
137+ if (activity == null ) {
138+ android.util.Log .w(" RNAppsFlyerRPC" , " [Android] Cannot emit event: activity not available" )
81139 return
82140 }
83141
@@ -90,16 +148,19 @@ class RNAppsFlyerRPCModule(private val reactContext: ReactApplicationContext) :
90148 when (value) {
91149 is String -> eventMap.putString(key, value)
92150 is Int -> eventMap.putInt(key, value)
151+ is Long -> eventMap.putDouble(key, value.toDouble())
93152 is Double -> eventMap.putDouble(key, value)
153+ is Float -> eventMap.putDouble(key, value.toDouble())
94154 is Boolean -> eventMap.putBoolean(key, value)
95155 is JSONObject -> eventMap.putMap(key, jsonObjectToWritableMap(value))
156+ is JSONArray -> eventMap.putArray(key, jsonArrayToWritableArray(value))
96157 else -> eventMap.putString(key, value.toString())
97158 }
98159 }
99160
100161 val runnable = Runnable {
101- if (context .hasActiveReactInstance()) {
102- context .getJSModule(DeviceEventManagerModule .RCTDeviceEventEmitter ::class .java)
162+ if (reactApplicationContext .hasActiveReactInstance() && getCurrentActivity() != null ) {
163+ reactApplicationContext .getJSModule(DeviceEventManagerModule .RCTDeviceEventEmitter ::class .java)
103164 .emit(" onEvent" , eventMap)
104165 }
105166 }
@@ -109,8 +170,10 @@ class RNAppsFlyerRPCModule(private val reactContext: ReactApplicationContext) :
109170 } else {
110171 mainHandler.post(runnable)
111172 }
173+ } catch (e: JSONException ) {
174+ android.util.Log .e(" RNAppsFlyerRPC" , " [Android] Failed to parse JSON event: ${e.message} " , e)
112175 } catch (e: Exception ) {
113- // Ignore JSON parsing errors
176+ android.util. Log .e( " RNAppsFlyerRPC " , " [Android] Failed to emit event: ${e.message} " , e)
114177 }
115178 }
116179
@@ -121,22 +184,44 @@ class RNAppsFlyerRPCModule(private val reactContext: ReactApplicationContext) :
121184 when (value) {
122185 is String -> map.putString(key, value)
123186 is Int -> map.putInt(key, value)
187+ is Long -> map.putDouble(key, value.toDouble())
124188 is Double -> map.putDouble(key, value)
189+ is Float -> map.putDouble(key, value.toDouble())
125190 is Boolean -> map.putBoolean(key, value)
126191 is JSONObject -> map.putMap(key, jsonObjectToWritableMap(value))
192+ is JSONArray -> map.putArray(key, jsonArrayToWritableArray(value))
127193 else -> map.putString(key, value.toString())
128194 }
129195 }
130196 return map
131197 }
132198
199+ private fun jsonArrayToWritableArray (jsonArray : JSONArray ): WritableArray {
200+ val array = Arguments .createArray()
201+ for (i in 0 until jsonArray.length()) {
202+ val value = jsonArray.get(i)
203+ when (value) {
204+ is String -> array.pushString(value)
205+ is Int -> array.pushInt(value)
206+ is Long -> array.pushDouble(value.toDouble())
207+ is Double -> array.pushDouble(value)
208+ is Float -> array.pushDouble(value.toDouble())
209+ is Boolean -> array.pushBoolean(value)
210+ is JSONObject -> array.pushMap(jsonObjectToWritableMap(value))
211+ is JSONArray -> array.pushArray(jsonArrayToWritableArray(value))
212+ else -> array.pushString(value.toString())
213+ }
214+ }
215+ return array
216+ }
217+
133218 @ReactMethod
134- fun addListener (eventName : String ) {
219+ fun addListener (_eventName : String ) {
135220 // Required for event emitter support
136221 }
137222
138223 @ReactMethod
139- fun removeListeners (count : Double ) {
224+ fun removeListeners (_count : Double ) {
140225 // Required for event emitter support
141226 }
142227}
0 commit comments