Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Refactor: changed deprecated intent service #24

Merged
merged 6 commits into from
Jun 20, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion personalizatio-sdk/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,8 @@ dependencies {
implementation 'com.github.bumptech.glide:glide:4.16.0'
implementation 'androidx.media3:media3-exoplayer:1.2.1'
implementation 'androidx.media3:media3-ui:1.2.1'
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.core:core-ktx:1.13.1'
implementation 'androidx.work:work-runtime-ktx:2.9.0'
}

group = 'com.personalizatio'
Expand Down
10 changes: 9 additions & 1 deletion personalizatio-sdk/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@
<action android:name="com.google.firebase.MESSAGING_EVENT" />
</intent-filter>
</service>
<service android:name=".notification.NotificationIntentService" />
<receiver
android:name=".notification.NotificationBroadcastReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="ACTION_NEXT_IMAGE" />
<action android:name="ACTION_PREVIOUS_IMAGE" />
</intent-filter>
</receiver>
</application>
</manifest>
Original file line number Diff line number Diff line change
Expand Up @@ -48,8 +48,7 @@ class RegisterManager(val sdk: SDK) {
/**
* Init device token
*/
private fun initToken()
{
private fun initToken() {
FirebaseMessaging.getInstance().token.addOnCompleteListener { task: Task<String> ->
if (!task.isSuccessful) {
SDK.error("getInstanceId failed", task.exception)
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.personalizatio.notification

import android.content.BroadcastReceiver
TorinAsakura marked this conversation as resolved.
Show resolved Hide resolved
import android.content.Context
import android.content.Intent
import androidx.work.Data
import androidx.work.OneTimeWorkRequest
import androidx.work.WorkManager
import com.personalizatio.SDK
import com.personalizatio.notification.NotificationHelper.ACTION_NEXT_IMAGE
import com.personalizatio.notification.NotificationHelper.ACTION_PREVIOUS_IMAGE
import com.personalizatio.notification.NotificationHelper.CURRENT_IMAGE_INDEX
import com.personalizatio.notification.NotificationHelper.NOTIFICATION_BODY
import com.personalizatio.notification.NotificationHelper.NOTIFICATION_IMAGES
import com.personalizatio.notification.NotificationHelper.NOTIFICATION_TITLE

class NotificationBroadcastReceiver : BroadcastReceiver() {

override fun onReceive(context: Context, intent: Intent) {
val action = intent.action

val currentIndex = intent.getIntExtra(CURRENT_IMAGE_INDEX, 0)
val images = intent.getStringExtra(NOTIFICATION_IMAGES)
val title = intent.getStringExtra(NOTIFICATION_TITLE)
val body = intent.getStringExtra(NOTIFICATION_BODY)

when (action) {
ACTION_NEXT_IMAGE, ACTION_PREVIOUS_IMAGE -> {
if (!images.isNullOrEmpty() && !title.isNullOrEmpty() && !body.isNullOrEmpty()) {
val inputData = Data.Builder()
.putString(NOTIFICATION_IMAGES, images)
.putString(NOTIFICATION_TITLE, title)
.putString(NOTIFICATION_BODY, body)
.putInt(CURRENT_IMAGE_INDEX, currentIndex)
.build()

val updateNotificationWork = OneTimeWorkRequest.Builder(
workerClass = UpdateNotificationWorker::class.java
).setInputData(inputData).build()

WorkManager.getInstance(context).enqueue(updateNotificationWork)
} else {
SDK.error("Error caught in onReceive because one of the fields is empty or null")
}
}

else -> SDK.error("Error caught in onReceive due to unknown action $action")
}
}
}
TorinAsakura marked this conversation as resolved.
Show resolved Hide resolved
Original file line number Diff line number Diff line change
Expand Up @@ -23,18 +23,16 @@ class NotificationHandler(
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channelId = context.getString(R.string.notification_channel_id)
val channelName = context.getString(R.string.notification_channel_name)
val notificationManager = context.getSystemService(NotificationManager::class.java)
when {
notificationManager != null -> notificationManager.createNotificationChannel(
NotificationChannel(
/* id = */ channelId,
/* name = */ channelName,
/* importance = */ NotificationManager.IMPORTANCE_LOW
)
val notificationManager = context.getSystemService(
NotificationManager::class.java
)
notificationManager?.createNotificationChannel(
/* channel = */ NotificationChannel(
/* id = */ channelId,
/* name = */ channelName,
/* importance = */ NotificationManager.IMPORTANCE_LOW
)

else -> error("NotificationManager not allowed")
}
)
}
}

Expand All @@ -43,26 +41,35 @@ class NotificationHandler(
sendAsync: (String, JSONObject) -> Unit,
source: Source
) {
val type = extras?.getString(NOTIFICATION_TYPE, null)
val code = extras?.getString(NOTIFICATION_ID, null)
if (type != null && code != null) {
val params = JSONObject()
try {
params.put(TYPE_PARAM, type)
params.put(CODE_PARAM, code)
sendAsync(TRACK_CLICKED, params)
if (extras == null) {
return
} else {
val type = extras.getString(NOTIFICATION_TYPE, null)
val code = extras.getString(NOTIFICATION_ID, null)

source.update(type, code, prefs())
} catch (e: JSONException) {
Log.e(TAG, e.message, e)
if (type != null && code != null) {
val params = JSONObject()
try {
params.put(TYPE_PARAM, type)
params.put(CODE_PARAM, code)
sendAsync(TRACK_CLICKED, params)

source.update(
type = type,
id = code,
preferences = prefs()
)
} catch (e: JSONException) {
Log.e(TAG, e.message, e)
}
}
}
}

fun prepareData(remoteMessage: RemoteMessage): MutableMap<String, String> {
val data: MutableMap<String, String> = HashMap(remoteMessage.data)
remoteMessage.notification?.let { notification ->
addNotificationData(notification, data)
addNotificationData(notification = notification, data = data)
}
data[IMAGES_FIELD]?.takeIf { it.isNotEmpty() }?.let { data[IMAGES_FIELD] = it }
return data
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,9 @@ import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Log
import androidx.core.app.NotificationCompat
import com.personalizatio.R
import com.personalizatio.SDK
import java.io.IOException
import java.io.InputStream
import java.net.URL
Expand All @@ -17,38 +17,40 @@ import kotlinx.coroutines.withContext

object NotificationHelper {

private const val TAG = "NotificationHelper"
private const val ACTION_PREVIOUS_IMAGE = "ACTION_PREVIOUS_IMAGE"
const val TAG = "NotificationHelper"

private const val NOTIFICATION_TYPE = "REES46_NOTIFICATION_TYPE"
private const val NOTIFICATION_CHANNEL = "notification_channel"
private const val CURRENT_IMAGE_INDEX = "current_image_index"
private const val NOTIFICATION_ID = "REES46_NOTIFICATION_ID"
private const val ACTION_NEXT_IMAGE = "ACTION_NEXT_IMAGE"
private const val NOTIFICATION_TITLE = "title"
private const val NOTIFICATION_BODY = "body"
const val ACTION_PREVIOUS_IMAGE = "ACTION_PREVIOUS_IMAGE"
const val CURRENT_IMAGE_INDEX = "current_image_index"
const val ACTION_NEXT_IMAGE = "ACTION_NEXT_IMAGE"
const val NOTIFICATION_IMAGES = "images"
const val NOTIFICATION_TITLE = "title"
const val NOTIFICATION_BODY = "body"

private val requestCodeGenerator = RequestCodeGenerator

fun createNotification(
context: Context,
data: Map<String, String?>,
images: List<Bitmap>?,
currentIndex: Int
) {
val intent = Intent(context, context::class.java).apply {
addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP or Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
putExtra(NOTIFICATION_IMAGES, data[NOTIFICATION_IMAGES])
putExtra(NOTIFICATION_TITLE, data[NOTIFICATION_TITLE])
putExtra(NOTIFICATION_BODY, data[NOTIFICATION_BODY])
putExtra(NOTIFICATION_TYPE, data[NOTIFICATION_TYPE])
putExtra(NOTIFICATION_ID, data[NOTIFICATION_ID])
putExtra(CURRENT_IMAGE_INDEX, currentIndex)
}
val intent = createNotificationIntent(
context = context,
data = data,
currentIndex = currentIndex
)

val pendingIntent = PendingIntent.getActivity(
/* context = */ context,
/* requestCode = */ 0,
/* requestCode = */ requestCodeGenerator.generateRequestCode(
action = intent.action.orEmpty(),
currentIndex = currentIndex
),
/* intent = */ intent,
/* flags = */ PendingIntent.FLAG_ONE_SHOT or PendingIntent.FLAG_IMMUTABLE
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)

val notificationBuilder = NotificationCompat.Builder(context, NOTIFICATION_CHANNEL)
Expand All @@ -58,41 +60,58 @@ object NotificationHelper {
.setAutoCancel(true)
.setContentIntent(pendingIntent)

if (!images.isNullOrEmpty()) {
if (!images.isNullOrEmpty() && currentIndex >= 0 && currentIndex < images.size) {
val currentImage = images[currentIndex]

notificationBuilder.setLargeIcon(currentImage)
.setStyle(
NotificationCompat.BigPictureStyle().bigPicture(currentImage).bigLargeIcon(null as Bitmap?)
NotificationCompat.BigPictureStyle().bigPicture(currentImage)
)

if (currentIndex > 0) {
val prevPendingIntent = createPendingIntent(
val prevIntent = createNotificationIntent(
context = context,
action = ACTION_PREVIOUS_IMAGE,
currentIndex = currentIndex,
data = data
data = data,
currentIndex = currentIndex - 1
)
val prevPendingIntent = PendingIntent.getBroadcast(
/* context = */ context,
/* requestCode = */ requestCodeGenerator.generateRequestCode(
action = prevIntent.action.orEmpty(),
currentIndex = currentIndex - 1
),
/* intent = */ prevIntent,
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
notificationBuilder.addAction(
NotificationCompat.Action.Builder(
android.R.drawable.ic_media_previous,
context.getString(R.string.notification_button_back),
prevPendingIntent
/* action = */ NotificationCompat.Action.Builder(
/* icon = */ android.R.drawable.ic_media_previous,
/* title = */ context.getString(R.string.notification_button_back),
/* intent = */ prevPendingIntent
).build()
)
}

if (currentIndex < images.size - 1) {
val nextPendingIntent = createPendingIntent(
val nextIntent = createNotificationIntent(
context = context,
action = ACTION_NEXT_IMAGE,
currentIndex = currentIndex,
data = data
data = data,
currentIndex = currentIndex + 1
)
val nextPendingIntent = PendingIntent.getBroadcast(
/* context = */ context,
/* requestCode = */ requestCodeGenerator.generateRequestCode(
action = nextIntent.action.orEmpty(),
currentIndex = currentIndex + 1
),
/* intent = */ nextIntent,
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
notificationBuilder.addAction(
NotificationCompat.Action.Builder(
android.R.drawable.ic_media_next,
context.getString(R.string.notification_button_forward),
nextPendingIntent
/* action = */ NotificationCompat.Action.Builder(
/* icon = */ android.R.drawable.ic_media_next,
/* title = */ context.getString(R.string.notification_button_forward),
/* intent = */ nextPendingIntent
).build()
)
}
Expand All @@ -104,36 +123,31 @@ object NotificationHelper {

val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager?
if (notificationManager != null) {
notificationManager.notify(0, notificationBuilder.build())
} else {
Log.e(TAG, "NotificationManager not allowed")
when {
notificationManager != null -> notificationManager.notify(
/* id = */ NOTIFICATION_ID.hashCode(),
/* notification = */ notificationBuilder.build()
)
else -> SDK.error("NotificationManager not available")
}
}

private fun createPendingIntent(
private fun createNotificationIntent(
context: Context,
action: String,
currentIndex: Int,
data: Map<String, String?>
): PendingIntent {
val intent = Intent(context, NotificationIntentService::class.java)

intent.action = action
intent.putExtra(NOTIFICATION_IMAGES, data[NOTIFICATION_IMAGES])
intent.putExtra(NOTIFICATION_TITLE, data[NOTIFICATION_TITLE])
intent.putExtra(NOTIFICATION_BODY, data[NOTIFICATION_BODY])
intent.putExtra(NOTIFICATION_TYPE, data[NOTIFICATION_TYPE])
intent.putExtra(NOTIFICATION_ID, data[NOTIFICATION_ID])
intent.putExtra(CURRENT_IMAGE_INDEX, currentIndex)

val requestCode = RequestCodeGenerator.generateRequestCode(action, currentIndex)
return PendingIntent.getService(
/* context = */ context,
/* requestCode = */ requestCode,
/* intent = */ intent,
/* flags = */ PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
data: Map<String, String?>,
currentIndex: Int
): Intent = Intent(context, NotificationBroadcastReceiver::class.java).apply {
putExtra(NOTIFICATION_IMAGES, data[NOTIFICATION_IMAGES])
putExtra(NOTIFICATION_TITLE, data[NOTIFICATION_TITLE])
putExtra(NOTIFICATION_BODY, data[NOTIFICATION_BODY])
putExtra(NOTIFICATION_TYPE, data[NOTIFICATION_TYPE])
putExtra(NOTIFICATION_ID, data[NOTIFICATION_ID])
putExtra(CURRENT_IMAGE_INDEX, currentIndex)

action = when (currentIndex) {
0 -> ACTION_NEXT_IMAGE
else -> ACTION_PREVIOUS_IMAGE
}
}

suspend fun loadBitmaps(urls: String?): List<Bitmap> {
Expand All @@ -146,7 +160,7 @@ object NotificationHelper {
val inputStream: InputStream = URL(url).openStream()
bitmaps.add(BitmapFactory.decodeStream(inputStream))
} catch (ioException: IOException) {
Log.e(TAG, "Error caught in load bitmaps", ioException)
SDK.error("Error caught in load bitmaps", ioException)
}
}
}
Expand Down
Loading