@attentive-mobile/attentive-react-native-sdk 2.0.0-beta.4 → 2.0.0-beta.6
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 +146 -10
- package/android/build.gradle +4 -1
- package/android/src/main/AndroidManifest.xml +2 -0
- package/android/src/main/kotlin/com/attentivereactnativesdk/AttentiveNotificationStore.kt +60 -0
- package/android/src/main/kotlin/com/attentivereactnativesdk/AttentivePushHelper.kt +101 -0
- package/android/src/main/kotlin/com/attentivereactnativesdk/AttentiveReactNativeSdkModule.kt +192 -134
- package/android/src/test/kotlin/com/attentivereactnativesdk/AttentiveNotificationStoreTest.kt +103 -0
- package/ios/AttentiveReactNativeSdk.mm +49 -2
- package/ios/AttentiveReactNativeSdk.xcodeproj/project.xcworkspace/xcuserdata/zheref.xcuserdatad/UserInterfaceState.xcuserstate +0 -0
- package/ios/Bridging/ATTNNativeSDK.swift +35 -28
- package/lib/commonjs/NativeAttentiveReactNativeSdk.js +1 -1
- package/lib/commonjs/NativeAttentiveReactNativeSdk.js.map +1 -1
- package/lib/commonjs/eventTypes.js.map +1 -1
- package/lib/commonjs/index.js +64 -10
- package/lib/commonjs/index.js.map +1 -1
- package/lib/module/NativeAttentiveReactNativeSdk.js +2 -2
- package/lib/module/NativeAttentiveReactNativeSdk.js.map +1 -1
- package/lib/module/eventTypes.js.map +1 -1
- package/lib/module/index.js +64 -12
- package/lib/module/index.js.map +1 -1
- package/lib/typescript/NativeAttentiveReactNativeSdk.d.ts +21 -2
- package/lib/typescript/NativeAttentiveReactNativeSdk.d.ts.map +1 -1
- package/lib/typescript/index.d.ts +55 -10
- package/lib/typescript/index.d.ts.map +1 -1
- package/package.json +9 -4
- package/src/NativeAttentiveReactNativeSdk.ts +79 -53
- package/src/index.tsx +65 -11
package/README.md
CHANGED
|
@@ -169,11 +169,149 @@ Attentive.identify({phone: '+15556667777'};)
|
|
|
169
169
|
// phone: '+15556667777'
|
|
170
170
|
```
|
|
171
171
|
|
|
172
|
-
### Push Notifications (iOS
|
|
172
|
+
### Push Notifications (iOS and Android)
|
|
173
173
|
|
|
174
|
-
The SDK supports push notification integration
|
|
174
|
+
The SDK supports push notification integration on both iOS (APNs) and Android (runtime permission + optional FCM). The following sections cover iOS-specific flows and a full **App events on Android** implementation that mirrors the behavior of the [Bonni](https://github.com/attentive-mobile/attentive-react-native-sdk/tree/main/Bonni) example app.
|
|
175
175
|
|
|
176
|
-
|
|
176
|
+
---
|
|
177
|
+
|
|
178
|
+
### App Events on Android
|
|
179
|
+
|
|
180
|
+
This section describes how to implement Attentive app events on Android so they behave like the iOS flow: **regular app opens** (launch and resume from background) and **notification permission** are handled using the SDK’s native Android APIs. You can add FCM token registration and push open handling when your app uses Firebase Cloud Messaging.
|
|
181
|
+
|
|
182
|
+
| SDK method | Purpose on Android |
|
|
183
|
+
|------------|--------------------|
|
|
184
|
+
| `getPushAuthorizationStatus()` | Returns `authorized`, `denied`, or `notDetermined` (uses `POST_NOTIFICATIONS` on API 33+). Use before `handleRegularOpen` so tracking uses the correct status. |
|
|
185
|
+
| `registerForPushNotifications()` | Requests `POST_NOTIFICATIONS` on Android 13+; no-op on older versions. |
|
|
186
|
+
| `handleRegularOpen(authStatus)` | Tracks a regular app open (launch or return to foreground). Call after `identify()` and pass the result of `getPushAuthorizationStatus()`. |
|
|
187
|
+
| `registerDeviceToken` / `registerDeviceTokenWithCallback` | Optional. Register your FCM token when using Firebase Cloud Messaging. |
|
|
188
|
+
| `handlePushOpen` / `handleForegroundPush` | Optional. Call when the user opens a notification or receives one in the foreground. |
|
|
189
|
+
|
|
190
|
+
#### Overview
|
|
191
|
+
|
|
192
|
+
- **Regular app open** – Call `handleRegularOpen(authorizationStatus)` when the app is opened (launch or returning to foreground). The SDK uses this for tracking and the `/mtctrl` endpoint.
|
|
193
|
+
- **Permission status** – On Android 13+ (API 33+), notification permission is `POST_NOTIFICATIONS`. The SDK exposes `getPushAuthorizationStatus()` so you can pass the correct status into `handleRegularOpen`.
|
|
194
|
+
- **Requesting permission** – Call `registerForPushNotifications()` to trigger the system permission dialog on Android 13+; it is a no-op on older versions.
|
|
195
|
+
- **Order of operations** – Always call `identify()` before any `handleRegularOpen()` so the SDK has user context for network requests.
|
|
196
|
+
|
|
197
|
+
#### Prerequisites
|
|
198
|
+
|
|
199
|
+
1. **AndroidManifest** – Declare the notification permission for Android 13+:
|
|
200
|
+
|
|
201
|
+
```xml
|
|
202
|
+
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
|
203
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
204
|
+
<!-- other permissions -->
|
|
205
|
+
</manifest>
|
|
206
|
+
```
|
|
207
|
+
|
|
208
|
+
2. **Initialize and identify first** – In your app entry (e.g. root component `useEffect`), call `initialize(config)` and `identify(identifiers)` before any push or app-event logic.
|
|
209
|
+
|
|
210
|
+
#### 1. On app launch (Android)
|
|
211
|
+
|
|
212
|
+
Right after `identify()`, do the following for the Android path:
|
|
213
|
+
|
|
214
|
+
1. Get the current notification authorization status with `getPushAuthorizationStatus()`.
|
|
215
|
+
2. Call `handleRegularOpen(authStatus)` with that status.
|
|
216
|
+
3. Optionally call `registerForPushNotifications()` to prompt for permission (Android 13+).
|
|
217
|
+
|
|
218
|
+
```typescript
|
|
219
|
+
import { Platform } from 'react-native';
|
|
220
|
+
import {
|
|
221
|
+
initialize,
|
|
222
|
+
identify,
|
|
223
|
+
getPushAuthorizationStatus,
|
|
224
|
+
registerForPushNotifications,
|
|
225
|
+
handleRegularOpen,
|
|
226
|
+
type AttentiveSdkConfiguration,
|
|
227
|
+
type PushAuthorizationStatus,
|
|
228
|
+
} from 'attentive-react-native-sdk';
|
|
229
|
+
|
|
230
|
+
// Inside your root component (e.g. App.tsx useEffect):
|
|
231
|
+
initialize(config);
|
|
232
|
+
identify({ email: 'user@example.com', clientUserId: 'id-123' });
|
|
233
|
+
|
|
234
|
+
if (Platform.OS === 'android') {
|
|
235
|
+
getPushAuthorizationStatus()
|
|
236
|
+
.then((authStatus: PushAuthorizationStatus) => {
|
|
237
|
+
handleRegularOpen(authStatus);
|
|
238
|
+
})
|
|
239
|
+
.catch(() => {
|
|
240
|
+
handleRegularOpen('authorized'); // fallback
|
|
241
|
+
});
|
|
242
|
+
registerForPushNotifications(); // Shows permission dialog on Android 13+
|
|
243
|
+
}
|
|
244
|
+
```
|
|
245
|
+
|
|
246
|
+
#### 2. When app returns to foreground (Android)
|
|
247
|
+
|
|
248
|
+
Subscribe to `AppState` and, when the app becomes `active`, get the current status and call `handleRegularOpen` again:
|
|
249
|
+
|
|
250
|
+
```typescript
|
|
251
|
+
import { AppState } from 'react-native';
|
|
252
|
+
import { getPushAuthorizationStatus, handleRegularOpen } from 'attentive-react-native-sdk';
|
|
253
|
+
import type { PushAuthorizationStatus } from 'attentive-react-native-sdk';
|
|
254
|
+
|
|
255
|
+
const subscription = AppState.addEventListener('change', (nextAppState) => {
|
|
256
|
+
if (nextAppState === 'active' && Platform.OS === 'android') {
|
|
257
|
+
getPushAuthorizationStatus()
|
|
258
|
+
.then((authStatus: PushAuthorizationStatus) => {
|
|
259
|
+
handleRegularOpen(authStatus);
|
|
260
|
+
})
|
|
261
|
+
.catch(() => {
|
|
262
|
+
handleRegularOpen('authorized');
|
|
263
|
+
});
|
|
264
|
+
}
|
|
265
|
+
});
|
|
266
|
+
|
|
267
|
+
// Cleanup on unmount:
|
|
268
|
+
return () => subscription.remove();
|
|
269
|
+
```
|
|
270
|
+
|
|
271
|
+
#### 3. Optional: Register FCM token (Android)
|
|
272
|
+
|
|
273
|
+
**Recommended:** This React Native SDK’s Android native module depends on Attentive Android SDK **2.1.1**, which exposes `AttentiveSdk.getPushTokenWithCallback`. Calling `registerForPushNotifications()` from JS triggers that API: the SDK requests permission (when needed), fetches the FCM token, and registers it with Attentive. No separate native code is required.
|
|
274
|
+
|
|
275
|
+
**Alternative (token from JS):** If you obtain the FCM token elsewhere (e.g. Firebase Messaging), use `registerDeviceTokenWithCallback` and then call `handleRegularOpen` in the callback:
|
|
276
|
+
|
|
277
|
+
```typescript
|
|
278
|
+
import { registerDeviceTokenWithCallback, handleRegularOpen } from 'attentive-react-native-sdk';
|
|
279
|
+
|
|
280
|
+
getPushAuthorizationStatus().then((authStatus) => {
|
|
281
|
+
registerDeviceTokenWithCallback(
|
|
282
|
+
fcmToken,
|
|
283
|
+
authStatus,
|
|
284
|
+
(data, url, response, error) => {
|
|
285
|
+
if (error) {
|
|
286
|
+
console.error('Attentive token registration failed', error);
|
|
287
|
+
}
|
|
288
|
+
handleRegularOpen(authStatus);
|
|
289
|
+
}
|
|
290
|
+
);
|
|
291
|
+
});
|
|
292
|
+
```
|
|
293
|
+
|
|
294
|
+
#### 4. Optional: Handle notification opens and foreground (Android)
|
|
295
|
+
|
|
296
|
+
If you handle FCM messages (e.g. with `@react-native-firebase/messaging`), you can report notification opens and foreground receives the same way as on iOS:
|
|
297
|
+
|
|
298
|
+
- **User opened notification (background/inactive):** `handlePushOpen(payload, authorizationStatus)`
|
|
299
|
+
- **Notification received while app in foreground:** `handleForegroundPush(payload, authorizationStatus)`
|
|
300
|
+
|
|
301
|
+
Get `authorizationStatus` via `getPushAuthorizationStatus()` when handling the event.
|
|
302
|
+
|
|
303
|
+
#### Complete Android flow (reference)
|
|
304
|
+
|
|
305
|
+
The [Bonni](https://github.com/attentive-mobile/attentive-react-native-sdk/tree/main/Bonni) example app ([App.tsx](https://github.com/attentive-mobile/attentive-react-native-sdk/blob/main/Bonni/App.tsx)) implements the full flow:
|
|
306
|
+
|
|
307
|
+
1. **Launch:** `initialize` → `identify` → (Android) `getPushAuthorizationStatus()` → `handleRegularOpen(authStatus)` → `registerForPushNotifications()`.
|
|
308
|
+
2. **Foreground:** `AppState.addEventListener('change', …)` → when `active` and Android → `getPushAuthorizationStatus()` → `handleRegularOpen(authStatus)`.
|
|
309
|
+
3. **Optional:** When FCM token is available → `registerDeviceTokenWithCallback(token, authStatus, callback)` → in callback call `handleRegularOpen(authStatus)`.
|
|
310
|
+
4. **Optional:** When user opens a notification or receives one in foreground → `handlePushOpen` / `handleForegroundPush` with payload and status from `getPushAuthorizationStatus()`.
|
|
311
|
+
|
|
312
|
+
---
|
|
313
|
+
|
|
314
|
+
#### Request Push Permission (iOS)
|
|
177
315
|
|
|
178
316
|
```typescript
|
|
179
317
|
import { registerForPushNotifications } from 'attentive-react-native-sdk';
|
|
@@ -183,9 +321,9 @@ import { registerForPushNotifications } from 'attentive-react-native-sdk';
|
|
|
183
321
|
registerForPushNotifications();
|
|
184
322
|
```
|
|
185
323
|
|
|
186
|
-
#### Register Device Token
|
|
324
|
+
#### Register Device Token (iOS: APNs / Android: FCM)
|
|
187
325
|
|
|
188
|
-
When your app receives a device token
|
|
326
|
+
When your app receives a device token (APNs on iOS, FCM on Android), register it with the Attentive backend:
|
|
189
327
|
|
|
190
328
|
```typescript
|
|
191
329
|
import { registerDeviceToken } from 'attentive-react-native-sdk';
|
|
@@ -202,7 +340,7 @@ The `authorizationStatus` parameter should be one of:
|
|
|
202
340
|
- `'provisional'` - Provisional authorization (quiet notifications)
|
|
203
341
|
- `'ephemeral'` - App Clip notifications
|
|
204
342
|
|
|
205
|
-
#### Handle Push Notification Opens
|
|
343
|
+
#### Handle Push Notification Opens (iOS and Android)
|
|
206
344
|
|
|
207
345
|
When a user taps on a push notification, track the event:
|
|
208
346
|
|
|
@@ -218,7 +356,7 @@ handlePushOpened(
|
|
|
218
356
|
);
|
|
219
357
|
```
|
|
220
358
|
|
|
221
|
-
#### Handle Foreground Notifications
|
|
359
|
+
#### Handle Foreground Notifications (iOS and Android)
|
|
222
360
|
|
|
223
361
|
When a notification arrives while the app is in the foreground:
|
|
224
362
|
|
|
@@ -285,6 +423,4 @@ func application(
|
|
|
285
423
|
- [Push Notifications Setup](./PUSH_NOTIFICATIONS_SETUP.md) - General push notification setup
|
|
286
424
|
- [iOS Native SDK documentation](https://github.com/attentive-mobile/attentive-ios-sdk) - Native SDK reference
|
|
287
425
|
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
Android push notification support is not yet implemented. The push notification methods will be no-ops on Android. FCM (Firebase Cloud Messaging) integration is planned for a future release.
|
|
426
|
+
For a full Android implementation (app launch, foreground, permission, and optional FCM), see the **[App Events on Android](#app-events-on-android)** section above.
|
package/android/build.gradle
CHANGED
|
@@ -82,7 +82,10 @@ dependencies {
|
|
|
82
82
|
// For > 0.71, this will be replaced by `com.facebook.react:react-android:$version` by react gradle plugin
|
|
83
83
|
//noinspection GradleDynamicVersion
|
|
84
84
|
implementation "com.facebook.react:react-native:+"
|
|
85
|
-
|
|
85
|
+
// Use `api` so that the Attentive Android SDK types (AttentiveSdk, CustomEvent, etc.)
|
|
86
|
+
// are visible to app-level code (e.g. Bonni's AttentiveFirebaseMessagingService) that
|
|
87
|
+
// depends on this library and needs to call the SDK directly from native components.
|
|
88
|
+
api 'com.attentive:attentive-android-sdk:2.1.3-beta.1'
|
|
86
89
|
implementation "org.jetbrains.kotlin:kotlin-stdlib:1.9.10"
|
|
87
90
|
implementation(platform("org.jetbrains.kotlin:kotlin-bom:1.9.10"))
|
|
88
91
|
|
|
@@ -1,4 +1,6 @@
|
|
|
1
1
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
|
2
2
|
package="com.attentivereactnativesdk">
|
|
3
3
|
|
|
4
|
+
<!-- Required for push notification permission prompt on Android 13+ (API 33+) -->
|
|
5
|
+
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
|
|
4
6
|
</manifest>
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
package com.attentivereactnativesdk
|
|
2
|
+
|
|
3
|
+
/**
|
|
4
|
+
* In-process store for a pending initial push notification payload.
|
|
5
|
+
*
|
|
6
|
+
* When the user taps an FCM notification while the app is in the killed state,
|
|
7
|
+
* Android launches the app's main activity before the React Native bridge is
|
|
8
|
+
* initialised. The notification payload is written here by the host app's
|
|
9
|
+
* `MainActivity` and consumed exactly once by [AttentiveReactNativeSdkModule.getInitialPushNotification]
|
|
10
|
+
* after the JS layer is ready.
|
|
11
|
+
*
|
|
12
|
+
* ## Usage pattern
|
|
13
|
+
*
|
|
14
|
+
* ```kotlin
|
|
15
|
+
* // In host app's MainActivity.onCreate:
|
|
16
|
+
* intent?.extras?.let { extras ->
|
|
17
|
+
* val payload = // … extract FCM data …
|
|
18
|
+
* AttentiveNotificationStore.setPendingInitialNotification(payload)
|
|
19
|
+
* }
|
|
20
|
+
* ```
|
|
21
|
+
*
|
|
22
|
+
* ```typescript
|
|
23
|
+
* // In JS (App.tsx), after initialize():
|
|
24
|
+
* const initial = await getInitialPushNotification()
|
|
25
|
+
* if (initial) handlePushOpen(initial, authStatus)
|
|
26
|
+
* ```
|
|
27
|
+
*
|
|
28
|
+
* Thread-safety: the two public methods are `@Synchronized` so concurrent access
|
|
29
|
+
* from the main UI thread (writer) and the JS bridge thread (reader) is safe.
|
|
30
|
+
*/
|
|
31
|
+
object AttentiveNotificationStore {
|
|
32
|
+
|
|
33
|
+
@Volatile
|
|
34
|
+
private var pendingInitialNotification: Map<String, String>? = null
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Stores [payload] as the pending initial push notification.
|
|
38
|
+
*
|
|
39
|
+
* Replaces any previously stored value (only one initial notification is tracked at a time).
|
|
40
|
+
*
|
|
41
|
+
* @param payload A map of string key-value pairs representing the notification data.
|
|
42
|
+
*/
|
|
43
|
+
@Synchronized
|
|
44
|
+
fun setPendingInitialNotification(payload: Map<String, String>) {
|
|
45
|
+
pendingInitialNotification = payload
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* Returns the stored initial push notification payload and clears it atomically,
|
|
50
|
+
* ensuring the payload is delivered to the JS layer exactly once.
|
|
51
|
+
*
|
|
52
|
+
* @return The stored payload map, or `null` if no initial notification is pending.
|
|
53
|
+
*/
|
|
54
|
+
@Synchronized
|
|
55
|
+
fun getAndClear(): Map<String, String>? {
|
|
56
|
+
val pending = pendingInitialNotification
|
|
57
|
+
pendingInitialNotification = null
|
|
58
|
+
return pending
|
|
59
|
+
}
|
|
60
|
+
}
|
|
@@ -0,0 +1,101 @@
|
|
|
1
|
+
package com.attentivereactnativesdk
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import android.content.Context
|
|
5
|
+
import android.content.pm.PackageManager
|
|
6
|
+
import android.os.Build
|
|
7
|
+
import android.util.Log
|
|
8
|
+
import androidx.core.app.ActivityCompat
|
|
9
|
+
import androidx.core.content.ContextCompat
|
|
10
|
+
|
|
11
|
+
/**
|
|
12
|
+
* Android push notification permission helper for the Attentive SDK.
|
|
13
|
+
*
|
|
14
|
+
* On Android 13+ (API 33+), push notifications require the runtime permission
|
|
15
|
+
* [android.permission.POST_NOTIFICATIONS]. On older versions, notifications
|
|
16
|
+
* are allowed by default (no runtime permission).
|
|
17
|
+
*
|
|
18
|
+
* This helper provides:
|
|
19
|
+
* - [getAuthorizationStatus] – current permission status for parity with iOS
|
|
20
|
+
* - [requestPermission] – request POST_NOTIFICATIONS when needed (used by registerForPushNotifications)
|
|
21
|
+
*/
|
|
22
|
+
object AttentivePushHelper {
|
|
23
|
+
|
|
24
|
+
private const val TAG = "AttentivePushHelper"
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* Authorization status values aligned with iOS push authorization for use in handleRegularOpen etc.
|
|
28
|
+
* - "authorized" – user has granted notification permission (or API < 33)
|
|
29
|
+
* - "denied" – user was asked and denied (API 33+, when determinable via activity)
|
|
30
|
+
* - "notDetermined" – not yet requested, or unable to distinguish (API 33+ only)
|
|
31
|
+
*/
|
|
32
|
+
const val STATUS_AUTHORIZED = "authorized"
|
|
33
|
+
const val STATUS_DENIED = "denied"
|
|
34
|
+
const val STATUS_NOT_DETERMINED = "notDetermined"
|
|
35
|
+
|
|
36
|
+
/**
|
|
37
|
+
* Returns the current push notification authorization status.
|
|
38
|
+
*
|
|
39
|
+
* On API 33+: uses [android.permission.POST_NOTIFICATIONS]. When permission is not granted,
|
|
40
|
+
* uses [activity] (when provided) and [ActivityCompat.shouldShowRequestPermissionRationale]
|
|
41
|
+
* to distinguish "denied" (user was asked and declined) from "notDetermined" (not yet asked).
|
|
42
|
+
* On API < 33: returns [STATUS_AUTHORIZED] (no runtime permission required).
|
|
43
|
+
*
|
|
44
|
+
* @param context Application or Activity context
|
|
45
|
+
* @param activity Current activity, or null. When non-null on API 33+, used to detect
|
|
46
|
+
* "denied" vs "notDetermined" so downstream logic and analytics are correct for denied users.
|
|
47
|
+
* @return One of [STATUS_AUTHORIZED], [STATUS_DENIED], or [STATUS_NOT_DETERMINED]
|
|
48
|
+
*/
|
|
49
|
+
@JvmStatic
|
|
50
|
+
fun getAuthorizationStatus(context: Context, activity: Activity? = null): String {
|
|
51
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
|
52
|
+
// API 32 and below: notification permission not required at runtime
|
|
53
|
+
return STATUS_AUTHORIZED
|
|
54
|
+
}
|
|
55
|
+
return when (ContextCompat.checkSelfPermission(context, android.Manifest.permission.POST_NOTIFICATIONS)) {
|
|
56
|
+
PackageManager.PERMISSION_GRANTED -> STATUS_AUTHORIZED
|
|
57
|
+
else -> {
|
|
58
|
+
// Not granted. Use shouldShowRequestPermissionRationale when we have an Activity
|
|
59
|
+
// so we do not report "denied" users as "notDetermined" (fixes prompt-gating and analytics).
|
|
60
|
+
if (activity != null && ActivityCompat.shouldShowRequestPermissionRationale(activity, android.Manifest.permission.POST_NOTIFICATIONS)) {
|
|
61
|
+
STATUS_DENIED
|
|
62
|
+
} else {
|
|
63
|
+
STATUS_NOT_DETERMINED
|
|
64
|
+
}
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
}
|
|
68
|
+
|
|
69
|
+
/**
|
|
70
|
+
* Requests the push notification permission (POST_NOTIFICATIONS) if needed.
|
|
71
|
+
* Must be called from an [Activity] (e.g. [reactApplicationContext.currentActivity]).
|
|
72
|
+
*
|
|
73
|
+
* On API < 33 this is a no-op and returns immediately.
|
|
74
|
+
*
|
|
75
|
+
* @param activity Current activity (required for requestPermissions)
|
|
76
|
+
* @param requestCode Request code for [Activity.onRequestPermissionsResult]
|
|
77
|
+
* @return true if the permission request was started or already granted, false if activity is null or permission not applicable
|
|
78
|
+
*/
|
|
79
|
+
@JvmStatic
|
|
80
|
+
fun requestPermissionIfNeeded(activity: Activity?, requestCode: Int): Boolean {
|
|
81
|
+
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU) {
|
|
82
|
+
Log.d(TAG, "requestPermissionIfNeeded: API < 33, no runtime permission needed")
|
|
83
|
+
return true
|
|
84
|
+
}
|
|
85
|
+
if (activity == null) {
|
|
86
|
+
Log.w(TAG, "requestPermissionIfNeeded: activity is null, cannot request permission")
|
|
87
|
+
return false
|
|
88
|
+
}
|
|
89
|
+
if (ContextCompat.checkSelfPermission(activity, android.Manifest.permission.POST_NOTIFICATIONS) == PackageManager.PERMISSION_GRANTED) {
|
|
90
|
+
Log.d(TAG, "requestPermissionIfNeeded: POST_NOTIFICATIONS already granted")
|
|
91
|
+
return true
|
|
92
|
+
}
|
|
93
|
+
Log.i(TAG, "requestPermissionIfNeeded: requesting POST_NOTIFICATIONS")
|
|
94
|
+
ActivityCompat.requestPermissions(
|
|
95
|
+
activity,
|
|
96
|
+
arrayOf(android.Manifest.permission.POST_NOTIFICATIONS),
|
|
97
|
+
requestCode
|
|
98
|
+
)
|
|
99
|
+
return true
|
|
100
|
+
}
|
|
101
|
+
}
|