bridgefy-react-native 1.1.7 → 1.1.9

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.
Files changed (105) hide show
  1. package/LICENSE +1 -1
  2. package/README.md +137 -76
  3. package/android/build.gradle +37 -56
  4. package/android/gradle.properties +4 -4
  5. package/android/src/main/AndroidManifest.xml +1 -11
  6. package/android/src/main/java/me/bridgefy/plugin/react_native/BridgefyReactNativeModule.kt +590 -333
  7. package/android/src/main/java/me/bridgefy/plugin/react_native/BridgefyReactNativePackage.kt +25 -8
  8. package/android/src/main/java/me/bridgefy/plugin/react_native/service/BridgefyService.kt +625 -0
  9. package/android/src/main/java/me/bridgefy/plugin/react_native/util/BridgefyOperationModeManager.kt +193 -0
  10. package/android/src/main/java/me/bridgefy/plugin/react_native/util/BridgefyServiceManager.kt +123 -0
  11. package/android/src/main/java/me/bridgefy/plugin/react_native/util/Utils.kt +172 -0
  12. package/bridgefy-react-native.podspec +5 -25
  13. package/ios/BridgefyReactNativeModule.m +88 -0
  14. package/ios/BridgefyReactNativeModule.swift +524 -0
  15. package/lib/module/NativeBridgefy.js +117 -0
  16. package/lib/module/NativeBridgefy.js.map +1 -0
  17. package/lib/module/index.js +172 -207
  18. package/lib/module/index.js.map +1 -1
  19. package/lib/module/package.json +1 -0
  20. package/lib/typescript/package.json +1 -0
  21. package/lib/typescript/src/NativeBridgefy.d.ts +250 -0
  22. package/lib/typescript/src/NativeBridgefy.d.ts.map +1 -0
  23. package/lib/typescript/src/index.d.ts +146 -0
  24. package/lib/typescript/src/index.d.ts.map +1 -0
  25. package/package.json +77 -72
  26. package/src/NativeBridgefy.ts +321 -0
  27. package/src/index.tsx +283 -225
  28. package/ios/BridgefyReactNative.m +0 -56
  29. package/ios/BridgefyReactNative.swift +0 -368
  30. package/ios/BridgefyReactNative.xcodeproj/project.pbxproj +0 -293
  31. package/ios/BridgefyReactNative.xcodeproj/project.xcworkspace/contents.xcworkspacedata +0 -7
  32. package/ios/BridgefyReactNative.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist +0 -8
  33. package/ios/BridgefyReactNative.xcodeproj/project.xcworkspace/xcuserdata/bridgefy.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
  34. package/ios/BridgefyReactNative.xcodeproj/xcuserdata/bridgefy.xcuserdatad/xcschemes/xcschememanagement.plist +0 -14
  35. package/ios/Frameworks/BridgefySDK.xcframework/Info.plist +0 -48
  36. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/BridgefySDK +0 -0
  37. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Headers/BridgefySDK-Swift.h +0 -313
  38. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Headers/BridgefySDK.h +0 -15
  39. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Info.plist +0 -0
  40. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios.abi.json +0 -7020
  41. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios.private.swiftinterface +0 -115
  42. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios.swiftdoc +0 -0
  43. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios.swiftinterface +0 -115
  44. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/Modules/module.modulemap +0 -11
  45. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/BridgefySDK.framework/_CodeSignature/CodeResources +0 -190
  46. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/dSYMs/BridgefySDK.framework.dSYM/Contents/Info.plist +0 -20
  47. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/dSYMs/BridgefySDK.framework.dSYM/Contents/Resources/DWARF/BridgefySDK +0 -0
  48. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64/dSYMs/BridgefySDK.framework.dSYM/Contents/Resources/Relocations/aarch64/BridgefySDK.yml +0 -13549
  49. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/BridgefySDK +0 -0
  50. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Headers/BridgefySDK-Swift.h +0 -622
  51. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Headers/BridgefySDK.h +0 -15
  52. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Info.plist +0 -0
  53. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios-simulator.abi.json +0 -7020
  54. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios-simulator.private.swiftinterface +0 -115
  55. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios-simulator.swiftdoc +0 -0
  56. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/arm64-apple-ios-simulator.swiftinterface +0 -115
  57. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/x86_64-apple-ios-simulator.abi.json +0 -7020
  58. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/x86_64-apple-ios-simulator.private.swiftinterface +0 -115
  59. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/x86_64-apple-ios-simulator.swiftdoc +0 -0
  60. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/BridgefySDK.swiftmodule/x86_64-apple-ios-simulator.swiftinterface +0 -115
  61. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/Modules/module.modulemap +0 -11
  62. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/BridgefySDK.framework/_CodeSignature/CodeResources +0 -245
  63. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/BridgefySDK.framework.dSYM/Contents/Info.plist +0 -20
  64. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/BridgefySDK.framework.dSYM/Contents/Resources/DWARF/BridgefySDK +0 -0
  65. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/BridgefySDK.framework.dSYM/Contents/Resources/Relocations/aarch64/BridgefySDK.yml +0 -13237
  66. package/ios/Frameworks/BridgefySDK.xcframework/ios-arm64_x86_64-simulator/dSYMs/BridgefySDK.framework.dSYM/Contents/Resources/Relocations/x86_64/BridgefySDK.yml +0 -12858
  67. package/lib/commonjs/index.js +0 -278
  68. package/lib/commonjs/index.js.map +0 -1
  69. package/lib/commonjs/infraestructure/index.js +0 -28
  70. package/lib/commonjs/infraestructure/index.js.map +0 -1
  71. package/lib/commonjs/infraestructure/interfaces/ibridgefy.js +0 -6
  72. package/lib/commonjs/infraestructure/interfaces/ibridgefy.js.map +0 -1
  73. package/lib/commonjs/infraestructure/interfaces/index.js +0 -17
  74. package/lib/commonjs/infraestructure/interfaces/index.js.map +0 -1
  75. package/lib/commonjs/infraestructure/services/bridgefy_service.js +0 -6
  76. package/lib/commonjs/infraestructure/services/bridgefy_service.js.map +0 -1
  77. package/lib/commonjs/infraestructure/services/index.js +0 -17
  78. package/lib/commonjs/infraestructure/services/index.js.map +0 -1
  79. package/lib/module/infraestructure/index.js +0 -3
  80. package/lib/module/infraestructure/index.js.map +0 -1
  81. package/lib/module/infraestructure/interfaces/ibridgefy.js +0 -2
  82. package/lib/module/infraestructure/interfaces/ibridgefy.js.map +0 -1
  83. package/lib/module/infraestructure/interfaces/index.js +0 -2
  84. package/lib/module/infraestructure/interfaces/index.js.map +0 -1
  85. package/lib/module/infraestructure/services/bridgefy_service.js +0 -2
  86. package/lib/module/infraestructure/services/bridgefy_service.js.map +0 -1
  87. package/lib/module/infraestructure/services/index.js +0 -2
  88. package/lib/module/infraestructure/services/index.js.map +0 -1
  89. package/lib/typescript/index.d.ts +0 -219
  90. package/lib/typescript/index.d.ts.map +0 -1
  91. package/lib/typescript/infraestructure/index.d.ts +0 -3
  92. package/lib/typescript/infraestructure/index.d.ts.map +0 -1
  93. package/lib/typescript/infraestructure/interfaces/ibridgefy.d.ts +0 -10
  94. package/lib/typescript/infraestructure/interfaces/ibridgefy.d.ts.map +0 -1
  95. package/lib/typescript/infraestructure/interfaces/index.d.ts +0 -2
  96. package/lib/typescript/infraestructure/interfaces/index.d.ts.map +0 -1
  97. package/lib/typescript/infraestructure/services/bridgefy_service.d.ts +0 -17
  98. package/lib/typescript/infraestructure/services/bridgefy_service.d.ts.map +0 -1
  99. package/lib/typescript/infraestructure/services/index.d.ts +0 -2
  100. package/lib/typescript/infraestructure/services/index.d.ts.map +0 -1
  101. package/src/infraestructure/index.tsx +0 -2
  102. package/src/infraestructure/interfaces/ibridgefy.tsx +0 -10
  103. package/src/infraestructure/interfaces/index.tsx +0 -1
  104. package/src/infraestructure/services/bridgefy_service.tsx +0 -20
  105. package/src/infraestructure/services/index.tsx +0 -1
