Skip to content

Commit

Permalink
Merge pull request #24 from rees46/refactor/change-intent-service
Browse files Browse the repository at this point in the history
Refactor: changed deprecated intent service
  • Loading branch information
TorinAsakura authored Jun 20, 2024
2 parents fb3c5a2 + af699a9 commit 8f2a112
Show file tree
Hide file tree
Showing 10 changed files with 251 additions and 176 deletions.
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
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")
}
}
}
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

0 comments on commit 8f2a112

Please sign in to comment.