react-native-push-signal 0.1.0
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/LICENSE +20 -0
- package/PushSignal.podspec +31 -0
- package/README.md +125 -0
- package/README.ru.md +125 -0
- package/android/CMakeLists.txt +24 -0
- package/android/build.gradle +115 -0
- package/android/src/main/AndroidManifest.xml +18 -0
- package/android/src/main/cpp/cpp-adapter.cpp +11 -0
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignal.kt +44 -0
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignalCenter.kt +353 -0
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignalInitProvider.kt +34 -0
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignalMessagingService.kt +15 -0
- package/android/src/main/java/com/margelo/nitro/pushsignal/PushSignalPackage.kt +22 -0
- package/ios/PushSignal.swift +38 -0
- package/ios/PushSignalCenter.swift +430 -0
- package/ios/PushSignalLaunchStore.h +21 -0
- package/ios/PushSignalLaunchStore.m +26 -0
- package/lib/module/PushSignal.nitro.js +4 -0
- package/lib/module/PushSignal.nitro.js.map +1 -0
- package/lib/module/index.js +4 -0
- package/lib/module/index.js.map +1 -0
- package/lib/module/package.json +1 -0
- package/lib/module/pushSignal.js +19 -0
- package/lib/module/pushSignal.js.map +1 -0
- package/lib/module/pushSignal.native.js +46 -0
- package/lib/module/pushSignal.native.js.map +1 -0
- package/lib/typescript/package.json +1 -0
- package/lib/typescript/src/PushSignal.nitro.d.ts +33 -0
- package/lib/typescript/src/PushSignal.nitro.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -0
- package/lib/typescript/src/index.d.ts.map +1 -0
- package/lib/typescript/src/pushSignal.d.ts +8 -0
- package/lib/typescript/src/pushSignal.d.ts.map +1 -0
- package/lib/typescript/src/pushSignal.native.d.ts +8 -0
- package/lib/typescript/src/pushSignal.native.d.ts.map +1 -0
- package/nitro.json +23 -0
- package/nitrogen/generated/android/c++/JAndroidFirebaseConfig.hpp +70 -0
- package/nitrogen/generated/android/c++/JFunc_void_PushMessage.hpp +80 -0
- package/nitrogen/generated/android/c++/JHybridPushSignalSpec.cpp +138 -0
- package/nitrogen/generated/android/c++/JHybridPushSignalSpec.hpp +68 -0
- package/nitrogen/generated/android/c++/JPermissionStatus.hpp +61 -0
- package/nitrogen/generated/android/c++/JPushCredentials.hpp +70 -0
- package/nitrogen/generated/android/c++/JPushEnvironment.hpp +58 -0
- package/nitrogen/generated/android/c++/JPushMessage.hpp +84 -0
- package/nitrogen/generated/android/c++/JPushPlatform.hpp +58 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/AndroidFirebaseConfig.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/Func_void_PushMessage.kt +78 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/HybridPushSignalSpec.kt +87 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PermissionStatus.kt +24 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushCredentials.kt +61 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushEnvironment.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushMessage.kt +66 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/PushPlatform.kt +23 -0
- package/nitrogen/generated/android/kotlin/com/margelo/nitro/pushsignal/pushsignalOnLoad.kt +35 -0
- package/nitrogen/generated/android/pushsignal+autolinking.cmake +81 -0
- package/nitrogen/generated/android/pushsignal+autolinking.gradle +27 -0
- package/nitrogen/generated/android/pushsignalOnLoad.cpp +56 -0
- package/nitrogen/generated/android/pushsignalOnLoad.hpp +34 -0
- package/nitrogen/generated/ios/PushSignal+autolinking.rb +62 -0
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.cpp +65 -0
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Bridge.hpp +257 -0
- package/nitrogen/generated/ios/PushSignal-Swift-Cxx-Umbrella.hpp +66 -0
- package/nitrogen/generated/ios/PushSignalAutolinking.mm +33 -0
- package/nitrogen/generated/ios/PushSignalAutolinking.swift +26 -0
- package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.cpp +11 -0
- package/nitrogen/generated/ios/c++/HybridPushSignalSpecSwift.hpp +137 -0
- package/nitrogen/generated/ios/swift/AndroidFirebaseConfig.swift +96 -0
- package/nitrogen/generated/ios/swift/Func_void_PermissionStatus.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_PushCredentials.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_PushMessage.swift +46 -0
- package/nitrogen/generated/ios/swift/Func_void_std__exception_ptr.swift +46 -0
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec.swift +60 -0
- package/nitrogen/generated/ios/swift/HybridPushSignalSpec_cxx.swift +226 -0
- package/nitrogen/generated/ios/swift/PermissionStatus.swift +44 -0
- package/nitrogen/generated/ios/swift/PushCredentials.swift +45 -0
- package/nitrogen/generated/ios/swift/PushEnvironment.swift +40 -0
- package/nitrogen/generated/ios/swift/PushMessage.swift +97 -0
- package/nitrogen/generated/ios/swift/PushPlatform.swift +40 -0
- package/nitrogen/generated/shared/c++/AndroidFirebaseConfig.hpp +96 -0
- package/nitrogen/generated/shared/c++/HybridPushSignalSpec.cpp +26 -0
- package/nitrogen/generated/shared/c++/HybridPushSignalSpec.hpp +79 -0
- package/nitrogen/generated/shared/c++/PermissionStatus.hpp +80 -0
- package/nitrogen/generated/shared/c++/PushCredentials.hpp +97 -0
- package/nitrogen/generated/shared/c++/PushEnvironment.hpp +76 -0
- package/nitrogen/generated/shared/c++/PushMessage.hpp +97 -0
- package/nitrogen/generated/shared/c++/PushPlatform.hpp +76 -0
- package/package.json +187 -0
- package/src/PushSignal.nitro.ts +37 -0
- package/src/index.tsx +16 -0
- package/src/pushSignal.native.tsx +67 -0
- package/src/pushSignal.tsx +32 -0
|
@@ -0,0 +1,353 @@
|
|
|
1
|
+
package com.margelo.nitro.pushsignal
|
|
2
|
+
|
|
3
|
+
import android.Manifest
|
|
4
|
+
import android.app.Activity
|
|
5
|
+
import android.app.Application
|
|
6
|
+
import android.content.Context
|
|
7
|
+
import android.content.Intent
|
|
8
|
+
import android.content.pm.PackageManager
|
|
9
|
+
import android.os.Build
|
|
10
|
+
import android.os.Bundle
|
|
11
|
+
import androidx.activity.ComponentActivity
|
|
12
|
+
import androidx.activity.result.ActivityResultLauncher
|
|
13
|
+
import androidx.activity.result.contract.ActivityResultContracts
|
|
14
|
+
import androidx.core.app.NotificationManagerCompat
|
|
15
|
+
import androidx.core.content.ContextCompat
|
|
16
|
+
import com.google.firebase.FirebaseApp
|
|
17
|
+
import com.google.firebase.FirebaseOptions
|
|
18
|
+
import com.google.firebase.messaging.FirebaseMessaging
|
|
19
|
+
import com.google.android.gms.tasks.Tasks
|
|
20
|
+
import com.google.firebase.messaging.RemoteMessage
|
|
21
|
+
import java.util.Collections
|
|
22
|
+
import java.util.WeakHashMap
|
|
23
|
+
import java.util.concurrent.CopyOnWriteArrayList
|
|
24
|
+
|
|
25
|
+
internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
26
|
+
private const val PREFS_NAME = "pushsignal"
|
|
27
|
+
private const val PREF_ASKED_PERMISSION = "asked_notifications"
|
|
28
|
+
private const val EXTRA_HANDLED = "pushsignal.handled"
|
|
29
|
+
private const val PERMISSION_LAUNCHER_KEY = "com.margelo.nitro.pushsignal.permission"
|
|
30
|
+
|
|
31
|
+
private val lock = Any()
|
|
32
|
+
@Volatile private var application: Application? = null
|
|
33
|
+
@Volatile private var currentActivity: Activity? = null
|
|
34
|
+
@Volatile private var permissionLauncher: ActivityResultLauncher<String>? = null
|
|
35
|
+
@Volatile private var onMessage: ((PushMessage) -> Unit)? = null
|
|
36
|
+
@Volatile private var onNotificationPress: ((PushMessage) -> Unit)? = null
|
|
37
|
+
@Volatile private var pendingPress: PushMessage? = null
|
|
38
|
+
private val permissionWaiters = CopyOnWriteArrayList<(PermissionStatus) -> Unit>()
|
|
39
|
+
private val registeredActivities = Collections.newSetFromMap(WeakHashMap<Activity, Boolean>())
|
|
40
|
+
@Volatile private var pendingFirebaseConfig: AndroidFirebaseConfig? = null
|
|
41
|
+
|
|
42
|
+
fun attach(context: Context) {
|
|
43
|
+
val app = context.applicationContext as? Application ?: return
|
|
44
|
+
if (application === app) {
|
|
45
|
+
return
|
|
46
|
+
}
|
|
47
|
+
application?.unregisterActivityLifecycleCallbacks(this)
|
|
48
|
+
application = app
|
|
49
|
+
app.registerActivityLifecycleCallbacks(this)
|
|
50
|
+
app.currentActivityOrNull()?.let { activity ->
|
|
51
|
+
currentActivity = activity
|
|
52
|
+
registerActivity(activity)
|
|
53
|
+
handleIntent(activity.intent)
|
|
54
|
+
}
|
|
55
|
+
pendingFirebaseConfig?.let { config ->
|
|
56
|
+
pendingFirebaseConfig = null
|
|
57
|
+
applyFirebaseConfig(app, config)
|
|
58
|
+
}
|
|
59
|
+
}
|
|
60
|
+
|
|
61
|
+
fun initialize(config: AndroidFirebaseConfig) {
|
|
62
|
+
if (!config.hasRequiredFields()) {
|
|
63
|
+
return
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
val context = application
|
|
67
|
+
if (context == null) {
|
|
68
|
+
pendingFirebaseConfig = config
|
|
69
|
+
return
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
applyFirebaseConfig(context, config)
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
fun setOnMessage(callback: (PushMessage) -> Unit) {
|
|
76
|
+
onMessage = callback
|
|
77
|
+
}
|
|
78
|
+
|
|
79
|
+
fun setOnNotificationPress(callback: (PushMessage) -> Unit) {
|
|
80
|
+
onNotificationPress = callback
|
|
81
|
+
val pending = synchronized(lock) {
|
|
82
|
+
val message = pendingPress
|
|
83
|
+
pendingPress = null
|
|
84
|
+
message
|
|
85
|
+
}
|
|
86
|
+
if (pending != null) {
|
|
87
|
+
callback(pending)
|
|
88
|
+
}
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
fun getPermissionStatus(): PermissionStatus {
|
|
92
|
+
val context = application ?: return PermissionStatus.NOTDETERMINED
|
|
93
|
+
val notificationsEnabled = NotificationManagerCompat.from(context).areNotificationsEnabled()
|
|
94
|
+
|
|
95
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
|
96
|
+
return if (notificationsEnabled) {
|
|
97
|
+
PermissionStatus.AUTHORIZED
|
|
98
|
+
} else {
|
|
99
|
+
PermissionStatus.DENIED
|
|
100
|
+
}
|
|
101
|
+
}
|
|
102
|
+
|
|
103
|
+
val granted =
|
|
104
|
+
ContextCompat.checkSelfPermission(context, Manifest.permission.POST_NOTIFICATIONS) ==
|
|
105
|
+
PackageManager.PERMISSION_GRANTED
|
|
106
|
+
if (granted && notificationsEnabled) {
|
|
107
|
+
return PermissionStatus.AUTHORIZED
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
val asked =
|
|
111
|
+
context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
|
112
|
+
.getBoolean(PREF_ASKED_PERMISSION, false)
|
|
113
|
+
return if (!asked && !granted) {
|
|
114
|
+
PermissionStatus.NOTDETERMINED
|
|
115
|
+
} else {
|
|
116
|
+
PermissionStatus.DENIED
|
|
117
|
+
}
|
|
118
|
+
}
|
|
119
|
+
|
|
120
|
+
fun requestPermission(onResult: (PermissionStatus) -> Unit) {
|
|
121
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
|
122
|
+
onResult(getPermissionStatus())
|
|
123
|
+
return
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
val activity = currentActivity
|
|
127
|
+
val launcher = permissionLauncher
|
|
128
|
+
if (activity == null || launcher == null) {
|
|
129
|
+
onResult(getPermissionStatus())
|
|
130
|
+
return
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
if (
|
|
134
|
+
ContextCompat.checkSelfPermission(activity, Manifest.permission.POST_NOTIFICATIONS) ==
|
|
135
|
+
PackageManager.PERMISSION_GRANTED
|
|
136
|
+
) {
|
|
137
|
+
onResult(getPermissionStatus())
|
|
138
|
+
return
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
permissionWaiters.add(onResult)
|
|
142
|
+
launcher.launch(Manifest.permission.POST_NOTIFICATIONS)
|
|
143
|
+
}
|
|
144
|
+
|
|
145
|
+
fun fetchToken(): String {
|
|
146
|
+
val context = application
|
|
147
|
+
?: throw IllegalStateException("PushSignal is not initialized")
|
|
148
|
+
|
|
149
|
+
try {
|
|
150
|
+
if (FirebaseApp.getApps(context).isEmpty()) {
|
|
151
|
+
FirebaseApp.initializeApp(context)
|
|
152
|
+
}
|
|
153
|
+
FirebaseApp.getInstance()
|
|
154
|
+
} catch (error: IllegalStateException) {
|
|
155
|
+
throw IllegalStateException(
|
|
156
|
+
"Firebase is not configured. Call initialize({ projectId, applicationId, apiKey, gcmSenderId }) or add google-services.json.",
|
|
157
|
+
error
|
|
158
|
+
)
|
|
159
|
+
}
|
|
160
|
+
|
|
161
|
+
val task = FirebaseMessaging.getInstance().token
|
|
162
|
+
val token = try {
|
|
163
|
+
Tasks.await(task)
|
|
164
|
+
} catch (error: Exception) {
|
|
165
|
+
throw IllegalStateException(
|
|
166
|
+
"Failed to get an FCM token. Call initialize({ projectId, applicationId, apiKey, gcmSenderId }) or add google-services.json.",
|
|
167
|
+
error
|
|
168
|
+
)
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
if (token.isNullOrEmpty()) {
|
|
172
|
+
throw IllegalStateException("Firebase returned an empty FCM token")
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
return token
|
|
176
|
+
}
|
|
177
|
+
|
|
178
|
+
fun emitMessage(message: PushMessage) {
|
|
179
|
+
onMessage?.invoke(message)
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
fun emitMessage(remoteMessage: RemoteMessage) {
|
|
183
|
+
emitMessage(remoteMessage.toPushMessage())
|
|
184
|
+
}
|
|
185
|
+
|
|
186
|
+
override fun onActivityCreated(activity: Activity, savedInstanceState: Bundle?) {
|
|
187
|
+
currentActivity = activity
|
|
188
|
+
registerActivity(activity)
|
|
189
|
+
handleIntent(activity.intent)
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
override fun onActivityStarted(activity: Activity) = Unit
|
|
193
|
+
|
|
194
|
+
override fun onActivityResumed(activity: Activity) {
|
|
195
|
+
currentActivity = activity
|
|
196
|
+
handleIntent(activity.intent)
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
override fun onActivityPaused(activity: Activity) {
|
|
200
|
+
if (currentActivity === activity) {
|
|
201
|
+
currentActivity = null
|
|
202
|
+
}
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
override fun onActivityStopped(activity: Activity) = Unit
|
|
206
|
+
|
|
207
|
+
override fun onActivitySaveInstanceState(activity: Activity, outState: Bundle) = Unit
|
|
208
|
+
|
|
209
|
+
override fun onActivityDestroyed(activity: Activity) {
|
|
210
|
+
if (currentActivity === activity) {
|
|
211
|
+
currentActivity = null
|
|
212
|
+
permissionLauncher = null
|
|
213
|
+
}
|
|
214
|
+
}
|
|
215
|
+
|
|
216
|
+
private fun registerActivity(activity: Activity) {
|
|
217
|
+
if (!registeredActivities.add(activity)) {
|
|
218
|
+
return
|
|
219
|
+
}
|
|
220
|
+
|
|
221
|
+
val componentActivity = activity as? ComponentActivity ?: return
|
|
222
|
+
|
|
223
|
+
permissionLauncher =
|
|
224
|
+
componentActivity.activityResultRegistry.register(
|
|
225
|
+
PERMISSION_LAUNCHER_KEY,
|
|
226
|
+
componentActivity,
|
|
227
|
+
ActivityResultContracts.RequestPermission()
|
|
228
|
+
) {
|
|
229
|
+
activity
|
|
230
|
+
.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE)
|
|
231
|
+
.edit()
|
|
232
|
+
.putBoolean(PREF_ASKED_PERMISSION, true)
|
|
233
|
+
.apply()
|
|
234
|
+
val status = getPermissionStatus()
|
|
235
|
+
val waiters = permissionWaiters.toList()
|
|
236
|
+
permissionWaiters.clear()
|
|
237
|
+
waiters.forEach { it(status) }
|
|
238
|
+
}
|
|
239
|
+
|
|
240
|
+
componentActivity.addOnNewIntentListener { intent ->
|
|
241
|
+
handleIntent(intent)
|
|
242
|
+
}
|
|
243
|
+
}
|
|
244
|
+
|
|
245
|
+
private fun handleIntent(intent: Intent?) {
|
|
246
|
+
if (intent == null || !intent.isPushTap() || intent.getBooleanExtra(EXTRA_HANDLED, false)) {
|
|
247
|
+
return
|
|
248
|
+
}
|
|
249
|
+
|
|
250
|
+
intent.putExtra(EXTRA_HANDLED, true)
|
|
251
|
+
emitPress(intent.toPushMessage())
|
|
252
|
+
}
|
|
253
|
+
|
|
254
|
+
private fun applyFirebaseConfig(context: Context, config: AndroidFirebaseConfig) {
|
|
255
|
+
if (!config.hasRequiredFields() || FirebaseApp.getApps(context).isNotEmpty()) {
|
|
256
|
+
return
|
|
257
|
+
}
|
|
258
|
+
|
|
259
|
+
try {
|
|
260
|
+
val options =
|
|
261
|
+
FirebaseOptions.Builder()
|
|
262
|
+
.setProjectId(config.projectId!!.trim())
|
|
263
|
+
.setApplicationId(config.applicationId!!.trim())
|
|
264
|
+
.setApiKey(config.apiKey!!.trim())
|
|
265
|
+
.setGcmSenderId(config.gcmSenderId!!.trim())
|
|
266
|
+
.build()
|
|
267
|
+
FirebaseApp.initializeApp(context, options)
|
|
268
|
+
} catch (_: Exception) {
|
|
269
|
+
// Keep initialize quiet; getCredentials reports a missing Firebase app.
|
|
270
|
+
}
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
private fun emitPress(message: PushMessage) {
|
|
274
|
+
val listener = onNotificationPress
|
|
275
|
+
if (listener != null) {
|
|
276
|
+
listener(message)
|
|
277
|
+
} else {
|
|
278
|
+
synchronized(lock) {
|
|
279
|
+
pendingPress = message
|
|
280
|
+
}
|
|
281
|
+
}
|
|
282
|
+
}
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
private fun Application.currentActivityOrNull(): Activity? {
|
|
286
|
+
return try {
|
|
287
|
+
val activityThreadClass = Class.forName("android.app.ActivityThread")
|
|
288
|
+
val activityThread = activityThreadClass.getMethod("currentActivityThread").invoke(null)
|
|
289
|
+
val activitiesField = activityThreadClass.getDeclaredField("mActivities")
|
|
290
|
+
activitiesField.isAccessible = true
|
|
291
|
+
val activities = activitiesField.get(activityThread) as Map<*, *>
|
|
292
|
+
activities.values.firstNotNullOfOrNull { record ->
|
|
293
|
+
val recordClass = record?.javaClass ?: return@firstNotNullOfOrNull null
|
|
294
|
+
val paused = recordClass.getDeclaredField("paused").apply { isAccessible = true }.getBoolean(record)
|
|
295
|
+
if (paused) {
|
|
296
|
+
return@firstNotNullOfOrNull null
|
|
297
|
+
}
|
|
298
|
+
recordClass.getDeclaredField("activity").apply { isAccessible = true }.get(record) as? Activity
|
|
299
|
+
}
|
|
300
|
+
} catch (_: Exception) {
|
|
301
|
+
null
|
|
302
|
+
}
|
|
303
|
+
}
|
|
304
|
+
|
|
305
|
+
private fun Intent.isPushTap(): Boolean {
|
|
306
|
+
val extras = extras ?: return false
|
|
307
|
+
return extras.containsKey("google.message_id") ||
|
|
308
|
+
extras.containsKey("google.sent_time") ||
|
|
309
|
+
extras.containsKey("gcm.n.e") ||
|
|
310
|
+
extras.containsKey("gcm.notification.title")
|
|
311
|
+
}
|
|
312
|
+
|
|
313
|
+
private fun Intent.toPushMessage(): PushMessage {
|
|
314
|
+
val extras = extras ?: Bundle()
|
|
315
|
+
val data = linkedMapOf<String, String>()
|
|
316
|
+
for (key in extras.keySet()) {
|
|
317
|
+
if (key.startsWith("google.") || key.startsWith("gcm.") || key == EXTRA_HANDLED_KEY) {
|
|
318
|
+
continue
|
|
319
|
+
}
|
|
320
|
+
@Suppress("DEPRECATION")
|
|
321
|
+
val value = extras.get(key) ?: continue
|
|
322
|
+
data[key] = value.toString()
|
|
323
|
+
}
|
|
324
|
+
|
|
325
|
+
return PushMessage(
|
|
326
|
+
extras.getString("google.message_id"),
|
|
327
|
+
extras.getString("gcm.n.title")
|
|
328
|
+
?: extras.getString("gcm.notification.title")
|
|
329
|
+
?: extras.getString("title"),
|
|
330
|
+
extras.getString("gcm.n.body")
|
|
331
|
+
?: extras.getString("gcm.notification.body")
|
|
332
|
+
?: extras.getString("body"),
|
|
333
|
+
data
|
|
334
|
+
)
|
|
335
|
+
}
|
|
336
|
+
|
|
337
|
+
private fun AndroidFirebaseConfig.hasRequiredFields(): Boolean {
|
|
338
|
+
return !projectId.isNullOrBlank() &&
|
|
339
|
+
!applicationId.isNullOrBlank() &&
|
|
340
|
+
!apiKey.isNullOrBlank() &&
|
|
341
|
+
!gcmSenderId.isNullOrBlank()
|
|
342
|
+
}
|
|
343
|
+
|
|
344
|
+
private const val EXTRA_HANDLED_KEY = "pushsignal.handled"
|
|
345
|
+
|
|
346
|
+
internal fun RemoteMessage.toPushMessage(): PushMessage {
|
|
347
|
+
return PushMessage(
|
|
348
|
+
messageId,
|
|
349
|
+
notification?.title,
|
|
350
|
+
notification?.body,
|
|
351
|
+
data
|
|
352
|
+
)
|
|
353
|
+
}
|
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
package com.margelo.nitro.pushsignal
|
|
2
|
+
|
|
3
|
+
import android.content.ContentProvider
|
|
4
|
+
import android.content.ContentValues
|
|
5
|
+
import android.database.Cursor
|
|
6
|
+
import android.net.Uri
|
|
7
|
+
|
|
8
|
+
class PushSignalInitProvider : ContentProvider() {
|
|
9
|
+
override fun onCreate(): Boolean {
|
|
10
|
+
context?.let(PushSignalCenter::attach)
|
|
11
|
+
return true
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
override fun query(
|
|
15
|
+
uri: Uri,
|
|
16
|
+
projection: Array<out String>?,
|
|
17
|
+
selection: String?,
|
|
18
|
+
selectionArgs: Array<out String>?,
|
|
19
|
+
sortOrder: String?
|
|
20
|
+
): Cursor? = null
|
|
21
|
+
|
|
22
|
+
override fun getType(uri: Uri): String? = null
|
|
23
|
+
|
|
24
|
+
override fun insert(uri: Uri, values: ContentValues?): Uri? = null
|
|
25
|
+
|
|
26
|
+
override fun delete(uri: Uri, selection: String?, selectionArgs: Array<out String>?): Int = 0
|
|
27
|
+
|
|
28
|
+
override fun update(
|
|
29
|
+
uri: Uri,
|
|
30
|
+
values: ContentValues?,
|
|
31
|
+
selection: String?,
|
|
32
|
+
selectionArgs: Array<out String>?
|
|
33
|
+
): Int = 0
|
|
34
|
+
}
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
package com.margelo.nitro.pushsignal
|
|
2
|
+
|
|
3
|
+
import com.google.firebase.messaging.FirebaseMessagingService
|
|
4
|
+
import com.google.firebase.messaging.RemoteMessage
|
|
5
|
+
|
|
6
|
+
class PushSignalMessagingService : FirebaseMessagingService() {
|
|
7
|
+
override fun onCreate() {
|
|
8
|
+
super.onCreate()
|
|
9
|
+
PushSignalCenter.attach(applicationContext)
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
override fun onMessageReceived(message: RemoteMessage) {
|
|
13
|
+
PushSignalCenter.emitMessage(message)
|
|
14
|
+
}
|
|
15
|
+
}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
package com.margelo.nitro.pushsignal
|
|
2
|
+
|
|
3
|
+
import com.facebook.react.BaseReactPackage
|
|
4
|
+
import com.facebook.react.bridge.NativeModule
|
|
5
|
+
import com.facebook.react.bridge.ReactApplicationContext
|
|
6
|
+
import com.facebook.react.module.model.ReactModuleInfoProvider
|
|
7
|
+
|
|
8
|
+
class PushSignalPackage : BaseReactPackage() {
|
|
9
|
+
override fun getModule(name: String, reactContext: ReactApplicationContext): NativeModule? {
|
|
10
|
+
return null
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
override fun getReactModuleInfoProvider(): ReactModuleInfoProvider {
|
|
14
|
+
return ReactModuleInfoProvider { HashMap() }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
companion object {
|
|
18
|
+
init {
|
|
19
|
+
System.loadLibrary("pushsignal")
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
import NitroModules
|
|
2
|
+
|
|
3
|
+
class PushSignal: HybridPushSignalSpec {
|
|
4
|
+
override init() {
|
|
5
|
+
super.init()
|
|
6
|
+
PushSignalCenter.shared.install()
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
func initialize(config: AndroidFirebaseConfig) throws {
|
|
10
|
+
_ = config
|
|
11
|
+
}
|
|
12
|
+
|
|
13
|
+
func getPermissionStatus() throws -> Promise<PermissionStatus> {
|
|
14
|
+
return Promise.async {
|
|
15
|
+
await PushSignalCenter.shared.permissionStatus()
|
|
16
|
+
}
|
|
17
|
+
}
|
|
18
|
+
|
|
19
|
+
func requestPermission() throws -> Promise<PermissionStatus> {
|
|
20
|
+
return Promise.async {
|
|
21
|
+
await PushSignalCenter.shared.requestPermission()
|
|
22
|
+
}
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
func getCredentials() throws -> Promise<PushCredentials> {
|
|
26
|
+
return Promise.async {
|
|
27
|
+
try await PushSignalCenter.shared.fetchCredentials()
|
|
28
|
+
}
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
func setOnMessage(callback: @escaping (PushMessage) -> Void) throws {
|
|
32
|
+
PushSignalCenter.shared.onMessage = callback
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
func setOnNotificationPress(callback: @escaping (PushMessage) -> Void) throws {
|
|
36
|
+
PushSignalCenter.shared.onNotificationPress = callback
|
|
37
|
+
}
|
|
38
|
+
}
|