react-native-push-signal 0.1.9 → 0.1.10
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/README.md +48 -1
- package/README.ru.md +48 -1
- package/android/src/main/AndroidManifest.xml +7 -0
- package/android/src/main/java/com/pushsignal/PushModels.kt +23 -0
- package/android/src/main/java/com/pushsignal/PushSignalCenter.kt +151 -17
- package/android/src/main/java/com/pushsignal/PushSignalModule.kt +30 -2
- package/ios/PushSignal.mm +18 -0
- package/lib/module/NativePushSignal.js.map +1 -1
- package/lib/module/PushSignalError.js +29 -0
- package/lib/module/PushSignalError.js.map +1 -0
- package/lib/module/index.js +2 -1
- package/lib/module/index.js.map +1 -1
- package/lib/module/pushSignal.js +3 -0
- package/lib/module/pushSignal.js.map +1 -1
- package/lib/module/pushSignal.native.js +51 -4
- package/lib/module/pushSignal.native.js.map +1 -1
- package/lib/typescript/src/NativePushSignal.d.ts +19 -0
- package/lib/typescript/src/NativePushSignal.d.ts.map +1 -1
- package/lib/typescript/src/PushSignalError.d.ts +22 -0
- package/lib/typescript/src/PushSignalError.d.ts.map +1 -0
- package/lib/typescript/src/index.d.ts +3 -2
- package/lib/typescript/src/index.d.ts.map +1 -1
- package/lib/typescript/src/pushSignal.d.ts +2 -1
- package/lib/typescript/src/pushSignal.d.ts.map +1 -1
- package/lib/typescript/src/pushSignal.native.d.ts +2 -1
- package/lib/typescript/src/pushSignal.native.d.ts.map +1 -1
- package/lib/typescript/src/types.d.ts +18 -0
- package/lib/typescript/src/types.d.ts.map +1 -1
- package/package.json +1 -1
- package/src/NativePushSignal.ts +20 -0
- package/src/PushSignalError.ts +29 -0
- package/src/index.tsx +4 -0
- package/src/pushSignal.native.tsx +68 -4
- package/src/pushSignal.tsx +5 -0
- package/src/types.ts +28 -0
package/README.md
CHANGED
|
@@ -115,7 +115,7 @@ If `getCredentials()` throws `Failed to get an FCM token: SERVICE_NOT_AVAILABLE`
|
|
|
115
115
|
Before requesting the token the library checks Google Play services and retries a few times with backoff, but some causes can only be fixed on the device:
|
|
116
116
|
|
|
117
117
|
- **Google account.** The device must be signed into a Google account. FCM does not issue a token without one.
|
|
118
|
-
- **Google Play services.** They must be installed, enabled and up to date. On a China-only ROM without GMS, FCM cannot work at all — you need another push provider.
|
|
118
|
+
- **Google Play services.** They must be installed, enabled and up to date. On a China-only ROM without GMS, FCM cannot work at all — you need another push provider; see [Detecting a non-Google device](#detecting-a-non-google-device-getdiagnostics-and-pushsignalerror).
|
|
119
119
|
- **Network.** Check connectivity and disable VPN and private DNS.
|
|
120
120
|
- **MIUI / HyperOS.** Enable autostart and remove battery restrictions: Settings → Apps → your app → Autostart; Battery → No restrictions. Allow background data for the app.
|
|
121
121
|
|
|
@@ -125,6 +125,53 @@ What to look for in the logs:
|
|
|
125
125
|
adb logcat | grep -iE "SERVICE_NOT_AVAILABLE|FirebaseMessaging|PushSignal"
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
### Detecting a non-Google device: `getDiagnostics()` and `PushSignalError`
|
|
129
|
+
|
|
130
|
+
When Google Play services cannot serve FCM, the library detects it and tells you which service to use instead — both in the error message and as structured data, so the cause is visible in React Native logs.
|
|
131
|
+
|
|
132
|
+
`initialize()` and `getCredentials()` reject with `PushSignalError`:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { getCredentials, PushSignalError } from 'react-native-push-signal';
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const credentials = await getCredentials();
|
|
139
|
+
} catch (error) {
|
|
140
|
+
if (error instanceof PushSignalError) {
|
|
141
|
+
console.warn(error.code); // E_GMS_MISSING, E_FCM_TOKEN, ...
|
|
142
|
+
console.warn(error.message); // "... Use HMS Push Kit (Huawei Push) instead of the standard Google service."
|
|
143
|
+
console.warn(error.provider); // 'hms'
|
|
144
|
+
console.warn(error.hint); // actionable sentence
|
|
145
|
+
console.warn(error.diagnostics); // full device/provider snapshot
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
You can also inspect diagnostics without requesting a token:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { getDiagnostics } from 'react-native-push-signal';
|
|
154
|
+
|
|
155
|
+
const diagnostics = await getDiagnostics();
|
|
156
|
+
// { platform, gmsAvailable, gmsStatus, manufacturer, brand, model,
|
|
157
|
+
// provider, providerName, providerInstalled?, hint? }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Provider suggested when GMS is unavailable:
|
|
161
|
+
|
|
162
|
+
| Manufacturer | `provider` | Service |
|
|
163
|
+
| --------------------------- | ------------ | --------------------------------------- |
|
|
164
|
+
| HUAWEI / HONOR | `hms` | HMS Push Kit (Huawei Push) |
|
|
165
|
+
| Xiaomi / Redmi / POCO | `mi_push` | Mi Push (Xiaomi Push) |
|
|
166
|
+
| OPPO / OnePlus / realme | `oppo_push` | OPPO Push (HeyTap) |
|
|
167
|
+
| vivo / iQOO | `vivo_push` | vivo Push |
|
|
168
|
+
| Meizu | `meizu_push` | Meizu Push |
|
|
169
|
+
| anything else | `unknown` | generic “use another provider” |
|
|
170
|
+
|
|
171
|
+
`providerInstalled` is `true` only when the provider service app was positively found on the device (`com.huawei.hwid`, `com.xiaomi.xmsf`); otherwise it is omitted. iOS always reports `provider: 'apns'`. The library never logs for you — pass the data wherever you need.
|
|
172
|
+
|
|
173
|
+
Error codes: `E_GMS_MISSING`, `E_GMS_DISABLED`, `E_GMS_UPDATE_REQUIRED`, `E_GMS_INVALID`, `E_GMS_UNAVAILABLE`, `E_FCM_TOKEN`, `E_FIREBASE_CONFIG`, `E_NOT_INITIALIZED`.
|
|
174
|
+
|
|
128
175
|
## Incoming messages vs taps
|
|
129
176
|
|
|
130
177
|
| App state | iOS | Android (notification payload) | Android (data-only) |
|
package/README.ru.md
CHANGED
|
@@ -115,7 +115,7 @@ apply plugin: "com.google.gms.google-services"
|
|
|
115
115
|
Перед запросом токена библиотека проверяет Google Play services и делает несколько попыток с паузами, но часть причин лечится только на устройстве:
|
|
116
116
|
|
|
117
117
|
- **Google-аккаунт.** На устройстве должен быть выполнен вход в Google-аккаунт. Без него FCM токен не выдаёт.
|
|
118
|
-
- **Google Play services.** Должны быть установлены, включены и обновлены. На китайской прошивке без GMS FCM не заработает в принципе — нужен другой провайдер
|
|
118
|
+
- **Google Play services.** Должны быть установлены, включены и обновлены. На китайской прошивке без GMS FCM не заработает в принципе — нужен другой провайдер пушей; см. [Определение не‑Google устройства](#определение-неgoogle-устройства-getdiagnostics-и-pushsignalerror).
|
|
119
119
|
- **Сеть.** Проверьте интернет, отключите VPN и приватный DNS.
|
|
120
120
|
- **MIUI / HyperOS.** Включите автозапуск и снимите ограничения батареи: Настройки → Приложения → «ваше приложение» → Автозапуск; Батарея → Без ограничений. Разрешите приложению фоновые данные.
|
|
121
121
|
|
|
@@ -125,6 +125,53 @@ apply plugin: "com.google.gms.google-services"
|
|
|
125
125
|
adb logcat | grep -iE "SERVICE_NOT_AVAILABLE|FirebaseMessaging|PushSignal"
|
|
126
126
|
```
|
|
127
127
|
|
|
128
|
+
### Определение не‑Google устройства: `getDiagnostics()` и `PushSignalError`
|
|
129
|
+
|
|
130
|
+
Когда Google Play services не могут обслуживать FCM, библиотека это определяет и подсказывает, какой сервис использовать вместо стандартного — в тексте ошибки и в структурированном виде, чтобы причина была видна в логах React Native.
|
|
131
|
+
|
|
132
|
+
`initialize()` и `getCredentials()` отклоняются с `PushSignalError`:
|
|
133
|
+
|
|
134
|
+
```ts
|
|
135
|
+
import { getCredentials, PushSignalError } from 'react-native-push-signal';
|
|
136
|
+
|
|
137
|
+
try {
|
|
138
|
+
const credentials = await getCredentials();
|
|
139
|
+
} catch (error) {
|
|
140
|
+
if (error instanceof PushSignalError) {
|
|
141
|
+
console.warn(error.code); // E_GMS_MISSING, E_FCM_TOKEN, ...
|
|
142
|
+
console.warn(error.message); // "... Use HMS Push Kit (Huawei Push) instead of the standard Google service."
|
|
143
|
+
console.warn(error.provider); // 'hms'
|
|
144
|
+
console.warn(error.hint); // готовая подсказка
|
|
145
|
+
console.warn(error.diagnostics); // полный снимок устройства и провайдера
|
|
146
|
+
}
|
|
147
|
+
}
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
Диагностику можно получить и без запроса токена:
|
|
151
|
+
|
|
152
|
+
```ts
|
|
153
|
+
import { getDiagnostics } from 'react-native-push-signal';
|
|
154
|
+
|
|
155
|
+
const diagnostics = await getDiagnostics();
|
|
156
|
+
// { platform, gmsAvailable, gmsStatus, manufacturer, brand, model,
|
|
157
|
+
// provider, providerName, providerInstalled?, hint? }
|
|
158
|
+
```
|
|
159
|
+
|
|
160
|
+
Провайдер, который предлагается при недоступных GMS:
|
|
161
|
+
|
|
162
|
+
| Производитель | `provider` | Сервис |
|
|
163
|
+
| ------------------------ | ------------ | ---------------------------------- |
|
|
164
|
+
| HUAWEI / HONOR | `hms` | HMS Push Kit (Huawei Push) |
|
|
165
|
+
| Xiaomi / Redmi / POCO | `mi_push` | Mi Push (Xiaomi Push) |
|
|
166
|
+
| OPPO / OnePlus / realme | `oppo_push` | OPPO Push (HeyTap) |
|
|
167
|
+
| vivo / iQOO | `vivo_push` | vivo Push |
|
|
168
|
+
| Meizu | `meizu_push` | Meizu Push |
|
|
169
|
+
| остальные | `unknown` | общая подсказка «нужен другой» |
|
|
170
|
+
|
|
171
|
+
`providerInstalled` равно `true` только если сервис-приложение провайдера действительно найдено на устройстве (`com.huawei.hwid`, `com.xiaomi.xmsf`), иначе поле отсутствует. iOS всегда сообщает `provider: 'apns'`. Библиотека сама ничего не логирует — передавайте данные туда, куда нужно.
|
|
172
|
+
|
|
173
|
+
Коды ошибок: `E_GMS_MISSING`, `E_GMS_DISABLED`, `E_GMS_UPDATE_REQUIRED`, `E_GMS_INVALID`, `E_GMS_UNAVAILABLE`, `E_FCM_TOKEN`, `E_FIREBASE_CONFIG`, `E_NOT_INITIALIZED`.
|
|
174
|
+
|
|
128
175
|
## Входящее сообщение и тап
|
|
129
176
|
|
|
130
177
|
| Состояние | iOS | Android (notification payload) | Android (data-only) |
|
|
@@ -1,6 +1,13 @@
|
|
|
1
1
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
2
2
|
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
3
3
|
|
|
4
|
+
<!-- Android 11+ package visibility: lets isPackageInstalled() confirm an
|
|
5
|
+
alternative push provider on the device. -->
|
|
6
|
+
<queries>
|
|
7
|
+
<package android:name="com.huawei.hwid" />
|
|
8
|
+
<package android:name="com.xiaomi.xmsf" />
|
|
9
|
+
</queries>
|
|
10
|
+
|
|
4
11
|
<application>
|
|
5
12
|
<provider
|
|
6
13
|
android:name="com.pushsignal.PushSignalInitProvider"
|
|
@@ -13,3 +13,26 @@ data class AndroidFirebaseConfig(
|
|
|
13
13
|
val current_key: String?,
|
|
14
14
|
val project_number: String?,
|
|
15
15
|
)
|
|
16
|
+
|
|
17
|
+
data class PushDiagnostics(
|
|
18
|
+
val platform: String,
|
|
19
|
+
val gmsAvailable: Boolean,
|
|
20
|
+
val gmsStatus: Int,
|
|
21
|
+
val manufacturer: String,
|
|
22
|
+
val brand: String,
|
|
23
|
+
val model: String,
|
|
24
|
+
val provider: String,
|
|
25
|
+
val providerName: String,
|
|
26
|
+
val providerInstalled: Boolean?,
|
|
27
|
+
val hint: String?,
|
|
28
|
+
)
|
|
29
|
+
|
|
30
|
+
/**
|
|
31
|
+
* Carries a machine-readable [code] to JavaScript, so the host app can branch on
|
|
32
|
+
* the exact reason (missing GMS, disabled GMS, FCM token failure, ...).
|
|
33
|
+
*/
|
|
34
|
+
class PushSignalException(
|
|
35
|
+
val code: String,
|
|
36
|
+
message: String,
|
|
37
|
+
cause: Throwable? = null,
|
|
38
|
+
) : IllegalStateException(message, cause)
|
|
@@ -7,6 +7,7 @@ import android.app.NotificationManager
|
|
|
7
7
|
import android.app.PendingIntent
|
|
8
8
|
import android.content.Context
|
|
9
9
|
import android.content.Intent
|
|
10
|
+
import android.content.pm.PackageManager
|
|
10
11
|
import android.os.Build
|
|
11
12
|
import android.os.Bundle
|
|
12
13
|
import android.os.Handler
|
|
@@ -36,6 +37,18 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
36
37
|
private const val TOKEN_INITIAL_RETRY_DELAY_MS = 1_000L
|
|
37
38
|
private const val TOKEN_MAX_RETRY_DELAY_MS = 8_000L
|
|
38
39
|
|
|
40
|
+
private const val PROVIDER_FCM = "fcm"
|
|
41
|
+
private const val PROVIDER_HMS = "hms"
|
|
42
|
+
private const val PROVIDER_MI_PUSH = "mi_push"
|
|
43
|
+
private const val PROVIDER_OPPO_PUSH = "oppo_push"
|
|
44
|
+
private const val PROVIDER_VIVO_PUSH = "vivo_push"
|
|
45
|
+
private const val PROVIDER_MEIZU_PUSH = "meizu_push"
|
|
46
|
+
private const val PROVIDER_UNKNOWN = "unknown"
|
|
47
|
+
|
|
48
|
+
/** Service apps used to positively confirm an alternative provider on the device. */
|
|
49
|
+
private const val PACKAGE_HMS = "com.huawei.hwid"
|
|
50
|
+
private const val PACKAGE_MI_PUSH = "com.xiaomi.xmsf"
|
|
51
|
+
|
|
39
52
|
private val lock = Any()
|
|
40
53
|
private val mainHandler = Handler(Looper.getMainLooper())
|
|
41
54
|
@Volatile private var application: Application? = null
|
|
@@ -107,7 +120,7 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
107
120
|
|
|
108
121
|
fun fetchToken(): String {
|
|
109
122
|
val context = application
|
|
110
|
-
?: throw
|
|
123
|
+
?: throw PushSignalException("E_NOT_INITIALIZED", "PushSignal is not initialized")
|
|
111
124
|
|
|
112
125
|
ensurePlayServices(context)
|
|
113
126
|
|
|
@@ -117,16 +130,17 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
117
130
|
}
|
|
118
131
|
FirebaseApp.getInstance()
|
|
119
132
|
} catch (error: IllegalStateException) {
|
|
120
|
-
throw
|
|
133
|
+
throw PushSignalException(
|
|
134
|
+
"E_FIREBASE_CONFIG",
|
|
121
135
|
"Firebase is not configured. Call initialize({ project_id, mobilesdk_app_id, current_key, project_number }) or add google-services.json.",
|
|
122
136
|
error
|
|
123
137
|
)
|
|
124
138
|
}
|
|
125
139
|
|
|
126
|
-
val token = awaitTokenWithRetry()
|
|
140
|
+
val token = awaitTokenWithRetry(context)
|
|
127
141
|
|
|
128
142
|
if (token.isNullOrEmpty()) {
|
|
129
|
-
throw
|
|
143
|
+
throw PushSignalException("E_FCM_TOKEN", "Firebase returned an empty FCM token")
|
|
130
144
|
}
|
|
131
145
|
|
|
132
146
|
return token
|
|
@@ -134,7 +148,8 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
134
148
|
|
|
135
149
|
/**
|
|
136
150
|
* Fails fast with an actionable message when Google Play services cannot serve FCM
|
|
137
|
-
* (for example a China-only ROM without GMS).
|
|
151
|
+
* (for example a China-only ROM without GMS). The message names the provider the
|
|
152
|
+
* device should use instead, so the cause is obvious in React Native logs.
|
|
138
153
|
*/
|
|
139
154
|
private fun ensurePlayServices(context: Context) {
|
|
140
155
|
val status = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
|
@@ -142,9 +157,17 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
142
157
|
return
|
|
143
158
|
}
|
|
144
159
|
|
|
160
|
+
val code = when (status) {
|
|
161
|
+
ConnectionResult.SERVICE_MISSING -> "E_GMS_MISSING"
|
|
162
|
+
ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED -> "E_GMS_UPDATE_REQUIRED"
|
|
163
|
+
ConnectionResult.SERVICE_DISABLED -> "E_GMS_DISABLED"
|
|
164
|
+
ConnectionResult.SERVICE_INVALID -> "E_GMS_INVALID"
|
|
165
|
+
else -> "E_GMS_UNAVAILABLE"
|
|
166
|
+
}
|
|
167
|
+
|
|
145
168
|
val reason = when (status) {
|
|
146
169
|
ConnectionResult.SERVICE_MISSING ->
|
|
147
|
-
"Google Play services are missing on this device, so
|
|
170
|
+
"Google Play services are missing on this device, so the standard Google push service (FCM) cannot be used."
|
|
148
171
|
ConnectionResult.SERVICE_VERSION_UPDATE_REQUIRED ->
|
|
149
172
|
"Google Play services are outdated. Update them in the Play Store and try again."
|
|
150
173
|
ConnectionResult.SERVICE_DISABLED ->
|
|
@@ -152,10 +175,118 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
152
175
|
ConnectionResult.SERVICE_INVALID ->
|
|
153
176
|
"Google Play services are invalid or corrupted on this device. Reinstalling them usually helps."
|
|
154
177
|
else ->
|
|
155
|
-
"Google Play services are unavailable (code $status)."
|
|
178
|
+
"Google Play services are unavailable (code $status), so the standard Google push service (FCM) cannot be used."
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
val diagnostics = diagnose(context)
|
|
182
|
+
val message = listOfNotNull(reason, diagnostics.hint).joinToString(" ")
|
|
183
|
+
Log.w(TAG, "Play services check failed ($code): $message")
|
|
184
|
+
throw PushSignalException(code, message)
|
|
185
|
+
}
|
|
186
|
+
|
|
187
|
+
/**
|
|
188
|
+
* Collects device and provider diagnostics without throwing. Used both by the
|
|
189
|
+
* `getDiagnostics` API and to enrich errors with a concrete replacement service.
|
|
190
|
+
*/
|
|
191
|
+
fun diagnose(context: Context): PushDiagnostics {
|
|
192
|
+
val status = GoogleApiAvailability.getInstance().isGooglePlayServicesAvailable(context)
|
|
193
|
+
val gmsAvailable = status == ConnectionResult.SUCCESS
|
|
194
|
+
val provider = resolveProvider(context, gmsAvailable)
|
|
195
|
+
val hint = providerHint(provider, gmsAvailable)
|
|
196
|
+
|
|
197
|
+
return PushDiagnostics(
|
|
198
|
+
platform = "android_os",
|
|
199
|
+
gmsAvailable = gmsAvailable,
|
|
200
|
+
gmsStatus = status,
|
|
201
|
+
manufacturer = Build.MANUFACTURER ?: "",
|
|
202
|
+
brand = Build.BRAND ?: "",
|
|
203
|
+
model = Build.MODEL ?: "",
|
|
204
|
+
provider = provider.id,
|
|
205
|
+
providerName = provider.name,
|
|
206
|
+
providerInstalled = provider.installed,
|
|
207
|
+
hint = hint,
|
|
208
|
+
)
|
|
209
|
+
}
|
|
210
|
+
|
|
211
|
+
private data class ProviderInfo(
|
|
212
|
+
val id: String,
|
|
213
|
+
val name: String,
|
|
214
|
+
val installed: Boolean?,
|
|
215
|
+
)
|
|
216
|
+
|
|
217
|
+
/**
|
|
218
|
+
* Picks the push provider this device should use. Checks the standard Google
|
|
219
|
+
* service first, then positively confirms an installed alternative, then falls
|
|
220
|
+
* back to the manufacturer mapping. Class reflection cannot see another
|
|
221
|
+
* provider's SDK unless the host bundles it, so package checks and the
|
|
222
|
+
* manufacturer are the reliable signals.
|
|
223
|
+
*/
|
|
224
|
+
private fun resolveProvider(context: Context, gmsAvailable: Boolean): ProviderInfo {
|
|
225
|
+
if (gmsAvailable) {
|
|
226
|
+
return ProviderInfo(PROVIDER_FCM, "Firebase Cloud Messaging (FCM)", true)
|
|
227
|
+
}
|
|
228
|
+
|
|
229
|
+
if (isPackageInstalled(context, PACKAGE_HMS)) {
|
|
230
|
+
return ProviderInfo(PROVIDER_HMS, "HMS Push Kit (Huawei Push)", true)
|
|
231
|
+
}
|
|
232
|
+
if (isPackageInstalled(context, PACKAGE_MI_PUSH)) {
|
|
233
|
+
return ProviderInfo(PROVIDER_MI_PUSH, "Mi Push (Xiaomi Push)", true)
|
|
234
|
+
}
|
|
235
|
+
|
|
236
|
+
val keys = setOf(Build.MANUFACTURER, Build.BRAND)
|
|
237
|
+
.filterNotNull()
|
|
238
|
+
.map { it.uppercase() }
|
|
239
|
+
|
|
240
|
+
return when {
|
|
241
|
+
keys.any { it.contains("HUAWEI") || it.contains("HONOR") } ->
|
|
242
|
+
ProviderInfo(PROVIDER_HMS, "HMS Push Kit (Huawei Push)", false)
|
|
243
|
+
keys.any { it.contains("XIAOMI") || it.contains("REDMI") || it.contains("POCO") } ->
|
|
244
|
+
ProviderInfo(PROVIDER_MI_PUSH, "Mi Push (Xiaomi Push)", false)
|
|
245
|
+
keys.any { it.contains("OPPO") || it.contains("ONEPLUS") || it.contains("REALME") } ->
|
|
246
|
+
ProviderInfo(PROVIDER_OPPO_PUSH, "OPPO Push (HeyTap)", false)
|
|
247
|
+
keys.any { it.contains("VIVO") || it.contains("IQOO") } ->
|
|
248
|
+
ProviderInfo(PROVIDER_VIVO_PUSH, "vivo Push", false)
|
|
249
|
+
keys.any { it.contains("MEIZU") } ->
|
|
250
|
+
ProviderInfo(PROVIDER_MEIZU_PUSH, "Meizu Push", false)
|
|
251
|
+
else ->
|
|
252
|
+
ProviderInfo(PROVIDER_UNKNOWN, "unknown", null)
|
|
253
|
+
}
|
|
254
|
+
}
|
|
255
|
+
|
|
256
|
+
private fun providerHint(provider: ProviderInfo, gmsAvailable: Boolean): String? {
|
|
257
|
+
if (gmsAvailable) {
|
|
258
|
+
return null
|
|
259
|
+
}
|
|
260
|
+
val device = listOfNotNull(Build.MANUFACTURER, Build.BRAND)
|
|
261
|
+
.filter { it.isNotBlank() }
|
|
262
|
+
.distinct()
|
|
263
|
+
.joinToString("/")
|
|
264
|
+
|
|
265
|
+
return when (provider.id) {
|
|
266
|
+
PROVIDER_HMS ->
|
|
267
|
+
"This device ($device) has no usable Google Play services, so FCM will not issue a token. Use HMS Push Kit (Huawei Push) instead of the standard Google service."
|
|
268
|
+
PROVIDER_MI_PUSH ->
|
|
269
|
+
"This device ($device) has no usable Google Play services, so FCM will not issue a token. Use Mi Push (Xiaomi Push) instead of the standard Google service."
|
|
270
|
+
PROVIDER_OPPO_PUSH ->
|
|
271
|
+
"This device ($device) has no usable Google Play services, so FCM will not issue a token. Use OPPO Push (HeyTap) instead of the standard Google service."
|
|
272
|
+
PROVIDER_VIVO_PUSH ->
|
|
273
|
+
"This device ($device) has no usable Google Play services, so FCM will not issue a token. Use vivo Push instead of the standard Google service."
|
|
274
|
+
PROVIDER_MEIZU_PUSH ->
|
|
275
|
+
"This device ($device) has no usable Google Play services, so FCM will not issue a token. Use Meizu Push instead of the standard Google service."
|
|
276
|
+
else ->
|
|
277
|
+
"No usable Google Play services were found and no known push provider was detected on this ROM, so FCM cannot be used. Integrate another push provider (HMS, Mi Push, OPPO/vivo/Meizu Push)."
|
|
278
|
+
}
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
private fun isPackageInstalled(context: Context, packageName: String): Boolean {
|
|
282
|
+
return try {
|
|
283
|
+
context.packageManager.getPackageInfo(packageName, 0)
|
|
284
|
+
true
|
|
285
|
+
} catch (_: PackageManager.NameNotFoundException) {
|
|
286
|
+
false
|
|
287
|
+
} catch (_: Exception) {
|
|
288
|
+
false
|
|
156
289
|
}
|
|
157
|
-
Log.w(TAG, "Play services check failed: $reason")
|
|
158
|
-
throw IllegalStateException(reason)
|
|
159
290
|
}
|
|
160
291
|
|
|
161
292
|
/**
|
|
@@ -163,7 +294,7 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
163
294
|
* Play services still starting, flaky network). Xiaomi/MIUI devices hit this often,
|
|
164
295
|
* so retry with backoff before surfacing the failure.
|
|
165
296
|
*/
|
|
166
|
-
private fun awaitTokenWithRetry(): String? {
|
|
297
|
+
private fun awaitTokenWithRetry(context: Context): String? {
|
|
167
298
|
var delayMs = TOKEN_INITIAL_RETRY_DELAY_MS
|
|
168
299
|
var lastError: Exception? = null
|
|
169
300
|
|
|
@@ -191,13 +322,16 @@ internal object PushSignalCenter : Application.ActivityLifecycleCallbacks {
|
|
|
191
322
|
}
|
|
192
323
|
|
|
193
324
|
val cause = lastError
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
"
|
|
199
|
-
|
|
200
|
-
|
|
325
|
+
val diagnostics = diagnose(context)
|
|
326
|
+
val message = listOfNotNull(
|
|
327
|
+
"Failed to get an FCM token: ${cause?.message ?: "unknown error"}.",
|
|
328
|
+
"Make sure the device is signed into a Google account, Google Play services are up to date, " +
|
|
329
|
+
"and the app is allowed to use background data.",
|
|
330
|
+
"Call initialize({ project_id, mobilesdk_app_id, current_key, project_number }) or add google-services.json.",
|
|
331
|
+
diagnostics.hint,
|
|
332
|
+
).joinToString(" ")
|
|
333
|
+
Log.w(TAG, "Failed to get an FCM token: $message")
|
|
334
|
+
throw PushSignalException("E_FCM_TOKEN", message, cause)
|
|
201
335
|
}
|
|
202
336
|
|
|
203
337
|
private fun isRetryableTokenError(error: Throwable): Boolean {
|
|
@@ -26,7 +26,8 @@ class PushSignalModule(reactContext: ReactApplicationContext) :
|
|
|
26
26
|
if (error == null) {
|
|
27
27
|
promise.resolve(null)
|
|
28
28
|
} else {
|
|
29
|
-
|
|
29
|
+
val code = (error as? PushSignalException)?.code ?: "E_INIT"
|
|
30
|
+
promise.reject(code, error.message, error)
|
|
30
31
|
}
|
|
31
32
|
}
|
|
32
33
|
}
|
|
@@ -42,7 +43,19 @@ class PushSignalModule(reactContext: ReactApplicationContext) :
|
|
|
42
43
|
}
|
|
43
44
|
promise.resolve(result)
|
|
44
45
|
} catch (error: Exception) {
|
|
45
|
-
|
|
46
|
+
val code = (error as? PushSignalException)?.code ?: "E_CREDENTIALS"
|
|
47
|
+
promise.reject(code, error.message, error)
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
}
|
|
51
|
+
|
|
52
|
+
override fun getDiagnostics(promise: Promise) {
|
|
53
|
+
executor.execute {
|
|
54
|
+
try {
|
|
55
|
+
PushSignalCenter.attach(reactApplicationContext)
|
|
56
|
+
promise.resolve(PushSignalCenter.diagnose(reactApplicationContext).toWritableMap())
|
|
57
|
+
} catch (error: Exception) {
|
|
58
|
+
promise.reject("E_DIAGNOSTICS", error.message, error)
|
|
46
59
|
}
|
|
47
60
|
}
|
|
48
61
|
}
|
|
@@ -86,3 +99,18 @@ private fun PushMessage.toWritableMap(): WritableMap {
|
|
|
86
99
|
map.putMap("data", dataMap)
|
|
87
100
|
return map
|
|
88
101
|
}
|
|
102
|
+
|
|
103
|
+
private fun PushDiagnostics.toWritableMap(): WritableMap {
|
|
104
|
+
val map = Arguments.createMap()
|
|
105
|
+
map.putString("platform", platform)
|
|
106
|
+
map.putBoolean("gmsAvailable", gmsAvailable)
|
|
107
|
+
map.putInt("gmsStatus", gmsStatus)
|
|
108
|
+
map.putString("manufacturer", manufacturer)
|
|
109
|
+
map.putString("brand", brand)
|
|
110
|
+
map.putString("model", model)
|
|
111
|
+
map.putString("provider", provider)
|
|
112
|
+
map.putString("providerName", providerName)
|
|
113
|
+
providerInstalled?.let { map.putBoolean("providerInstalled", it) }
|
|
114
|
+
hint?.let { map.putString("hint", it) }
|
|
115
|
+
return map
|
|
116
|
+
}
|
package/ios/PushSignal.mm
CHANGED
|
@@ -1,5 +1,6 @@
|
|
|
1
1
|
#import "PushSignal.h"
|
|
2
2
|
#import "PushSignalCenter.h"
|
|
3
|
+
#import <UIKit/UIKit.h>
|
|
3
4
|
|
|
4
5
|
@implementation PushSignal {
|
|
5
6
|
BOOL _listening;
|
|
@@ -22,6 +23,23 @@
|
|
|
22
23
|
}];
|
|
23
24
|
}
|
|
24
25
|
|
|
26
|
+
- (void)getDiagnostics:(RCTPromiseResolveBlock)resolve
|
|
27
|
+
reject:(RCTPromiseRejectBlock)reject {
|
|
28
|
+
(void)reject;
|
|
29
|
+
UIDevice *device = [UIDevice currentDevice];
|
|
30
|
+
resolve(@{
|
|
31
|
+
@"platform": @"ios",
|
|
32
|
+
@"gmsAvailable": @YES,
|
|
33
|
+
@"gmsStatus": @0,
|
|
34
|
+
@"manufacturer": @"Apple",
|
|
35
|
+
@"brand": @"Apple",
|
|
36
|
+
@"model": device.model ?: @"iOS device",
|
|
37
|
+
@"provider": @"apns",
|
|
38
|
+
@"providerName": @"Apple Push Notification service (APNs)",
|
|
39
|
+
@"providerInstalled": @YES,
|
|
40
|
+
});
|
|
41
|
+
}
|
|
42
|
+
|
|
25
43
|
- (void)startListening {
|
|
26
44
|
if (_listening) {
|
|
27
45
|
return;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativePushSignal.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;
|
|
1
|
+
{"version":3,"names":["TurboModuleRegistry","getEnforcing"],"sourceRoot":"../../src","sources":["NativePushSignal.ts"],"mappings":";;AACA,SAASA,mBAAmB,QAAQ,cAAc;AA2ClD,eAAeA,mBAAmB,CAACC,YAAY,CAAO,YAAY,CAAC","ignoreList":[]}
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error thrown by `initialize` and `getCredentials`.
|
|
5
|
+
*
|
|
6
|
+
* The message already contains a human-readable, actionable hint when the
|
|
7
|
+
* standard Google service (FCM/GMS) cannot be used. Structured details are
|
|
8
|
+
* available on the instance so the host app can decide how to log or report them.
|
|
9
|
+
*/
|
|
10
|
+
export class PushSignalError extends Error {
|
|
11
|
+
/** Machine-readable code, e.g. `E_GMS_MISSING` or `E_FCM_TOKEN`. */
|
|
12
|
+
|
|
13
|
+
/** Suggested alternative push provider, when the standard service is unusable. */
|
|
14
|
+
|
|
15
|
+
/** Actionable sentence: which service to use instead of the standard one. */
|
|
16
|
+
|
|
17
|
+
/** Full device/provider diagnostics if they could be collected. */
|
|
18
|
+
|
|
19
|
+
/** Original error from the native layer. */
|
|
20
|
+
|
|
21
|
+
constructor(code, message, cause) {
|
|
22
|
+
super(message);
|
|
23
|
+
this.name = 'PushSignalError';
|
|
24
|
+
this.code = code;
|
|
25
|
+
this.cause = cause;
|
|
26
|
+
Object.setPrototypeOf(this, PushSignalError.prototype);
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
//# sourceMappingURL=PushSignalError.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"names":["PushSignalError","Error","constructor","code","message","cause","name","Object","setPrototypeOf","prototype"],"sourceRoot":"../../src","sources":["PushSignalError.ts"],"mappings":";;AAEA;AACA;AACA;AACA;AACA;AACA;AACA;AACA,OAAO,MAAMA,eAAe,SAASC,KAAK,CAAC;EACzC;;EAEA;;EAEA;;EAEA;;EAEA;;EAGAC,WAAWA,CAACC,IAAY,EAAEC,OAAe,EAAEC,KAAe,EAAE;IAC1D,KAAK,CAACD,OAAO,CAAC;IACd,IAAI,CAACE,IAAI,GAAG,iBAAiB;IAC7B,IAAI,CAACH,IAAI,GAAGA,IAAI;IAChB,IAAI,CAACE,KAAK,GAAGA,KAAK;IAClBE,MAAM,CAACC,cAAc,CAAC,IAAI,EAAER,eAAe,CAACS,SAAS,CAAC;EACxD;AACF","ignoreList":[]}
|
package/lib/module/index.js
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
|
-
export {
|
|
3
|
+
export { PushSignalError } from "./PushSignalError.js";
|
|
4
|
+
export { getCredentials, getDiagnostics, initialize, onMessage, onNotificationPress } from './pushSignal';
|
|
4
5
|
//# sourceMappingURL=index.js.map
|
package/lib/module/index.js.map
CHANGED
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["getCredentials","initialize","onMessage","onNotificationPress"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["PushSignalError","getCredentials","getDiagnostics","initialize","onMessage","onNotificationPress"],"sourceRoot":"../../src","sources":["index.tsx"],"mappings":";;AAUA,SAASA,eAAe,QAAQ,sBAAmB;AACnD,SACEC,cAAc,EACdC,cAAc,EACdC,UAAU,EACVC,SAAS,EACTC,mBAAmB,QACd,cAAc","ignoreList":[]}
|
package/lib/module/pushSignal.js
CHANGED
|
@@ -4,6 +4,9 @@ export async function initialize(_config = {}) {}
|
|
|
4
4
|
export async function getCredentials() {
|
|
5
5
|
throw new Error('Push credentials are not supported on web');
|
|
6
6
|
}
|
|
7
|
+
export async function getDiagnostics() {
|
|
8
|
+
throw new Error('Push diagnostics are not supported on web');
|
|
9
|
+
}
|
|
7
10
|
export function onMessage(_listener) {
|
|
8
11
|
return () => {};
|
|
9
12
|
}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["initialize","_config","getCredentials","Error","onMessage","_listener","onNotificationPress"],"sourceRoot":"../../src","sources":["pushSignal.tsx"],"mappings":";;
|
|
1
|
+
{"version":3,"names":["initialize","_config","getCredentials","Error","getDiagnostics","onMessage","_listener","onNotificationPress"],"sourceRoot":"../../src","sources":["pushSignal.tsx"],"mappings":";;AAQA,OAAO,eAAeA,UAAUA,CAC9BC,OAA8B,GAAG,CAAC,CAAC,EACpB,CAAC;AAElB,OAAO,eAAeC,cAAcA,CAAA,EAA6B;EAC/D,MAAM,IAAIC,KAAK,CAAC,2CAA2C,CAAC;AAC9D;AAEA,OAAO,eAAeC,cAAcA,CAAA,EAA6B;EAC/D,MAAM,IAAID,KAAK,CAAC,2CAA2C,CAAC;AAC9D;AAEA,OAAO,SAASE,SAASA,CAACC,SAA4B,EAAc;EAClE,OAAO,MAAM,CAAC,CAAC;AACjB;AAEA,OAAO,SAASC,mBAAmBA,CACjCD,SAAyC,EAC7B;EACZ,OAAO,MAAM,CAAC,CAAC;AACjB","ignoreList":[]}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
|
|
3
3
|
import NativePushSignal from "./NativePushSignal.js";
|
|
4
|
+
import { PushSignalError } from "./PushSignalError.js";
|
|
4
5
|
const messageListeners = new Set();
|
|
5
6
|
const pressListeners = new Set();
|
|
6
7
|
let nativeCallbacksBound = false;
|
|
@@ -28,6 +29,40 @@ function normalizeCredentials(raw) {
|
|
|
28
29
|
environment: raw.environment
|
|
29
30
|
};
|
|
30
31
|
}
|
|
32
|
+
function normalizeDiagnostics(raw) {
|
|
33
|
+
return {
|
|
34
|
+
platform: raw.platform,
|
|
35
|
+
gmsAvailable: raw.gmsAvailable,
|
|
36
|
+
gmsStatus: raw.gmsStatus,
|
|
37
|
+
manufacturer: raw.manufacturer,
|
|
38
|
+
brand: raw.brand,
|
|
39
|
+
model: raw.model,
|
|
40
|
+
provider: raw.provider,
|
|
41
|
+
providerName: raw.providerName,
|
|
42
|
+
providerInstalled: raw.providerInstalled ?? undefined,
|
|
43
|
+
hint: raw.hint ?? undefined
|
|
44
|
+
};
|
|
45
|
+
}
|
|
46
|
+
function toPushSignalError(error, fallbackCode) {
|
|
47
|
+
const candidate = error;
|
|
48
|
+
return new PushSignalError(candidate?.code ?? fallbackCode, candidate?.message ?? 'PushSignal request failed', error);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
/**
|
|
52
|
+
* Attaches structured diagnostics to an error on a best-effort basis. Failing to
|
|
53
|
+
* collect them must never hide the original, already actionable error.
|
|
54
|
+
*/
|
|
55
|
+
async function enrichError(error) {
|
|
56
|
+
try {
|
|
57
|
+
const diagnostics = normalizeDiagnostics(await NativePushSignal.getDiagnostics());
|
|
58
|
+
error.diagnostics = diagnostics;
|
|
59
|
+
error.provider = diagnostics.provider;
|
|
60
|
+
error.hint = diagnostics.hint;
|
|
61
|
+
} catch {
|
|
62
|
+
// Diagnostics are optional; keep the original error.
|
|
63
|
+
}
|
|
64
|
+
return error;
|
|
65
|
+
}
|
|
31
66
|
function bindNativeCallbacks() {
|
|
32
67
|
if (nativeCallbacksBound) {
|
|
33
68
|
return;
|
|
@@ -49,11 +84,23 @@ function bindNativeCallbacks() {
|
|
|
49
84
|
});
|
|
50
85
|
NativePushSignal.startListening();
|
|
51
86
|
}
|
|
52
|
-
export function initialize(config = {}) {
|
|
53
|
-
|
|
87
|
+
export async function initialize(config = {}) {
|
|
88
|
+
try {
|
|
89
|
+
await NativePushSignal.initialize(config);
|
|
90
|
+
} catch (error) {
|
|
91
|
+
throw await enrichError(toPushSignalError(error, 'E_INIT'));
|
|
92
|
+
}
|
|
93
|
+
}
|
|
94
|
+
export async function getCredentials() {
|
|
95
|
+
try {
|
|
96
|
+
const raw = await NativePushSignal.getCredentials();
|
|
97
|
+
return normalizeCredentials(raw);
|
|
98
|
+
} catch (error) {
|
|
99
|
+
throw await enrichError(toPushSignalError(error, 'E_CREDENTIALS'));
|
|
100
|
+
}
|
|
54
101
|
}
|
|
55
|
-
export function
|
|
56
|
-
return NativePushSignal.
|
|
102
|
+
export async function getDiagnostics() {
|
|
103
|
+
return normalizeDiagnostics(await NativePushSignal.getDiagnostics());
|
|
57
104
|
}
|
|
58
105
|
export function onMessage(listener) {
|
|
59
106
|
bindNativeCallbacks();
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":["NativePushSignal","messageListeners","Set","pressListeners","nativeCallbacksBound","normalizeMessage","raw","data","key","value","Object","entries","String","id","title","body","normalizeCredentials","platform","token","environment","
|
|
1
|
+
{"version":3,"names":["NativePushSignal","PushSignalError","messageListeners","Set","pressListeners","nativeCallbacksBound","normalizeMessage","raw","data","key","value","Object","entries","String","id","title","body","normalizeCredentials","platform","token","environment","normalizeDiagnostics","gmsAvailable","gmsStatus","manufacturer","brand","model","provider","providerName","providerInstalled","undefined","hint","toPushSignalError","error","fallbackCode","candidate","code","message","enrichError","diagnostics","getDiagnostics","bindNativeCallbacks","onMessage","listener","Promise","resolve","then","onNotificationPress","forEach","startListening","initialize","config","getCredentials","add","delete"],"sourceRoot":"../../src","sources":["pushSignal.native.tsx"],"mappings":"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","ignoreList":[]}
|
|
@@ -10,9 +10,28 @@ export type NativePushCredentials = {
|
|
|
10
10
|
token: string;
|
|
11
11
|
environment?: string;
|
|
12
12
|
};
|
|
13
|
+
export type NativePushDiagnostics = {
|
|
14
|
+
platform: string;
|
|
15
|
+
/** True when Google Play services can serve FCM; false on a ROM without GMS. */
|
|
16
|
+
gmsAvailable: boolean;
|
|
17
|
+
/** Raw GoogleApiAvailability status code. 0 means SUCCESS. */
|
|
18
|
+
gmsStatus: number;
|
|
19
|
+
manufacturer: string;
|
|
20
|
+
brand: string;
|
|
21
|
+
model: string;
|
|
22
|
+
/** Machine-readable provider id: fcm, hms, mi_push, oppo_push, vivo_push, meizu_push, apns, unknown. */
|
|
23
|
+
provider: string;
|
|
24
|
+
/** Human-readable provider name, e.g. "HMS Push Kit". */
|
|
25
|
+
providerName: string;
|
|
26
|
+
/** True when the provider service app was found on the device. */
|
|
27
|
+
providerInstalled: boolean;
|
|
28
|
+
/** Actionable sentence explaining which service to use instead of the standard one. */
|
|
29
|
+
hint?: string;
|
|
30
|
+
};
|
|
13
31
|
export interface Spec extends TurboModule {
|
|
14
32
|
initialize(config: Object): Promise<void>;
|
|
15
33
|
getCredentials(): Promise<NativePushCredentials>;
|
|
34
|
+
getDiagnostics(): Promise<NativePushDiagnostics>;
|
|
16
35
|
startListening(): void;
|
|
17
36
|
readonly onMessage: CodegenTypes.EventEmitter<NativePushMessage>;
|
|
18
37
|
readonly onNotificationPress: CodegenTypes.EventEmitter<NativePushMessage>;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"NativePushSignal.d.ts","sourceRoot":"","sources":["../../../src/NativePushSignal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG9D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,cAAc,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjD,cAAc,IAAI,IAAI,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjE,QAAQ,CAAC,mBAAmB,EAAE,YAAY,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;CAC5E;;AAED,wBAAoE"}
|
|
1
|
+
{"version":3,"file":"NativePushSignal.d.ts","sourceRoot":"","sources":["../../../src/NativePushSignal.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,YAAY,EAAE,WAAW,EAAE,MAAM,cAAc,CAAC;AAG9D,MAAM,MAAM,iBAAiB,GAAG;IAC9B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CACd,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,MAAM,CAAC;CACtB,CAAC;AAEF,MAAM,MAAM,qBAAqB,GAAG;IAClC,QAAQ,EAAE,MAAM,CAAC;IACjB,gFAAgF;IAChF,YAAY,EAAE,OAAO,CAAC;IACtB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,wGAAwG;IACxG,QAAQ,EAAE,MAAM,CAAC;IACjB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,kEAAkE;IAClE,iBAAiB,EAAE,OAAO,CAAC;IAC3B,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf,CAAC;AAEF,MAAM,WAAW,IAAK,SAAQ,WAAW;IACvC,UAAU,CAAC,MAAM,EAAE,MAAM,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;IAC1C,cAAc,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjD,cAAc,IAAI,OAAO,CAAC,qBAAqB,CAAC,CAAC;IACjD,cAAc,IAAI,IAAI,CAAC;IACvB,QAAQ,CAAC,SAAS,EAAE,YAAY,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;IACjE,QAAQ,CAAC,mBAAmB,EAAE,YAAY,CAAC,YAAY,CAAC,iBAAiB,CAAC,CAAC;CAC5E;;AAED,wBAAoE"}
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { PushDiagnostics, PushProvider } from './types.js';
|
|
2
|
+
/**
|
|
3
|
+
* Error thrown by `initialize` and `getCredentials`.
|
|
4
|
+
*
|
|
5
|
+
* The message already contains a human-readable, actionable hint when the
|
|
6
|
+
* standard Google service (FCM/GMS) cannot be used. Structured details are
|
|
7
|
+
* available on the instance so the host app can decide how to log or report them.
|
|
8
|
+
*/
|
|
9
|
+
export declare class PushSignalError extends Error {
|
|
10
|
+
/** Machine-readable code, e.g. `E_GMS_MISSING` or `E_FCM_TOKEN`. */
|
|
11
|
+
readonly code: string;
|
|
12
|
+
/** Suggested alternative push provider, when the standard service is unusable. */
|
|
13
|
+
provider?: PushProvider;
|
|
14
|
+
/** Actionable sentence: which service to use instead of the standard one. */
|
|
15
|
+
hint?: string;
|
|
16
|
+
/** Full device/provider diagnostics if they could be collected. */
|
|
17
|
+
diagnostics?: PushDiagnostics;
|
|
18
|
+
/** Original error from the native layer. */
|
|
19
|
+
readonly cause?: unknown;
|
|
20
|
+
constructor(code: string, message: string, cause?: unknown);
|
|
21
|
+
}
|
|
22
|
+
//# sourceMappingURL=PushSignalError.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"PushSignalError.d.ts","sourceRoot":"","sources":["../../../src/PushSignalError.ts"],"names":[],"mappings":"AAAA,OAAO,KAAK,EAAE,eAAe,EAAE,YAAY,EAAE,MAAM,YAAS,CAAC;AAE7D;;;;;;GAMG;AACH,qBAAa,eAAgB,SAAQ,KAAK;IACxC,oEAAoE;IACpE,QAAQ,CAAC,IAAI,EAAE,MAAM,CAAC;IACtB,kFAAkF;IAClF,QAAQ,CAAC,EAAE,YAAY,CAAC;IACxB,6EAA6E;IAC7E,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,mEAAmE;IACnE,WAAW,CAAC,EAAE,eAAe,CAAC;IAC9B,4CAA4C;IAC5C,SAAkB,KAAK,CAAC,EAAE,OAAO,CAAC;gBAEtB,IAAI,EAAE,MAAM,EAAE,OAAO,EAAE,MAAM,EAAE,KAAK,CAAC,EAAE,OAAO;CAO3D"}
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
-
export type { AndroidFirebaseConfig, OnMessageListener, PushCredentials, PushEnvironment, PushMessage, PushPlatform, } from './types.js';
|
|
2
|
-
export {
|
|
1
|
+
export type { AndroidFirebaseConfig, OnMessageListener, PushCredentials, PushDiagnostics, PushEnvironment, PushMessage, PushPlatform, PushProvider, } from './types.js';
|
|
2
|
+
export { PushSignalError } from './PushSignalError.js';
|
|
3
|
+
export { getCredentials, getDiagnostics, initialize, onMessage, onNotificationPress, } from './pushSignal';
|
|
3
4
|
//# sourceMappingURL=index.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,WAAW,EACX,YAAY,GACb,MAAM,YAAS,CAAC;AACjB,OAAO,EACL,cAAc,EACd,UAAU,EACV,SAAS,EACT,mBAAmB,GACpB,MAAM,cAAc,CAAC"}
|
|
1
|
+
{"version":3,"file":"index.d.ts","sourceRoot":"","sources":["../../../src/index.tsx"],"names":[],"mappings":"AAAA,YAAY,EACV,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,eAAe,EACf,WAAW,EACX,YAAY,EACZ,YAAY,GACb,MAAM,YAAS,CAAC;AACjB,OAAO,EAAE,eAAe,EAAE,MAAM,sBAAmB,CAAC;AACpD,OAAO,EACL,cAAc,EACd,cAAc,EACd,UAAU,EACV,SAAS,EACT,mBAAmB,GACpB,MAAM,cAAc,CAAC"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { AndroidFirebaseConfig, OnMessageListener, PushCredentials, PushMessage } from './types.js';
|
|
1
|
+
import type { AndroidFirebaseConfig, OnMessageListener, PushCredentials, PushDiagnostics, PushMessage } from './types.js';
|
|
2
2
|
export declare function initialize(_config?: AndroidFirebaseConfig): Promise<void>;
|
|
3
3
|
export declare function getCredentials(): Promise<PushCredentials>;
|
|
4
|
+
export declare function getDiagnostics(): Promise<PushDiagnostics>;
|
|
4
5
|
export declare function onMessage(_listener: OnMessageListener): () => void;
|
|
5
6
|
export declare function onNotificationPress(_listener: (message: PushMessage) => void): () => void;
|
|
6
7
|
//# sourceMappingURL=pushSignal.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pushSignal.d.ts","sourceRoot":"","sources":["../../../src/pushSignal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,WAAW,EACZ,MAAM,YAAS,CAAC;AAEjB,wBAAsB,UAAU,CAC9B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAAG;AAEnB,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAE/D;AAED,wBAAgB,SAAS,CAAC,SAAS,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAElE;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GACxC,MAAM,IAAI,CAEZ"}
|
|
1
|
+
{"version":3,"file":"pushSignal.d.ts","sourceRoot":"","sources":["../../../src/pushSignal.tsx"],"names":[],"mappings":"AAAA,OAAO,KAAK,EACV,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,eAAe,EACf,WAAW,EACZ,MAAM,YAAS,CAAC;AAEjB,wBAAsB,UAAU,CAC9B,OAAO,GAAE,qBAA0B,GAClC,OAAO,CAAC,IAAI,CAAC,CAAG;AAEnB,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAE/D;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAE/D;AAED,wBAAgB,SAAS,CAAC,SAAS,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAElE;AAED,wBAAgB,mBAAmB,CACjC,SAAS,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GACxC,MAAM,IAAI,CAEZ"}
|
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import type { AndroidFirebaseConfig, OnMessageListener, PushCredentials, PushMessage } from './types.js';
|
|
1
|
+
import type { AndroidFirebaseConfig, OnMessageListener, PushCredentials, PushDiagnostics, PushMessage } from './types.js';
|
|
2
2
|
export declare function initialize(config?: AndroidFirebaseConfig): Promise<void>;
|
|
3
3
|
export declare function getCredentials(): Promise<PushCredentials>;
|
|
4
|
+
export declare function getDiagnostics(): Promise<PushDiagnostics>;
|
|
4
5
|
export declare function onMessage(listener: OnMessageListener): () => void;
|
|
5
6
|
export declare function onNotificationPress(listener: (message: PushMessage) => void): () => void;
|
|
6
7
|
//# sourceMappingURL=pushSignal.native.d.ts.map
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"pushSignal.native.d.ts","sourceRoot":"","sources":["../../../src/pushSignal.native.tsx"],"names":[],"mappings":"
|
|
1
|
+
{"version":3,"file":"pushSignal.native.d.ts","sourceRoot":"","sources":["../../../src/pushSignal.native.tsx"],"names":[],"mappings":"AAGA,OAAO,KAAK,EACV,qBAAqB,EACrB,iBAAiB,EACjB,eAAe,EACf,eAAe,EAEf,WAAW,EAGZ,MAAM,YAAS,CAAC;AAsHjB,wBAAsB,UAAU,CAC9B,MAAM,GAAE,qBAA0B,GACjC,OAAO,CAAC,IAAI,CAAC,CAMf;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAO/D;AAED,wBAAsB,cAAc,IAAI,OAAO,CAAC,eAAe,CAAC,CAE/D;AAED,wBAAgB,SAAS,CAAC,QAAQ,EAAE,iBAAiB,GAAG,MAAM,IAAI,CAMjE;AAED,wBAAgB,mBAAmB,CACjC,QAAQ,EAAE,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GACvC,MAAM,IAAI,CAMZ"}
|
|
@@ -13,6 +13,24 @@ export interface PushMessage {
|
|
|
13
13
|
data: Record<string, string>;
|
|
14
14
|
}
|
|
15
15
|
export type OnMessageListener = (message: PushMessage) => void | Promise<void>;
|
|
16
|
+
export type PushProvider = 'fcm' | 'hms' | 'mi_push' | 'oppo_push' | 'vivo_push' | 'meizu_push' | 'apns' | 'unknown';
|
|
17
|
+
export interface PushDiagnostics {
|
|
18
|
+
platform: PushPlatform;
|
|
19
|
+
/** True when Google Play services can serve FCM; false on a ROM without GMS. */
|
|
20
|
+
gmsAvailable: boolean;
|
|
21
|
+
/** Raw GoogleApiAvailability status code. 0 means SUCCESS. */
|
|
22
|
+
gmsStatus: number;
|
|
23
|
+
manufacturer: string;
|
|
24
|
+
brand: string;
|
|
25
|
+
model: string;
|
|
26
|
+
provider: PushProvider;
|
|
27
|
+
/** Human-readable provider name, e.g. "HMS Push Kit". */
|
|
28
|
+
providerName: string;
|
|
29
|
+
/** True only when the provider service app was positively found on the device. */
|
|
30
|
+
providerInstalled?: boolean;
|
|
31
|
+
/** Actionable sentence explaining which service to use instead of the standard one. */
|
|
32
|
+
hint?: string;
|
|
33
|
+
}
|
|
16
34
|
export interface AndroidFirebaseConfig {
|
|
17
35
|
project_id?: string;
|
|
18
36
|
mobilesdk_app_id?: string;
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;AAChD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,YAAY,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/E,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB"}
|
|
1
|
+
{"version":3,"file":"types.d.ts","sourceRoot":"","sources":["../../../src/types.ts"],"names":[],"mappings":"AAAA,oFAAoF;AACpF,MAAM,MAAM,YAAY,GAAG,KAAK,GAAG,YAAY,CAAC;AAChD,MAAM,MAAM,eAAe,GAAG,SAAS,GAAG,YAAY,CAAC;AAEvD,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,KAAK,EAAE,MAAM,CAAC;IACd,WAAW,CAAC,EAAE,eAAe,CAAC;CAC/B;AAED,MAAM,WAAW,WAAW;IAC1B,EAAE,CAAC,EAAE,MAAM,CAAC;IACZ,KAAK,CAAC,EAAE,MAAM,CAAC;IACf,IAAI,CAAC,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAAC;CAC9B;AAED,MAAM,MAAM,iBAAiB,GAAG,CAAC,OAAO,EAAE,WAAW,KAAK,IAAI,GAAG,OAAO,CAAC,IAAI,CAAC,CAAC;AAE/E,MAAM,MAAM,YAAY,GACpB,KAAK,GACL,KAAK,GACL,SAAS,GACT,WAAW,GACX,WAAW,GACX,YAAY,GACZ,MAAM,GACN,SAAS,CAAC;AAEd,MAAM,WAAW,eAAe;IAC9B,QAAQ,EAAE,YAAY,CAAC;IACvB,gFAAgF;IAChF,YAAY,EAAE,OAAO,CAAC;IACtB,8DAA8D;IAC9D,SAAS,EAAE,MAAM,CAAC;IAClB,YAAY,EAAE,MAAM,CAAC;IACrB,KAAK,EAAE,MAAM,CAAC;IACd,KAAK,EAAE,MAAM,CAAC;IACd,QAAQ,EAAE,YAAY,CAAC;IACvB,yDAAyD;IACzD,YAAY,EAAE,MAAM,CAAC;IACrB,kFAAkF;IAClF,iBAAiB,CAAC,EAAE,OAAO,CAAC;IAC5B,uFAAuF;IACvF,IAAI,CAAC,EAAE,MAAM,CAAC;CACf;AAED,MAAM,WAAW,qBAAqB;IACpC,UAAU,CAAC,EAAE,MAAM,CAAC;IACpB,gBAAgB,CAAC,EAAE,MAAM,CAAC;IAC1B,WAAW,CAAC,EAAE,MAAM,CAAC;IACrB,cAAc,CAAC,EAAE,MAAM,CAAC;CACzB"}
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-push-signal",
|
|
3
|
-
"version": "0.1.
|
|
3
|
+
"version": "0.1.10",
|
|
4
4
|
"description": "React Native push notifications with direct APNs and FCM integration — get device tokens for your server and listen for incoming messages and taps",
|
|
5
5
|
"main": "./lib/module/index.js",
|
|
6
6
|
"types": "./lib/typescript/src/index.d.ts",
|
package/src/NativePushSignal.ts
CHANGED
|
@@ -14,9 +14,29 @@ export type NativePushCredentials = {
|
|
|
14
14
|
environment?: string;
|
|
15
15
|
};
|
|
16
16
|
|
|
17
|
+
export type NativePushDiagnostics = {
|
|
18
|
+
platform: string;
|
|
19
|
+
/** True when Google Play services can serve FCM; false on a ROM without GMS. */
|
|
20
|
+
gmsAvailable: boolean;
|
|
21
|
+
/** Raw GoogleApiAvailability status code. 0 means SUCCESS. */
|
|
22
|
+
gmsStatus: number;
|
|
23
|
+
manufacturer: string;
|
|
24
|
+
brand: string;
|
|
25
|
+
model: string;
|
|
26
|
+
/** Machine-readable provider id: fcm, hms, mi_push, oppo_push, vivo_push, meizu_push, apns, unknown. */
|
|
27
|
+
provider: string;
|
|
28
|
+
/** Human-readable provider name, e.g. "HMS Push Kit". */
|
|
29
|
+
providerName: string;
|
|
30
|
+
/** True when the provider service app was found on the device. */
|
|
31
|
+
providerInstalled: boolean;
|
|
32
|
+
/** Actionable sentence explaining which service to use instead of the standard one. */
|
|
33
|
+
hint?: string;
|
|
34
|
+
};
|
|
35
|
+
|
|
17
36
|
export interface Spec extends TurboModule {
|
|
18
37
|
initialize(config: Object): Promise<void>;
|
|
19
38
|
getCredentials(): Promise<NativePushCredentials>;
|
|
39
|
+
getDiagnostics(): Promise<NativePushDiagnostics>;
|
|
20
40
|
startListening(): void;
|
|
21
41
|
readonly onMessage: CodegenTypes.EventEmitter<NativePushMessage>;
|
|
22
42
|
readonly onNotificationPress: CodegenTypes.EventEmitter<NativePushMessage>;
|
|
@@ -0,0 +1,29 @@
|
|
|
1
|
+
import type { PushDiagnostics, PushProvider } from './types';
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* Error thrown by `initialize` and `getCredentials`.
|
|
5
|
+
*
|
|
6
|
+
* The message already contains a human-readable, actionable hint when the
|
|
7
|
+
* standard Google service (FCM/GMS) cannot be used. Structured details are
|
|
8
|
+
* available on the instance so the host app can decide how to log or report them.
|
|
9
|
+
*/
|
|
10
|
+
export class PushSignalError extends Error {
|
|
11
|
+
/** Machine-readable code, e.g. `E_GMS_MISSING` or `E_FCM_TOKEN`. */
|
|
12
|
+
readonly code: string;
|
|
13
|
+
/** Suggested alternative push provider, when the standard service is unusable. */
|
|
14
|
+
provider?: PushProvider;
|
|
15
|
+
/** Actionable sentence: which service to use instead of the standard one. */
|
|
16
|
+
hint?: string;
|
|
17
|
+
/** Full device/provider diagnostics if they could be collected. */
|
|
18
|
+
diagnostics?: PushDiagnostics;
|
|
19
|
+
/** Original error from the native layer. */
|
|
20
|
+
override readonly cause?: unknown;
|
|
21
|
+
|
|
22
|
+
constructor(code: string, message: string, cause?: unknown) {
|
|
23
|
+
super(message);
|
|
24
|
+
this.name = 'PushSignalError';
|
|
25
|
+
this.code = code;
|
|
26
|
+
this.cause = cause;
|
|
27
|
+
Object.setPrototypeOf(this, PushSignalError.prototype);
|
|
28
|
+
}
|
|
29
|
+
}
|
package/src/index.tsx
CHANGED
|
@@ -2,12 +2,16 @@ export type {
|
|
|
2
2
|
AndroidFirebaseConfig,
|
|
3
3
|
OnMessageListener,
|
|
4
4
|
PushCredentials,
|
|
5
|
+
PushDiagnostics,
|
|
5
6
|
PushEnvironment,
|
|
6
7
|
PushMessage,
|
|
7
8
|
PushPlatform,
|
|
9
|
+
PushProvider,
|
|
8
10
|
} from './types';
|
|
11
|
+
export { PushSignalError } from './PushSignalError';
|
|
9
12
|
export {
|
|
10
13
|
getCredentials,
|
|
14
|
+
getDiagnostics,
|
|
11
15
|
initialize,
|
|
12
16
|
onMessage,
|
|
13
17
|
onNotificationPress,
|
|
@@ -1,11 +1,15 @@
|
|
|
1
1
|
import NativePushSignal from './NativePushSignal';
|
|
2
|
+
import type { NativePushDiagnostics } from './NativePushSignal';
|
|
3
|
+
import { PushSignalError } from './PushSignalError';
|
|
2
4
|
import type {
|
|
3
5
|
AndroidFirebaseConfig,
|
|
4
6
|
OnMessageListener,
|
|
5
7
|
PushCredentials,
|
|
8
|
+
PushDiagnostics,
|
|
6
9
|
PushEnvironment,
|
|
7
10
|
PushMessage,
|
|
8
11
|
PushPlatform,
|
|
12
|
+
PushProvider,
|
|
9
13
|
} from './types';
|
|
10
14
|
|
|
11
15
|
const messageListeners = new Set<OnMessageListener>();
|
|
@@ -50,6 +54,51 @@ function normalizeCredentials(raw: {
|
|
|
50
54
|
};
|
|
51
55
|
}
|
|
52
56
|
|
|
57
|
+
function normalizeDiagnostics(raw: NativePushDiagnostics): PushDiagnostics {
|
|
58
|
+
return {
|
|
59
|
+
platform: raw.platform as PushPlatform,
|
|
60
|
+
gmsAvailable: raw.gmsAvailable,
|
|
61
|
+
gmsStatus: raw.gmsStatus,
|
|
62
|
+
manufacturer: raw.manufacturer,
|
|
63
|
+
brand: raw.brand,
|
|
64
|
+
model: raw.model,
|
|
65
|
+
provider: raw.provider as PushProvider,
|
|
66
|
+
providerName: raw.providerName,
|
|
67
|
+
providerInstalled: raw.providerInstalled ?? undefined,
|
|
68
|
+
hint: raw.hint ?? undefined,
|
|
69
|
+
};
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
function toPushSignalError(
|
|
73
|
+
error: unknown,
|
|
74
|
+
fallbackCode: string
|
|
75
|
+
): PushSignalError {
|
|
76
|
+
const candidate = error as { code?: string; message?: string } | undefined;
|
|
77
|
+
return new PushSignalError(
|
|
78
|
+
candidate?.code ?? fallbackCode,
|
|
79
|
+
candidate?.message ?? 'PushSignal request failed',
|
|
80
|
+
error
|
|
81
|
+
);
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
/**
|
|
85
|
+
* Attaches structured diagnostics to an error on a best-effort basis. Failing to
|
|
86
|
+
* collect them must never hide the original, already actionable error.
|
|
87
|
+
*/
|
|
88
|
+
async function enrichError(error: PushSignalError): Promise<PushSignalError> {
|
|
89
|
+
try {
|
|
90
|
+
const diagnostics = normalizeDiagnostics(
|
|
91
|
+
await NativePushSignal.getDiagnostics()
|
|
92
|
+
);
|
|
93
|
+
error.diagnostics = diagnostics;
|
|
94
|
+
error.provider = diagnostics.provider;
|
|
95
|
+
error.hint = diagnostics.hint;
|
|
96
|
+
} catch {
|
|
97
|
+
// Diagnostics are optional; keep the original error.
|
|
98
|
+
}
|
|
99
|
+
return error;
|
|
100
|
+
}
|
|
101
|
+
|
|
53
102
|
function bindNativeCallbacks() {
|
|
54
103
|
if (nativeCallbacksBound) {
|
|
55
104
|
return;
|
|
@@ -79,12 +128,27 @@ function bindNativeCallbacks() {
|
|
|
79
128
|
NativePushSignal.startListening();
|
|
80
129
|
}
|
|
81
130
|
|
|
82
|
-
export function initialize(
|
|
83
|
-
|
|
131
|
+
export async function initialize(
|
|
132
|
+
config: AndroidFirebaseConfig = {}
|
|
133
|
+
): Promise<void> {
|
|
134
|
+
try {
|
|
135
|
+
await NativePushSignal.initialize(config);
|
|
136
|
+
} catch (error) {
|
|
137
|
+
throw await enrichError(toPushSignalError(error, 'E_INIT'));
|
|
138
|
+
}
|
|
139
|
+
}
|
|
140
|
+
|
|
141
|
+
export async function getCredentials(): Promise<PushCredentials> {
|
|
142
|
+
try {
|
|
143
|
+
const raw = await NativePushSignal.getCredentials();
|
|
144
|
+
return normalizeCredentials(raw);
|
|
145
|
+
} catch (error) {
|
|
146
|
+
throw await enrichError(toPushSignalError(error, 'E_CREDENTIALS'));
|
|
147
|
+
}
|
|
84
148
|
}
|
|
85
149
|
|
|
86
|
-
export function
|
|
87
|
-
return NativePushSignal.
|
|
150
|
+
export async function getDiagnostics(): Promise<PushDiagnostics> {
|
|
151
|
+
return normalizeDiagnostics(await NativePushSignal.getDiagnostics());
|
|
88
152
|
}
|
|
89
153
|
|
|
90
154
|
export function onMessage(listener: OnMessageListener): () => void {
|
package/src/pushSignal.tsx
CHANGED
|
@@ -2,6 +2,7 @@ import type {
|
|
|
2
2
|
AndroidFirebaseConfig,
|
|
3
3
|
OnMessageListener,
|
|
4
4
|
PushCredentials,
|
|
5
|
+
PushDiagnostics,
|
|
5
6
|
PushMessage,
|
|
6
7
|
} from './types';
|
|
7
8
|
|
|
@@ -13,6 +14,10 @@ export async function getCredentials(): Promise<PushCredentials> {
|
|
|
13
14
|
throw new Error('Push credentials are not supported on web');
|
|
14
15
|
}
|
|
15
16
|
|
|
17
|
+
export async function getDiagnostics(): Promise<PushDiagnostics> {
|
|
18
|
+
throw new Error('Push diagnostics are not supported on web');
|
|
19
|
+
}
|
|
20
|
+
|
|
16
21
|
export function onMessage(_listener: OnMessageListener): () => void {
|
|
17
22
|
return () => {};
|
|
18
23
|
}
|
package/src/types.ts
CHANGED
|
@@ -17,6 +17,34 @@ export interface PushMessage {
|
|
|
17
17
|
|
|
18
18
|
export type OnMessageListener = (message: PushMessage) => void | Promise<void>;
|
|
19
19
|
|
|
20
|
+
export type PushProvider =
|
|
21
|
+
| 'fcm'
|
|
22
|
+
| 'hms'
|
|
23
|
+
| 'mi_push'
|
|
24
|
+
| 'oppo_push'
|
|
25
|
+
| 'vivo_push'
|
|
26
|
+
| 'meizu_push'
|
|
27
|
+
| 'apns'
|
|
28
|
+
| 'unknown';
|
|
29
|
+
|
|
30
|
+
export interface PushDiagnostics {
|
|
31
|
+
platform: PushPlatform;
|
|
32
|
+
/** True when Google Play services can serve FCM; false on a ROM without GMS. */
|
|
33
|
+
gmsAvailable: boolean;
|
|
34
|
+
/** Raw GoogleApiAvailability status code. 0 means SUCCESS. */
|
|
35
|
+
gmsStatus: number;
|
|
36
|
+
manufacturer: string;
|
|
37
|
+
brand: string;
|
|
38
|
+
model: string;
|
|
39
|
+
provider: PushProvider;
|
|
40
|
+
/** Human-readable provider name, e.g. "HMS Push Kit". */
|
|
41
|
+
providerName: string;
|
|
42
|
+
/** True only when the provider service app was positively found on the device. */
|
|
43
|
+
providerInstalled?: boolean;
|
|
44
|
+
/** Actionable sentence explaining which service to use instead of the standard one. */
|
|
45
|
+
hint?: string;
|
|
46
|
+
}
|
|
47
|
+
|
|
20
48
|
export interface AndroidFirebaseConfig {
|
|
21
49
|
project_id?: string;
|
|
22
50
|
mobilesdk_app_id?: string;
|