@@ -1,17 +1,34 @@
1
1
  package me.bridgefy.plugin.react_native
2
2
 
3
- import com.facebook.react.ReactPackage
3
+ import com.facebook.react.BaseReactPackage
4
4
  import com.facebook.react.bridge.NativeModule
5
5
  import com.facebook.react.bridge.ReactApplicationContext
6
- import com.facebook.react.uimanager.ViewManager
6
+ import com.facebook.react.module.model.ReactModuleInfo
7
+ import com.facebook.react.module.model.ReactModuleInfoProvider
8
+ import me.bridgefy.plugin.react_native.NativeBridgefySpec
9
+ import java.util.HashMap
7
10
 
8
-
9
- class BridgefyReactNativePackage : ReactPackage {
10
- override fun createNativeModules(reactContext: ReactApplicationContext): List<NativeModule> {
11
- return listOf(BridgefyReactNativeModule(reactContext))
11
+ class BridgefyReactNativePackage : BaseReactPackage() {
12
+ override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
13
+ return if (name == NativeBridgefySpec.NAME) {
14
+ BridgefyReactNativeModule(reactContext)
15
+ } else {
16
+ null
17
+ }
12
18
  }
13
19
 
14
- override fun createViewManagers(reactContext: ReactApplicationContext): List<ViewManager<*, *>> {
15
- return emptyList()
20
+ override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
21
+ return ReactModuleInfoProvider {
22
+ val moduleInfos: MutableMap<String, ReactModuleInfo> = HashMap()
23
+ moduleInfos[NativeBridgefySpec.NAME] = ReactModuleInfo(
24
+ NativeBridgefySpec.NAME,
25
+ NativeBridgefySpec.NAME,
26
+ false, // canOverrideExistingModule
27
+ false, // needsEagerInit
28
+ false, // isCxxModule
29
+ true // isTurboModule
30
+ )
31
+ moduleInfos
32
+ }
16
33
  }
17
34
  }
@@ -0,0 +1,625 @@
1
+ /**
2
+ * BridgefyService
3
+ *
4
+ * Android Service for Bridgefy SDK
5
+ * Runs Bridgefy in the background with persistent notification
6
+ * Communicates with React Native via Broadcast/Intent
7
+ */
8
+
9
+ package me.bridgefy.plugin.react_native.service
10
+
11
+ import android.app.Notification
12
+ import android.app.NotificationChannel
13
+ import android.app.NotificationManager
14
+ import android.app.PendingIntent
15
+ import android.app.Service
16
+ import android.content.Context
17
+ import android.content.Intent
18
+ import android.content.pm.ServiceInfo
19
+ import android.graphics.drawable.Drawable
20
+ import android.os.Build
21
+ import android.os.Bundle
22
+ import android.os.IBinder
23
+ import android.util.Log
24
+ import androidx.core.app.NotificationCompat
25
+ import androidx.core.app.ServiceCompat
26
+ import androidx.core.graphics.drawable.IconCompat
27
+ import androidx.core.graphics.drawable.toBitmap
28
+ import me.bridgefy.Bridgefy
29
+ import me.bridgefy.commons.TransmissionMode
30
+ import me.bridgefy.commons.exception.BridgefyException
31
+ import me.bridgefy.commons.listener.BridgefyDelegate
32
+ import me.bridgefy.commons.propagation.PropagationProfile
33
+ import me.bridgefy.logger.enums.LogType
34
+ import me.bridgefy.plugin.react_native.util.BridgefyServiceManager
35
+ import me.bridgefy.plugin.react_native.util.Utils.bundleFromBridgefyException
36
+ import me.bridgefy.plugin.react_native.util.Utils.bundleFromTransmissionMode
37
+ import me.bridgefy.plugin.react_native.util.Utils.transmissionModeFromBundle
38
+ import java.util.UUID
39
+
40
+ class BridgefyService :
41
+ Service(),
42
+ BridgefyDelegate {
43
+ companion object {
44
+ const val CHANNEL_ID = "BridgefyServiceChannel"
45
+ const val NOTIFICATION_ID = 1001
46
+
47
+ // Intent Actions
48
+ const val ACTION_START_SERVICE = "me.bridgefy.START_SERVICE"
49
+ const val ACTION_STOP_SERVICE = "me.bridgefy.STOP_SERVICE"
50
+ const val ACTION_INITIALIZE = "me.bridgefy.INITIALIZE"
51
+ const val ACTION_START_SDK = "me.bridgefy.START_SDK"
52
+ const val ACTION_STOP_SDK = "me.bridgefy.STOP_SDK"
53
+ const val ACTION_SEND_MESSAGE = "me.bridgefy.SEND_MESSAGE"
54
+ const val ACTION_ESTABLISH_SECURE = "me.bridgefy.ESTABLISH_SECURE"
55
+
56
+ // Broadcast Events
57
+ const val EVENT_BRIDGEFY_DID_START = "me.bridgefy.event.DID_START"
58
+ const val EVENT_BRIDGEFY_DID_STOP = "me.bridgefy.event.DID_STOP"
59
+ const val EVENT_BRIDGEFY_DID_CONNECT = "me.bridgefy.event.DID_CONNECT"
60
+ const val EVENT_BRIDGEFY_DID_UPDATE_CONNECTED_PEERS =
61
+ "me.bridgefy.event.DID_UPDATE_CONNECTED_PEERS"
62
+ const val EVENT_BRIDGEFY_DID_DISCONNECT = "me.bridgefy.event.DID_DISCONNECT"
63
+ const val EVENT_BRIDGEFY_DID_DESTROY_SESSION = "me.bridgefy.event.DID_DESTROY_SESSION"
64
+ const val EVENT_BRIDGEFY_RECEIVE_DATA = "me.bridgefy.event.RECEIVE_DATA"
65
+ const val EVENT_BRIDGEFY_SEND_MESSAGE = "me.bridgefy.event.SEND_MESSAGE"
66
+ const val EVENT_BRIDGEFY_PROGRESS_OF_SEND = "me.bridgefy.event.PROGRESS_OF_SEND"
67
+ const val EVENT_BRIDGEFY_FAIL_SENDING = "me.bridgefy.event.FAIL_SENDING"
68
+ const val EVENT_BRIDGEFY_FAIL_TO_START = "me.bridgefy.event.FAIL_TO_START"
69
+ const val EVENT_BRIDGEFY_FAIL_TO_STOP = "me.bridgefy.event.FAIL_TO_STOP"
70
+ const val EVENT_BRIDGEFY_FAIL_TO_DESTROY_SESSION = "me.bridgefy.event.FAIL_DESTROY_SESSION"
71
+ const val EVENT_BRIDGEFY_ESTABLISH_SECURE = "me.bridgefy.event.ESTABLISH_SECURE"
72
+ const val EVENT_BRIDGEFY_FAIL_SECURE = "me.bridgefy.event.FAIL_SECURE"
73
+
74
+ // Extra Keys
75
+ const val EXTRA_API_KEY = "API_KEY"
76
+ const val EXTRA_VERBOSE_LOGGING = "VERBOSE_LOGGING"
77
+ const val EXTRA_USER_ID = "USER_ID"
78
+ const val EXTRA_CONNECTED_PEERS = "CONNECTED_PEERS"
79
+ const val EXTRA_PROPAGATION_PROFILE = "PROPAGATION_PROFILE"
80
+ const val EXTRA_MESSAGE_DATA = "MESSAGE_DATA"
81
+ const val EXTRA_TRANSMISSION_MODE = "TRANSMISSION_MODE"
82
+ const val EXTRA_RECIPIENT_ID = "RECIPIENT_ID"
83
+ const val EXTRA_MESSAGE_ID = "MESSAGE_ID"
84
+ const val EXTRA_POSITION = "POSITION"
85
+ const val EXTRA_OF = "OF"
86
+ const val EXTRA_ERROR_CODE = "ERROR_CODE"
87
+ const val EXTRA_ERROR_MESSAGE = "ERROR_MESSAGE"
88
+ }
89
+
90
+ private val serviceManager by lazy { BridgefyServiceManager.getInstance(this) }
91
+ private var currentUserId: String = ""
92
+ private val connectedPeers = mutableListOf<String>()
93
+
94
+ override fun onBind(p0: Intent?): IBinder? = null
95
+
96
+ override fun onCreate() {
97
+ super.onCreate()
98
+ currentUserId = serviceManager.getCurrentUserId() ?: ""
99
+ // ISSUE 1 FIX: Check FOREGROUND_SERVICE permission in manifest
100
+ verifyForegroundServicePermission()
101
+
102
+ // ISSUE 2 FIX: Create notification channel for Android 8+
103
+ createNotificationChannel()
104
+ }
105
+
106
+ override fun onStartCommand(
107
+ intent: Intent?,
108
+ flags: Int,
109
+ startId: Int,
110
+ ): Int {
111
+ when (intent?.action) {
112
+ ACTION_START_SERVICE -> {
113
+ startForegroundService()
114
+ }
115
+
116
+ ACTION_STOP_SERVICE -> {
117
+ stopForegroundService()
118
+ // Return START_STICKY so service restarts if killed
119
+ return START_STICKY
120
+ }
121
+
122
+ ACTION_INITIALIZE -> {
123
+ val apiKey = intent.getStringExtra(EXTRA_API_KEY) ?: ""
124
+ val verboseLogging = intent.getBooleanExtra(EXTRA_VERBOSE_LOGGING, false)
125
+ initializeBridgefy(apiKey, verboseLogging)
126
+ }
127
+
128
+ ACTION_START_SDK -> {
129
+ val userId = intent.getStringExtra(EXTRA_USER_ID)
130
+ val profile = intent.getStringExtra(EXTRA_PROPAGATION_PROFILE) ?: "realTime"
131
+ startBridgefy(userId, profile)
132
+ }
133
+
134
+ ACTION_STOP_SDK -> {
135
+ stopBridgefy()
136
+ }
137
+
138
+ ACTION_SEND_MESSAGE -> {
139
+ val data = intent.getByteArrayExtra(EXTRA_MESSAGE_DATA) ?: ByteArray(0)
140
+ val mode = intent.getBundleExtra(EXTRA_TRANSMISSION_MODE) ?: Bundle()
141
+ sendMessage(data, transmissionModeFromBundle(mode))
142
+ }
143
+
144
+ ACTION_ESTABLISH_SECURE -> {
145
+ val userId = intent.getStringExtra(EXTRA_USER_ID) ?: ""
146
+ establishSecureConnection(userId)
147
+ }
148
+ }
149
+
150
+ // Return START_STICKY to ensure service restarts if killed
151
+ return START_STICKY
152
+ }
153
+
154
+ /**
155
+ * ISSUE 1 FIX: Verify FOREGROUND_SERVICE permission in manifest
156
+ */
157
+ private fun verifyForegroundServicePermission() {
158
+ try {
159
+ val permission = "android.permission.FOREGROUND_SERVICE"
160
+ val packageInfo = packageManager.getPackageInfo(packageName, android.content.pm.PackageManager.GET_PERMISSIONS)
161
+ val requestedPermissions = packageInfo.requestedPermissions ?: arrayOf()
162
+
163
+ if (!requestedPermissions.contains(permission)) {
164
+ println("✗ FOREGROUND_SERVICE permission missing from manifest!")
165
+ println(" Add to AndroidManifest.xml: <uses-permission android:name=\"android.permission.FOREGROUND_SERVICE\" />")
166
+ }
167
+
168
+ // Android 12+: Check FOREGROUND_SERVICE_CONNECTED_DEVICE
169
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
170
+ val connectedDevicePermission = "android.permission.FOREGROUND_SERVICE_CONNECTED_DEVICE"
171
+ if (requestedPermissions.contains(connectedDevicePermission)) {
172
+ } else {
173
+ println("⚠ FOREGROUND_SERVICE_CONNECTED_DEVICE permission missing (optional)")
174
+ }
175
+ }
176
+ } catch (e: Exception) {
177
+ println("Error verifying permissions: ${e.localizedMessage}")
178
+ }
179
+ }
180
+
181
+ /**
182
+ * ISSUE 3 FIX: Verify Android 8+ uses startForegroundService()
183
+ */
184
+ private fun startForegroundService() {
185
+ try {
186
+ val notification = createNotification("${getHostAppName()}", "")
187
+
188
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
189
+ // Android 8+: Use startForegroundService()
190
+ ServiceCompat.startForeground(this, NOTIFICATION_ID, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_DATA_SYNC)
191
+ } else {
192
+ // Android 7-: Use legacy startForeground()
193
+ startForeground(NOTIFICATION_ID, notification)
194
+ }
195
+ } catch (e: Exception) {
196
+ println("Error starting foreground service: ${e.localizedMessage}")
197
+ }
198
+ }
199
+
200
+ private fun stopForegroundService() {
201
+ try {
202
+ if (serviceManager.isSDKStarted()) {
203
+ stopBridgefy()
204
+ }
205
+
206
+ // Stop foreground and remove notification
207
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
208
+ stopForeground(STOP_FOREGROUND_REMOVE)
209
+ } else {
210
+ @Suppress("DEPRECATION")
211
+ stopForeground(true)
212
+ }
213
+
214
+ stopSelf()
215
+ } catch (e: Exception) {
216
+ println("Error stopping foreground service: ${e.localizedMessage}")
217
+ }
218
+ }
219
+
220
+ /**
221
+ * ISSUE 2 FIX: Create notification channel for Android 8+
222
+ */
223
+ private fun createNotificationChannel() {
224
+ // Only create channel on Android 8+
225
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
226
+ try {
227
+ val serviceChannel =
228
+ NotificationChannel(
229
+ CHANNEL_ID,
230
+ getHostAppName(),
231
+ NotificationManager.IMPORTANCE_LOW,
232
+ ).apply {
233
+ setShowBadge(false)
234
+ enableLights(false)
235
+ enableVibration(false)
236
+ setSound(null, null)
237
+ }
238
+
239
+ val manager = getSystemService(NOTIFICATION_SERVICE) as? NotificationManager
240
+ if (manager != null) {
241
+ manager.createNotificationChannel(serviceChannel)
242
+
243
+ // Verify channel was created
244
+ val existingChannel = manager.getNotificationChannel(CHANNEL_ID)
245
+ if (existingChannel != null) {
246
+ } else {
247
+ println("✗ Error: Notification channel creation failed!")
248
+ }
249
+ } else {
250
+ println("✗ NotificationManager is null!")
251
+ }
252
+ } catch (e: Exception) {
253
+ println("Error creating notification channel: ${e.localizedMessage}")
254
+ }
255
+ }
256
+ }
257
+
258
+ private fun getHostAppName(): String = packageManager.getApplicationLabel(applicationInfo).toString()
259
+
260
+ private fun createNotification(
261
+ title: String,
262
+ content: String,
263
+ ): Notification {
264
+ try {
265
+ val notificationIntent = packageManager.getLaunchIntentForPackage(packageName)
266
+ val pendingIntent =
267
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
268
+ PendingIntent.getActivity(
269
+ this,
270
+ 0,
271
+ notificationIntent ?: Intent(),
272
+ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
273
+ )
274
+ } else {
275
+ @Suppress("DEPRECATION")
276
+ PendingIntent.getActivity(
277
+ this,
278
+ 0,
279
+ notificationIntent ?: Intent(),
280
+ PendingIntent.FLAG_UPDATE_CURRENT,
281
+ )
282
+ }
283
+
284
+ val builder =
285
+ NotificationCompat
286
+ .Builder(this, CHANNEL_ID)
287
+ .setContentTitle(title)
288
+ .setContentText(content)
289
+ .setSmallIcon(getAppIcon())
290
+ .setContentIntent(pendingIntent)
291
+ .setOngoing(true)
292
+ .setPriority(NotificationCompat.PRIORITY_LOW)
293
+ .setCategory(NotificationCompat.CATEGORY_SERVICE)
294
+
295
+ return builder.build()
296
+ } catch (e: Exception) {
297
+ println("Error creating notification${e.localizedMessage}")
298
+ throw e
299
+ }
300
+ }
301
+
302
+ private fun getAppIcon(): IconCompat {
303
+ val icon = applicationContext.packageManager.getApplicationIcon(applicationInfo)
304
+ return IconCompat.createWithAdaptiveBitmap(icon.toBitmap())
305
+ }
306
+
307
+ private fun updateNotification(
308
+ title: String,
309
+ content: String,
310
+ ) {
311
+ try {
312
+ val notification = createNotification(title, content)
313
+ val manager = getSystemService(Context.NOTIFICATION_SERVICE) as? NotificationManager
314
+ manager?.notify(NOTIFICATION_ID, notification)
315
+ } catch (e: Exception) {
316
+ println("Error updating notification: ${e.localizedMessage}")
317
+ }
318
+ }
319
+
320
+ // MARK: - Permission Check
321
+
322
+ private fun hasPermission(permission: String): Boolean =
323
+ if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
324
+ checkSelfPermission(permission) == android.content.pm.PackageManager.PERMISSION_GRANTED
325
+ } else {
326
+ true // Assume granted on Android < 6
327
+ }
328
+
329
+ // MARK: - Bridgefy Methods
330
+
331
+ private fun initializeBridgefy(
332
+ apiKey: String,
333
+ verboseLogging: Boolean,
334
+ ) {
335
+ try {
336
+ if (serviceManager.isSDKInitialized()) {
337
+ sendErrorBroadcast("SERVICE_ALREADY_STARTED", "Bridgefy already initialized")
338
+ return
339
+ }
340
+
341
+ val uuid =
342
+ try {
343
+ UUID.fromString(apiKey)
344
+ } catch (e: IllegalArgumentException) {
345
+ sendErrorBroadcast("INVALID_API_KEY", "Invalid API key format: $apiKey")
346
+ return
347
+ }
348
+
349
+ serviceManager.getBridgefy()!!.init(
350
+ uuid,
351
+ this,
352
+ if (verboseLogging) LogType.ConsoleLogger(Log.DEBUG) else LogType.None,
353
+ )
354
+ } catch (e: Exception) {
355
+ // serviceManager.releaseBridgefy()
356
+ sendErrorBroadcast("INITIALIZATION_FAILED", e.message ?: "Unknown error")
357
+ }
358
+ }
359
+
360
+ private fun startBridgefy(
361
+ userId: String?,
362
+ propagationProfile: String,
363
+ ) {
364
+ try {
365
+ if (!serviceManager.isSDKInitialized()) {
366
+ sendErrorBroadcast("SERVICE_NOT_STARTED", "Bridgefy not initialized")
367
+ return
368
+ }
369
+
370
+ if (serviceManager.isSDKStarted()) {
371
+ sendErrorBroadcast("SERVICE_ALREADY_STARTED", "Bridgefy already started")
372
+ return
373
+ }
374
+
375
+ val profile =
376
+ when (propagationProfile.lowercase()) {
377
+ "highDensityNetwork" -> PropagationProfile.HighDensityEnvironment
378
+ "sparseNetwork" -> PropagationProfile.SparseEnvironment
379
+ "longReach" -> PropagationProfile.LongReach
380
+ "shortReach" -> PropagationProfile.ShortReach
381
+ "realTime" -> PropagationProfile.Realtime
382
+ else -> PropagationProfile.Standard
383
+ }
384
+
385
+ val customUserId =
386
+ userId?.let {
387
+ try {
388
+ UUID.fromString(it)
389
+ } catch (e: IllegalArgumentException) {
390
+ null
391
+ }
392
+ }
393
+
394
+ serviceManager.getBridgefy()?.start(customUserId, profile)
395
+ } catch (e: Exception) {
396
+ sendErrorBroadcast("START_FAILED", e.message ?: "Unknown error")
397
+ }
398
+ }
399
+
400
+ private fun stopBridgefy() {
401
+ try {
402
+ if (!serviceManager.isSDKStarted()) {
403
+ sendErrorBroadcast("SERVICE_NOT_STARTED", "Bridgefy not started")
404
+ return
405
+ }
406
+
407
+ serviceManager.getBridgefy()?.stop()
408
+ } catch (e: Exception) {
409
+ sendErrorBroadcast("STOP_FAILED", e.message ?: "Unknown error")
410
+ }
411
+ }
412
+
413
+ private fun sendMessage(
414
+ data: ByteArray,
415
+ transmissionMode: TransmissionMode,
416
+ ) {
417
+ try {
418
+ if (!serviceManager.isSDKStarted()) {
419
+ sendErrorBroadcast("SERVICE_NOT_STARTED", "Bridgefy not started")
420
+ return
421
+ }
422
+
423
+ serviceManager.getBridgefy()?.send(data, transmissionMode)
424
+ } catch (e: Exception) {
425
+ sendErrorBroadcast("SEND_FAILED", e.message ?: "Unknown error")
426
+ }
427
+ }
428
+
429
+ private fun establishSecureConnection(userId: String) {
430
+ try {
431
+ if (!serviceManager.isSDKStarted()) {
432
+ sendErrorBroadcast("SERVICE_NOT_STARTED", "Bridgefy not started")
433
+ return
434
+ }
435
+
436
+ val uuid =
437
+ try {
438
+ UUID.fromString(userId)
439
+ } catch (e: IllegalArgumentException) {
440
+ sendErrorBroadcast("INVALID_MESSAGE", "Invalid user UUID")
441
+ return
442
+ }
443
+
444
+ serviceManager.getBridgefy()?.establishSecureConnection(uuid)
445
+ } catch (e: Exception) {
446
+ sendErrorBroadcast("CONNECTION_FAILED", e.message ?: "Unknown error")
447
+ }
448
+ }
449
+
450
+ // MARK: - BridgefyClient Delegate Methods (SDK 1.2.4)
451
+
452
+ override fun onStarted(userId: UUID) {
453
+ currentUserId = userId.toString()
454
+
455
+ serviceManager.setCurrentUserId(userId.toString())
456
+
457
+ updateNotification("${getHostAppName()}", "")
458
+
459
+ sendBroadcast(
460
+ Intent(EVENT_BRIDGEFY_DID_START).apply {
461
+ putExtra(EXTRA_USER_ID, userId.toString())
462
+ },
463
+ )
464
+ }
465
+
466
+ override fun onStopped() {
467
+ updateNotification("${getHostAppName()}", "")
468
+
469
+ sendBroadcast(Intent(EVENT_BRIDGEFY_DID_STOP))
470
+ }
471
+
472
+ override fun onFailToStart(error: BridgefyException) {
473
+ sendBroadcast(
474
+ Intent(EVENT_BRIDGEFY_FAIL_TO_START).apply {
475
+ putExtra(EXTRA_ERROR_CODE, bundleFromBridgefyException(error))
476
+ putExtra(EXTRA_ERROR_MESSAGE, error.message)
477
+ },
478
+ )
479
+ }
480
+
481
+ override fun onFailToStop(error: BridgefyException) {
482
+ sendBroadcast(
483
+ Intent(EVENT_BRIDGEFY_FAIL_TO_STOP).apply {
484
+ putExtra(EXTRA_ERROR_CODE, bundleFromBridgefyException(error))
485
+ putExtra(EXTRA_ERROR_MESSAGE, error.message)
486
+ },
487
+ )
488
+ }
489
+
490
+ override fun onConnected(peerID: UUID) {
491
+ connectedPeers.add(peerID.toString())
492
+
493
+ sendBroadcast(
494
+ Intent(EVENT_BRIDGEFY_DID_CONNECT).apply {
495
+ putExtra(EXTRA_USER_ID, peerID.toString())
496
+ },
497
+ )
498
+ }
499
+
500
+ override fun onConnectedPeers(connectedPeers: List<UUID>) {
501
+ this.connectedPeers.clear()
502
+ this.connectedPeers.addAll(connectedPeers.map(UUID::toString).distinct())
503
+
504
+ sendBroadcast(
505
+ Intent(EVENT_BRIDGEFY_DID_UPDATE_CONNECTED_PEERS).apply {
506
+ putStringArrayListExtra(EXTRA_CONNECTED_PEERS, ArrayList(connectedPeers.map(UUID::toString)))
507
+ },
508
+ )
509
+ }
510
+
511
+ override fun onDisconnected(peerID: UUID) {
512
+ connectedPeers.remove(peerID.toString())
513
+
514
+ sendBroadcast(
515
+ Intent(EVENT_BRIDGEFY_DID_DISCONNECT).apply {
516
+ putExtra(EXTRA_USER_ID, peerID.toString())
517
+ },
518
+ )
519
+ }
520
+
521
+ override fun onReceiveData(
522
+ data: ByteArray,
523
+ messageID: UUID,
524
+ transmissionMode: TransmissionMode,
525
+ ) {
526
+ sendBroadcast(
527
+ Intent(EVENT_BRIDGEFY_RECEIVE_DATA).apply {
528
+ putExtra(EXTRA_MESSAGE_DATA, data)
529
+ putExtra(EXTRA_MESSAGE_ID, messageID.toString())
530
+ putExtra(EXTRA_TRANSMISSION_MODE, bundleFromTransmissionMode(transmissionMode))
531
+ },
532
+ )
533
+ }
534
+
535
+ override fun onSend(messageID: UUID) {
536
+ sendBroadcast(
537
+ Intent(EVENT_BRIDGEFY_SEND_MESSAGE).apply {
538
+ putExtra(EXTRA_MESSAGE_ID, messageID.toString())
539
+ },
540
+ )
541
+ }
542
+
543
+ override fun onProgressOfSend(
544
+ messageID: UUID,
545
+ position: Int,
546
+ of: Int,
547
+ ) {
548
+ sendBroadcast(
549
+ Intent(EVENT_BRIDGEFY_PROGRESS_OF_SEND).apply {
550
+ putExtra(EXTRA_MESSAGE_ID, messageID.toString())
551
+ putExtra(EXTRA_POSITION, position)
552
+ putExtra(EXTRA_OF, of)
553
+ },
554
+ )
555
+ }
556
+
557
+ override fun onFailToSend(
558
+ messageID: UUID,
559
+ error: BridgefyException,
560
+ ) {
561
+ sendBroadcast(
562
+ Intent(EVENT_BRIDGEFY_FAIL_SENDING).apply {
563
+ putExtra(EXTRA_MESSAGE_ID, messageID.toString())
564
+ putExtra(EXTRA_ERROR_CODE, bundleFromBridgefyException(error))
565
+ putExtra(EXTRA_ERROR_MESSAGE, error.message)
566
+ },
567
+ )
568
+ }
569
+
570
+ override fun onEstablishSecureConnection(userId: UUID) {
571
+ sendBroadcast(
572
+ Intent(EVENT_BRIDGEFY_ESTABLISH_SECURE).apply {
573
+ putExtra(EXTRA_USER_ID, userId.toString())
574
+ },
575
+ )
576
+ }
577
+
578
+ override fun onFailToEstablishSecureConnection(
579
+ userId: UUID,
580
+ error: BridgefyException,
581
+ ) {
582
+ sendBroadcast(
583
+ Intent(EVENT_BRIDGEFY_FAIL_SECURE).apply {
584
+ putExtra(EXTRA_USER_ID, userId.toString())
585
+ putExtra(EXTRA_ERROR_CODE, bundleFromBridgefyException(error))
586
+ putExtra(EXTRA_ERROR_MESSAGE, error.message)
587
+ },
588
+ )
589
+ }
590
+
591
+ override fun onDestroySession() = sendBroadcast(Intent(EVENT_BRIDGEFY_DID_DESTROY_SESSION))
592
+
593
+ override fun onFailToDestroySession(error: BridgefyException) {
594
+ sendBroadcast(
595
+ Intent(EVENT_BRIDGEFY_FAIL_TO_DESTROY_SESSION).apply {
596
+ putExtra(EXTRA_ERROR_CODE, bundleFromBridgefyException(error))
597
+ putExtra(EXTRA_ERROR_MESSAGE, error.message)
598
+ },
599
+ )
600
+ }
601
+
602
+ // MARK: - Helper Methods
603
+
604
+ private fun sendErrorBroadcast(
605
+ code: String,
606
+ message: String,
607
+ ) {
608
+ sendBroadcast(
609
+ Intent(EVENT_BRIDGEFY_FAIL_TO_START).apply {
610
+ putExtra(EXTRA_ERROR_CODE, code)
611
+ putExtra(EXTRA_ERROR_MESSAGE, message)
612
+ },
613
+ )
614
+ }
615
+
616
+ override fun onDestroy() {
617
+ if (serviceManager.isSDKStarted()) {
618
+ stopBridgefy()
619
+ }
620
+ // Clear state when service is destroyed
621
+ serviceManager.clearState()
622
+ serviceManager.refreshBridgefy()
623
+ super.onDestroy()
624
+ }
625
+ }