Skip to content

Commit 66d0311

Browse files
committed
[User Model] notification_types and model event rework
* Update `ISingletonModelStore.get()` function to be `ISingletonModelStore.model` property * Rework the model store change event system to always fire, using tags to differentiate why changes occurred. * Add `SubscriptionModel.status` to capture the subscription status, for when retrieving push token fails for some reason. * Drive event callback when app killed during request notification permission activity.
1 parent 1266cbd commit 66d0311

File tree

60 files changed

+532
-316
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

60 files changed

+532
-316
lines changed

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/OneSignalImp.kt

Lines changed: 10 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ import com.onesignal.core.internal.common.IDManager
1111
import com.onesignal.core.internal.common.OneSignalUtils
1212
import com.onesignal.core.internal.debug.DebugManager
1313
import com.onesignal.core.internal.logging.Logging
14+
import com.onesignal.core.internal.modeling.ModelChangeTags
1415
import com.onesignal.core.internal.models.ConfigModel
1516
import com.onesignal.core.internal.models.ConfigModelStore
1617
import com.onesignal.core.internal.models.IdentityModel
@@ -69,7 +70,7 @@ internal class OneSignalImp : IOneSignal, IServiceProvider {
6970
// check again now that we are synchronized.
7071
if (!_hasCreatedBackendUser) {
7172
// Create the new user in the backend as an operation
72-
_operationRepo!!.enqueue(CreateUserOperation(_configModel!!.appId, _identityModelStore!!.get().onesignalId, _identityModelStore!!.get().externalId))
73+
_operationRepo!!.enqueue(CreateUserOperation(_configModel!!.appId, _identityModelStore!!.model.onesignalId, _identityModelStore!!.model.externalId))
7374
_hasCreatedBackendUser = true
7475
}
7576
}
@@ -122,8 +123,8 @@ internal class OneSignalImp : IOneSignal, IServiceProvider {
122123
(_services.getService<IApplicationService>() as ApplicationService).start(context)
123124

124125
// get the current config model, if there is one
125-
_configModel = _services.getService<ConfigModelStore>().get()
126-
_sessionModel = _services.getService<SessionModelStore>().get()
126+
_configModel = _services.getService<ConfigModelStore>().model
127+
_sessionModel = _services.getService<SessionModelStore>().model
127128

128129
// if the app id was specified as input, update the config model with it
129130
if (appId != null) {
@@ -154,8 +155,8 @@ internal class OneSignalImp : IOneSignal, IServiceProvider {
154155
_startupService = _services.getService()
155156
_startupService!!.bootstrap()
156157

157-
if (_identityModelStore!!.get().hasProperty(IdentityConstants.ONESIGNAL_ID)) {
158-
Logging.debug("initWithContext: using cached user ${_identityModelStore!!.get().onesignalId}")
158+
if (_identityModelStore!!.model.hasProperty(IdentityConstants.ONESIGNAL_ID)) {
159+
Logging.debug("initWithContext: using cached user ${_identityModelStore!!.model.onesignalId}")
159160
_hasCreatedBackendUser = true
160161
} else {
161162
createAndSwitchToNewUser()
@@ -185,7 +186,7 @@ internal class OneSignalImp : IOneSignal, IServiceProvider {
185186
// TODO: Set JWT Token for all future requests.
186187

187188
// Create the new user in the backend as an operation
188-
_operationRepo!!.execute(CreateUserOperation(_configModel!!.appId, _identityModelStore!!.get().onesignalId, _identityModelStore!!.get().externalId))
189+
_operationRepo!!.execute(CreateUserOperation(_configModel!!.appId, _identityModelStore!!.model.onesignalId, _identityModelStore!!.model.externalId))
189190
}
190191

191192
override fun logout() {
@@ -238,10 +239,10 @@ internal class OneSignalImp : IOneSignal, IServiceProvider {
238239
subscriptions.add(newPushSubscription)
239240

240241
// The next 4 lines makes this user the effective user locally. We clear the subscriptions
241-
// first without firing the event because we don't want to drive deleting the cleared subscriptions
242+
// first as an internal change because we don't want to drive deleting the cleared subscriptions
242243
// on the backend. Once cleared we can then setup the new identity/properties model, and add
243-
// the new user's subscriptions.
244-
_subscriptionModelStore!!.clear(fireEvent = false)
244+
// the new user's subscriptions as a "normal" change, which will drive changes to the backend.
245+
_subscriptionModelStore!!.clear(ModelChangeTags.NO_PROPOGATE)
245246
_identityModelStore!!.replace(identityModel)
246247
_propertiesModelStore!!.replace(propertiesModel)
247248
_subscriptionModelStore!!.replaceAll(subscriptions)

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/backend/ISubscriptionBackendService.kt

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -13,10 +13,11 @@ internal interface ISubscriptionBackendService {
1313
* @param type The type of subscription to create.
1414
* @param enabled Whether this subscription is enabled.
1515
* @param address The subscription address.
16+
* @param status The subscription status.
1617
*
1718
* @return The ID of the subscription created.
1819
*/
19-
suspend fun createSubscription(appId: String, aliasLabel: String, aliasValue: String, type: SubscriptionObjectType, enabled: Boolean, address: String): String
20+
suspend fun createSubscription(appId: String, aliasLabel: String, aliasValue: String, type: SubscriptionObjectType, enabled: Boolean, address: String, status: Int): String
2021

2122
/**
2223
* Update an existing subscription with the properties provided.
@@ -25,8 +26,9 @@ internal interface ISubscriptionBackendService {
2526
* @param subscriptionId The ID of the subscription to update.
2627
* @param enabled Whether this subscription is enabled.
2728
* @param address The subscription address.
29+
* @param status The subscription status.
2830
*/
29-
suspend fun updateSubscription(appId: String, subscriptionId: String, enabled: Boolean, address: String)
31+
suspend fun updateSubscription(appId: String, subscriptionId: String, enabled: Boolean, address: String, status: Int)
3032

3133
/**
3234
* Delete an existing subscription.

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/backend/impl/SubscriptionBackendService.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ internal class SubscriptionBackendService(
2323
private val _http: IHttpClient
2424
) : ISubscriptionBackendService {
2525

26-
override suspend fun createSubscription(appId: String, aliasLabel: String, aliasValue: String, type: SubscriptionObjectType, enabled: Boolean, address: String): String {
26+
override suspend fun createSubscription(appId: String, aliasLabel: String, aliasValue: String, type: SubscriptionObjectType, enabled: Boolean, address: String, status: Int): String {
2727
// TODO: To Implement, temporarily using players endpoint when PUSH
2828
if (type == SubscriptionObjectType.SMS || type == SubscriptionObjectType.EMAIL) {
2929
return UUID.randomUUID().toString()
@@ -70,7 +70,7 @@ internal class SubscriptionBackendService(
7070
return responseJSON.getString("id")
7171
}
7272

73-
override suspend fun updateSubscription(appId: String, subscriptionId: String, enabled: Boolean, address: String) {
73+
override suspend fun updateSubscription(appId: String, subscriptionId: String, enabled: Boolean, address: String, status: Int) {
7474
// TODO: To Implement
7575
}
7676

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/backend/impl/UserBackendService.kt

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ import com.onesignal.core.internal.backend.IdentityConstants
77
import com.onesignal.core.internal.backend.PropertiesDeltasObject
88
import com.onesignal.core.internal.backend.PropertiesObject
99
import com.onesignal.core.internal.backend.SubscriptionObject
10+
import com.onesignal.core.internal.models.SubscriptionModel
1011
import org.json.JSONArray
1112
import org.json.JSONObject
1213
import java.util.*
@@ -34,7 +35,7 @@ internal class UserBackendService(
3435
// TODO: Temporarily using players endpoint via subscription backend to register the subscription, so we can drive push/IAMs.
3536
val subscriptionIDs = mutableListOf<String>()
3637
for (subscription in subscriptions) {
37-
val subscriptionId = _subscriptionBackend.createSubscription(appId, "", "", subscription.type, subscription.enabled ?: true, subscription.token ?: "")
38+
val subscriptionId = _subscriptionBackend.createSubscription(appId, "", "", subscription.type, subscription.enabled ?: true, subscription.token ?: "", subscription.notificationTypes ?: SubscriptionModel.STATUS_SUBSCRIBED)
3839
subscriptionIDs.add(subscriptionId)
3940
}
4041

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/common/AndroidUtils.kt

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,9 @@ import android.os.Bundle
1212
import android.os.Looper
1313
import android.text.TextUtils
1414
import androidx.annotation.Keep
15+
import androidx.core.app.JobIntentService
16+
import androidx.core.app.NotificationManagerCompat
17+
import androidx.legacy.content.WakefulBroadcastReceiver
1518
import com.onesignal.core.internal.application.IApplicationService
1619
import com.onesignal.core.internal.logging.Logging
1720
import java.util.Random
@@ -119,6 +122,33 @@ internal object AndroidUtils {
119122
return Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1
120123
}
121124

125+
fun hasJobIntentService(): Boolean {
126+
return try {
127+
// noinspection ConstantConditions
128+
JobIntentService::class.java != null
129+
} catch (e: Throwable) {
130+
false
131+
}
132+
}
133+
134+
fun hasWakefulBroadcastReceiver(): Boolean {
135+
return try {
136+
// noinspection ConstantConditions
137+
WakefulBroadcastReceiver::class.java != null
138+
} catch (e: Throwable) {
139+
false
140+
}
141+
}
142+
143+
fun hasNotificationManagerCompat(): Boolean {
144+
return try {
145+
// noinspection ConstantConditions
146+
NotificationManagerCompat::class.java != null
147+
} catch (e: Throwable) {
148+
false
149+
}
150+
}
151+
122152
fun openURLInBrowser(appContext: Context, url: String) {
123153
openURLInBrowser(appContext, Uri.parse(url.trim { it <= ' ' }))
124154
}

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/device/IDeviceService.kt

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,11 @@ internal interface IDeviceService {
1313
val isGMSInstalledAndEnabled: Boolean
1414
val hasAllHMSLibrariesForPushKit: Boolean
1515
val hasFCMLibrary: Boolean
16+
val androidSupportLibraryStatus: AndroidSupportLibraryStatus
17+
18+
enum class AndroidSupportLibraryStatus {
19+
MISSING,
20+
OUTDATED,
21+
OK
22+
}
1623
}

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/device/impl/DeviceService.kt

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
package com.onesignal.core.internal.device.impl
22

33
import android.content.pm.PackageManager
4+
import android.os.Build
45
import com.google.android.gms.common.GoogleApiAvailability
56
import com.google.android.gms.location.LocationListener
67
import com.google.firebase.messaging.FirebaseMessaging
@@ -82,6 +83,32 @@ internal class DeviceService(private val _applicationService: IApplicationServic
8283
return false
8384
}
8485

86+
override val androidSupportLibraryStatus: IDeviceService.AndroidSupportLibraryStatus
87+
get() {
88+
val hasWakefulBroadcastReceiver: Boolean = AndroidUtils.hasWakefulBroadcastReceiver()
89+
val hasNotificationManagerCompat: Boolean = AndroidUtils.hasNotificationManagerCompat()
90+
if (!hasWakefulBroadcastReceiver && !hasNotificationManagerCompat) {
91+
return IDeviceService.AndroidSupportLibraryStatus.MISSING
92+
}
93+
94+
if (!hasWakefulBroadcastReceiver || !hasNotificationManagerCompat) {
95+
return IDeviceService.AndroidSupportLibraryStatus.OUTDATED
96+
}
97+
98+
// If running on Android O and targeting O we need version 26.0.0 for
99+
// the new compat NotificationCompat.Builder constructor.
100+
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
101+
AndroidUtils.getTargetSdkVersion(_applicationService.appContext) >= Build.VERSION_CODES.O
102+
) {
103+
// Class was added in 26.0.0-beta2
104+
if (!AndroidUtils.hasJobIntentService()) {
105+
return IDeviceService.AndroidSupportLibraryStatus.OUTDATED
106+
}
107+
}
108+
109+
return IDeviceService.AndroidSupportLibraryStatus.OK
110+
}
111+
85112
private fun supportsGooglePush(): Boolean {
86113
// 1. If app does not have the FCM library it won't support Google push
87114
return if (!hasFCMLibrary) false else isGMSInstalledAndEnabled

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/http/impl/HttpClient.kt

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ internal class HttpClient(
5656
cacheKey: String?
5757
): HttpResponse {
5858
// If privacy consent is required but not yet given, any non-GET request should be blocked.
59-
if (method != null && _configModelStore.get().requiresPrivacyConsent == true && _configModelStore.get().givenPrivacyConsent != true) {
59+
if (method != null && _configModelStore.model.requiresPrivacyConsent == true && _configModelStore.model.givenPrivacyConsent != true) {
6060
Logging.warn("$method `$url` was called before the user provided privacy consent. Your application is set to require the user's privacy consent before the OneSignal SDK can be initialized. Please ensure the user has provided consent before calling this method. You can check the latest OneSignal consent status by calling OneSignal.privacyConsent")
6161
return HttpResponse(0, null, null)
6262
}

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/influence/impl/InfluenceDataRepository.kt

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -124,23 +124,23 @@ internal class InfluenceDataRepository(
124124
}
125125

126126
override val notificationLimit: Int
127-
get() = _configModelStore.get().influenceParams.notificationLimit
127+
get() = _configModelStore.model.influenceParams.notificationLimit
128128

129129
override val iamLimit: Int
130-
get() = _configModelStore.get().influenceParams.iamLimit
130+
get() = _configModelStore.model.influenceParams.iamLimit
131131

132132
override val notificationIndirectAttributionWindow: Int
133-
get() = _configModelStore.get().influenceParams.indirectNotificationAttributionWindow
133+
get() = _configModelStore.model.influenceParams.indirectNotificationAttributionWindow
134134

135135
override val iamIndirectAttributionWindow: Int
136-
get() = _configModelStore.get().influenceParams.indirectIAMAttributionWindow
136+
get() = _configModelStore.model.influenceParams.indirectIAMAttributionWindow
137137

138138
override val isDirectInfluenceEnabled: Boolean
139-
get() = _configModelStore.get().influenceParams.isDirectEnabled
139+
get() = _configModelStore.model.influenceParams.isDirectEnabled
140140

141141
override val isIndirectInfluenceEnabled: Boolean
142-
get() = _configModelStore.get().influenceParams.isIndirectEnabled
142+
get() = _configModelStore.model.influenceParams.isIndirectEnabled
143143

144144
override val isUnattributedInfluenceEnabled: Boolean
145-
get() = _configModelStore.get().influenceParams.isUnattributedEnabled
145+
get() = _configModelStore.model.influenceParams.isUnattributedEnabled
146146
}

OneSignalSDK/onesignal/src/main/java/com/onesignal/core/internal/language/impl/LanguageContext.kt

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,6 @@ internal class LanguageContext(
1010
private var _deviceLanguageProvider = LanguageProviderDevice()
1111

1212
override var language: String
13-
get() = _propertiesModelStore.get().language ?: _deviceLanguageProvider.language
14-
set(value) { _propertiesModelStore.get().language = value }
13+
get() = _propertiesModelStore.model.language ?: _deviceLanguageProvider.language
14+
set(value) { _propertiesModelStore.model.language = value }
1515
}

0 commit comments

Comments
 (0)