Skip to content

Commit

Permalink
Release 1.6.0
Browse files Browse the repository at this point in the history
  • Loading branch information
cristidregan committed Sep 4, 2023
1 parent dc156ec commit 1576943
Show file tree
Hide file tree
Showing 15 changed files with 192 additions and 114 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -14,3 +14,4 @@
/captures
.externalNativeBuild
.cxx
/app/google-services.json
15 changes: 8 additions & 7 deletions OmetriaSDK/build.gradle.kts
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
val versionName = "1.5.1"
val versionName = "1.6.0"

plugins {
id("com.android.library")
Expand All @@ -9,7 +9,7 @@ android {
compileSdk = 31

defaultConfig {
minSdk = 21
minSdk = 23
targetSdk = 29
}

Expand All @@ -34,15 +34,16 @@ dependencies {

// Android Core
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
implementation("androidx.core:core-ktx:1.8.0")
implementation("androidx.appcompat:appcompat:1.4.2")
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.security:security-crypto:1.0.0")

// Lifecycle
implementation("androidx.lifecycle:lifecycle-process:2.5.1")
implementation("androidx.lifecycle:lifecycle-common-java8:2.5.1")
implementation("androidx.lifecycle:lifecycle-process:2.6.1")
implementation("androidx.lifecycle:lifecycle-common-java8:2.6.1")

// Add the SDK for Firebase Cloud Messaging
implementation("com.google.firebase:firebase-messaging:23.0.8")
implementation("com.google.firebase:firebase-messaging:23.2.0")
}

// Publishing
Expand Down
73 changes: 50 additions & 23 deletions OmetriaSDK/src/main/java/com/android/ometriasdk/core/LocalCache.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,11 +2,14 @@ package com.android.ometriasdk.core

import android.content.Context
import android.content.SharedPreferences
import androidx.security.crypto.EncryptedSharedPreferences
import androidx.security.crypto.MasterKeys
import com.android.ometriasdk.core.event.OmetriaEvent
import com.android.ometriasdk.core.network.toJson
import com.android.ometriasdk.core.network.toOmetriaEventList

private const val LOCAL_CACHE_PREFERENCES = "LOCAL_CACHE_PREFERENCES"
private const val LOCAL_ENCRYPTED_CACHE_PREFERENCES = "LOCAL_ENCRYPTED_CACHE_PREFERENCES"
private const val IS_FIRST_APP_RUN_KEY = "IS_FIRST_APP_RUN_KEY"
private const val INSTALLATION_ID_KEY = "INSTALLATION_ID_KEY"
private const val EVENTS_KEY = "EVENTS_KEY"
Expand All @@ -20,40 +23,64 @@ private const val SDK_VERSION_RN_KEY = "SDK_VERSION_RN_KEY"

internal class LocalCache(private val context: Context) {

private val masterKey = MasterKeys.getOrCreate(MasterKeys.AES256_GCM_SPEC)
private var localCacheEncryptedPreferences: SharedPreferences

init {
val localCachePreferences = getLocalCachePreferences()
localCacheEncryptedPreferences = getLocalEncryptedCachePreferences()

if (localCachePreferences.all.isNotEmpty()) {
localCachePreferences.copyTo(localCacheEncryptedPreferences)
localCachePreferences.clear()
}
}

private fun getLocalCachePreferences(): SharedPreferences {
return context.getSharedPreferences(LOCAL_CACHE_PREFERENCES, Context.MODE_PRIVATE)
}

private fun getLocalEncryptedCachePreferences(): SharedPreferences {
return EncryptedSharedPreferences.create(
LOCAL_ENCRYPTED_CACHE_PREFERENCES,
masterKey,
context,
EncryptedSharedPreferences.PrefKeyEncryptionScheme.AES256_SIV,
EncryptedSharedPreferences.PrefValueEncryptionScheme.AES256_GCM
)
}

fun saveIsFirstAppRun(isFirstAppRun: Boolean) {
getLocalCachePreferences().edit().putBoolean(IS_FIRST_APP_RUN_KEY, isFirstAppRun).apply()
localCacheEncryptedPreferences.edit().putBoolean(IS_FIRST_APP_RUN_KEY, isFirstAppRun)
.apply()
}

fun isFirstAppRun(): Boolean {
return getLocalCachePreferences().getBoolean(IS_FIRST_APP_RUN_KEY, true)
return localCacheEncryptedPreferences.getBoolean(IS_FIRST_APP_RUN_KEY, true)
}

fun saveInstallationId(installationId: String?) {
getLocalCachePreferences().edit().putString(INSTALLATION_ID_KEY, installationId).apply()
localCacheEncryptedPreferences.edit().putString(INSTALLATION_ID_KEY, installationId).apply()
}

fun getInstallationId(): String? {
return getLocalCachePreferences().getString(INSTALLATION_ID_KEY, null)
return localCacheEncryptedPreferences.getString(INSTALLATION_ID_KEY, null)
}

fun saveEvent(ometriaEvent: OmetriaEvent) {
val eventsString =
getLocalCachePreferences().getString(EVENTS_KEY, JSON_ARRAY) ?: JSON_ARRAY
localCacheEncryptedPreferences.getString(EVENTS_KEY, JSON_ARRAY) ?: JSON_ARRAY

val eventsList = eventsString.toOmetriaEventList()

eventsList.add(ometriaEvent)

getLocalCachePreferences().edit().putString(EVENTS_KEY, eventsList.toJson().toString())
localCacheEncryptedPreferences.edit().putString(EVENTS_KEY, eventsList.toJson().toString())
.apply()
}

fun getEvents(): List<OmetriaEvent> {
val eventsString = getLocalCachePreferences().getString(EVENTS_KEY, null) ?: JSON_ARRAY
val eventsString = localCacheEncryptedPreferences.getString(EVENTS_KEY, null) ?: JSON_ARRAY

return eventsString.toOmetriaEventList()
}
Expand All @@ -68,7 +95,7 @@ internal class LocalCache(private val context: Context) {
isBeingFlushed
}

getLocalCachePreferences().edit()
localCacheEncryptedPreferences.edit()
.putString(EVENTS_KEY, cachedEvents.toJson().toString())
.apply()
}
Expand All @@ -80,62 +107,62 @@ internal class LocalCache(private val context: Context) {
eventsList.remove(eventsList.firstOrNull { it.eventId == event.eventId })
}

getLocalCachePreferences().edit().putString(EVENTS_KEY, eventsList.toJson().toString())
localCacheEncryptedPreferences.edit().putString(EVENTS_KEY, eventsList.toJson().toString())
.apply()
}

fun savePushToken(pushToken: String) {
getLocalCachePreferences().edit().putString(PUSH_TOKEN_KEY, pushToken).apply()
localCacheEncryptedPreferences.edit().putString(PUSH_TOKEN_KEY, pushToken).apply()
}

fun getPushToken(): String? {
return getLocalCachePreferences().getString(PUSH_TOKEN_KEY, null)
return localCacheEncryptedPreferences.getString(PUSH_TOKEN_KEY, null)
}

fun clearEvents() {
getLocalCachePreferences().edit().remove(EVENTS_KEY).apply()
localCacheEncryptedPreferences.edit().remove(EVENTS_KEY).apply()
}

fun saveCustomerId(customerId: String?) {
getLocalCachePreferences().edit().putString(CUSTOMER_ID_KEY, customerId).apply()
localCacheEncryptedPreferences.edit().putString(CUSTOMER_ID_KEY, customerId).apply()
}

fun getCustomerId(): String? {
return getLocalCachePreferences().getString(CUSTOMER_ID_KEY, null)
return localCacheEncryptedPreferences.getString(CUSTOMER_ID_KEY, null)
}

fun saveEmail(email: String?) {
getLocalCachePreferences().edit().putString(EMAIL_KEY, email).apply()
localCacheEncryptedPreferences.edit().putString(EMAIL_KEY, email).apply()
}

fun getEmail(): String? {
return getLocalCachePreferences().getString(EMAIL_KEY, null)
return localCacheEncryptedPreferences.getString(EMAIL_KEY, null)
}

fun clearProfileIdentifiedData() {
getLocalCachePreferences().edit().remove(CUSTOMER_ID_KEY).apply()
getLocalCachePreferences().edit().remove(EMAIL_KEY).apply()
localCacheEncryptedPreferences.edit().remove(CUSTOMER_ID_KEY).apply()
localCacheEncryptedPreferences.edit().remove(EMAIL_KEY).apply()
}

fun saveAreNotificationsEnabled(areNotificationsEnabled: Boolean) {
getLocalCachePreferences().edit()
localCacheEncryptedPreferences.edit()
.putBoolean(ARE_NOTIFICATIONS_ENABLED_KEY, areNotificationsEnabled).apply()
}

fun areNotificationsEnabled(): Boolean {
return getLocalCachePreferences().getBoolean(ARE_NOTIFICATIONS_ENABLED_KEY, true)
return localCacheEncryptedPreferences.getBoolean(ARE_NOTIFICATIONS_ENABLED_KEY, true)
}

fun saveIsFirstPermissionsUpdateEvent(isFirstPermissionsUpdateEvent: Boolean) {
getLocalCachePreferences().edit()
localCacheEncryptedPreferences.edit()
.putBoolean(IS_FIRST_PERMISSION_UPDATE_EVENT_KEY, isFirstPermissionsUpdateEvent).apply()
}

fun isFirstPermissionsUpdateEvent(): Boolean {
return getLocalCachePreferences().getBoolean(IS_FIRST_PERMISSION_UPDATE_EVENT_KEY, true)
return localCacheEncryptedPreferences.getBoolean(IS_FIRST_PERMISSION_UPDATE_EVENT_KEY, true)
}

fun getSdkVersionRN(): String? {
return getLocalCachePreferences().getString(SDK_VERSION_RN_KEY, null)
return localCacheEncryptedPreferences.getString(SDK_VERSION_RN_KEY, null)
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
package com.android.ometriasdk.core

import android.content.SharedPreferences

internal fun SharedPreferences.copyTo(dest: SharedPreferences) {
for (entry in all.entries) {
val key = entry.key
val value: Any? = entry.value
dest.set(key, value)
}
}

internal inline fun SharedPreferences.edit(operation: (SharedPreferences.Editor) -> Unit) {
val editor = this.edit()
operation(editor)
editor.apply()
}

internal fun SharedPreferences.set(key: String, value: Any?) {
when (value) {
is String? -> edit { it.putString(key, value) }
is Int -> edit { it.putInt(key, value.toInt()) }
is Boolean -> edit { it.putBoolean(key, value) }
is Float -> edit { it.putFloat(key, value.toFloat()) }
is Long -> edit { it.putLong(key, value.toLong()) }
else -> Unit
}
}

internal fun SharedPreferences.clear() {
edit { it.clear() }
}
21 changes: 21 additions & 0 deletions OmetriaSDK/src/main/java/com/android/ometriasdk/core/Ometria.kt
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import com.android.ometriasdk.core.network.Client
import com.android.ometriasdk.core.network.ConnectionFactory
import com.android.ometriasdk.core.network.OmetriaThreadPoolExecutor
import com.android.ometriasdk.core.network.toOmetriaNotification
import com.android.ometriasdk.core.network.toOmetriaNotificationBody
import com.android.ometriasdk.lifecycle.OmetriaActivityLifecycleHelper
import com.android.ometriasdk.notification.NotificationHandler
import com.android.ometriasdk.notification.OMETRIA_CHANNEL_NAME
Expand Down Expand Up @@ -169,10 +170,30 @@ class Ometria private constructor() : OmetriaNotificationInteractionHandler {
return instance
}

/**
* Extracts OmetriaNotification from RemoteMessage, then displays Push Notification and tracks
* notificationReceived event.
*/
fun onMessageReceived(remoteMessage: RemoteMessage) {
notificationHandler.handleNotification(remoteMessage)
}

/**
* Extracts OmetriaNotification from RemoteMessage and tracks notificationReceived event.
*/
fun onNotificationReceived(remoteMessage: RemoteMessage) {
notificationHandler.handleNotification(remoteMessage, false)
}

/**
* Extracts OmetriaNotification from RemoteMessage and tracks notificationInteracted event.
*/
fun onNotificationInteracted(remoteMessage: RemoteMessage) {
remoteMessage.toOmetriaNotificationBody()?.let { ometriaPushNotificationBody ->
trackNotificationInteractedEvent(ometriaPushNotificationBody.context ?: return)
}
}

fun onNewToken(token: String) {
trackPushTokenRefreshedEvent(token)
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -113,13 +113,17 @@ internal fun String.toOmetriaNotificationBody(): OmetriaNotificationBody {
)
}

internal fun RemoteMessage.toOmetriaNotification(): OmetriaNotification? {
internal fun RemoteMessage.toOmetriaNotificationBody(): OmetriaNotificationBody? {
val ometriaNotificationString = this.data[KEY_OMETRIA]
ometriaNotificationString ?: return null

return ometriaNotificationString.toOmetriaNotificationBody().toOmetriaNotification()
return ometriaNotificationString.toOmetriaNotificationBody()
}

internal fun RemoteMessage.toOmetriaNotification(): OmetriaNotification? =
toOmetriaNotificationBody()?.toOmetriaNotification()


@Suppress("UNCHECKED_CAST")
internal fun OmetriaNotificationBody.toOmetriaNotification(): OmetriaNotification {
val deepLinkActionUrl = this.deepLinkActionUrl
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,15 +35,18 @@ internal class NotificationHandler(
* Handles a received push notification
* We should handle and display the push notification only if the [remoteMessage] contains the [KEY_OMETRIA] object
*/
fun handleNotification(remoteMessage: RemoteMessage) {
val ometriaNotificationString = remoteMessage.data[KEY_OMETRIA]
ometriaNotificationString ?: return
fun handleNotification(
remoteMessage: RemoteMessage,
shouldDisplayNotification: Boolean = true
) {
val ometriaNotificationBody = remoteMessage.toOmetriaNotificationBody() ?: return

val ometriaNotificationBody = ometriaNotificationString.toOmetriaNotificationBody()
ometriaNotificationBody.context?.let {
Ometria.instance().trackNotificationReceivedEvent(it)
}

if (!shouldDisplayNotification) return

val title = remoteMessage.data[KEY_TITLE]
val body = remoteMessage.data[KEY_BODY]

Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ To install the library inside **Android Studio**, declare it as dependency in yo

```gradle
dependencies {
implementation 'com.ometria:android-sdk:1.5.1'
implementation 'com.ometria:android-sdk:1.6.0'
}
```

Expand Down
13 changes: 7 additions & 6 deletions app/build.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,10 @@ android {

defaultConfig {
applicationId = "com.android.sample"
minSdk = 21
minSdk = 23
targetSdk = 33
versionCode = 9
versionName = "1.0.6"
versionName = "1.0.8"
}
signingConfigs {
getByName("debug") {
Expand Down Expand Up @@ -53,11 +53,12 @@ dependencies {

// Support libraries
implementation("org.jetbrains.kotlin:kotlin-stdlib:$kotlinVersion")
implementation("androidx.core:core-ktx:1.8.0")
implementation("androidx.appcompat:appcompat:1.4.2")
implementation("androidx.core:core-ktx:1.10.1")
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
implementation("com.google.android.material:material:1.6.1")
implementation("com.google.android.material:material:1.9.0")
implementation("androidx.work:work-runtime:2.8.1")

// Add the SDK for Firebase Cloud Messaging
implementation("com.google.firebase:firebase-messaging:23.0.8")
implementation("com.google.firebase:firebase-messaging:23.2.0")
}
Loading

0 comments on commit 1576943

Please sign in to comment.