ref: separate notification form CallActivity

- create CallNotificationManager to handle notifications, to ensure separation of concerns
- create helper class CallContactAvatarHelper to get contact's avatar. It is needed by the CallActivity and CallNotificationManager
This commit is contained in:
darthpaul
2021-09-19 23:22:45 +01:00
parent 8113972a19
commit e032bdddce
3 changed files with 163 additions and 128 deletions

View File

@ -0,0 +1,49 @@
package com.simplemobiletools.dialer.helpers
import android.annotation.SuppressLint
import android.content.Context
import android.graphics.*
import android.net.Uri
import android.provider.MediaStore
import android.util.Size
import com.simplemobiletools.commons.helpers.isQPlus
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.models.CallContact
class CallContactAvatarHelper(private val context: Context) {
@SuppressLint("NewApi")
fun getCallContactAvatar(callContact: CallContact?): Bitmap? {
var bitmap: Bitmap? = null
if (callContact?.photoUri?.isNotEmpty() == true) {
val photoUri = Uri.parse(callContact.photoUri)
try {
val contentResolver = context.contentResolver
bitmap = if (isQPlus()) {
val tmbSize = context.resources.getDimension(R.dimen.list_avatar_size).toInt()
contentResolver.loadThumbnail(photoUri, Size(tmbSize, tmbSize), null)
} else {
MediaStore.Images.Media.getBitmap(contentResolver, photoUri)
}
bitmap = getCircularBitmap(bitmap!!)
} catch (ignored: Exception) {
return null
}
}
return bitmap
}
fun getCircularBitmap(bitmap: Bitmap): Bitmap {
val output = Bitmap.createBitmap(bitmap.width, bitmap.width, Bitmap.Config.ARGB_8888)
val canvas = Canvas(output)
val paint = Paint()
val rect = Rect(0, 0, bitmap.width, bitmap.height)
val radius = bitmap.width / 2.toFloat()
paint.isAntiAlias = true
canvas.drawARGB(0, 0, 0, 0)
canvas.drawCircle(radius, radius, radius, paint)
paint.xfermode = PorterDuffXfermode(PorterDuff.Mode.SRC_IN)
canvas.drawBitmap(bitmap, rect, rect, paint)
return output
}
}

View File

@ -0,0 +1,96 @@
package com.simplemobiletools.dialer.helpers
import android.annotation.SuppressLint
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PendingIntent
import android.content.Context
import android.content.Intent
import android.telecom.Call
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import com.simplemobiletools.commons.extensions.notificationManager
import com.simplemobiletools.commons.extensions.setText
import com.simplemobiletools.commons.extensions.setVisibleIf
import com.simplemobiletools.commons.helpers.isOreoPlus
import com.simplemobiletools.dialer.R
import com.simplemobiletools.dialer.activities.CallActivity
import com.simplemobiletools.dialer.receivers.CallActionReceiver
class CallNotificationManager(private val context: Context) {
private val CALL_NOTIFICATION_ID = 1
private val notificationManager = context.notificationManager
private val callContactAvatarHelper = CallContactAvatarHelper(context)
@SuppressLint("NewApi")
fun setupNotification() {
CallManager.getCallContact(context.applicationContext) { callContact ->
val callContactAvatar = callContactAvatarHelper.getCallContactAvatar(callContact)
val callState = CallManager.getState()
val channelId = "simple_dialer_call"
if (isOreoPlus()) {
val importance = NotificationManager.IMPORTANCE_DEFAULT
val name = "call_notification_channel"
NotificationChannel(channelId, name, importance).apply {
setSound(null, null)
notificationManager.createNotificationChannel(this)
}
}
val openAppIntent = Intent(context, CallActivity::class.java)
openAppIntent.flags = Intent.FLAG_ACTIVITY_BROUGHT_TO_FRONT
val openAppPendingIntent = PendingIntent.getActivity(context, 0, openAppIntent, 0)
val acceptCallIntent = Intent(context, CallActionReceiver::class.java)
acceptCallIntent.action = ACCEPT_CALL
val acceptPendingIntent = PendingIntent.getBroadcast(context, 0, acceptCallIntent, PendingIntent.FLAG_CANCEL_CURRENT)
val declineCallIntent = Intent(context, CallActionReceiver::class.java)
declineCallIntent.action = DECLINE_CALL
val declinePendingIntent = PendingIntent.getBroadcast(context, 1, declineCallIntent, PendingIntent.FLAG_CANCEL_CURRENT)
val callerName = if (callContact != null && callContact.name.isNotEmpty()) callContact.name else context.getString(R.string.unknown_caller)
val contentTextId = when (callState) {
Call.STATE_RINGING -> R.string.is_calling
Call.STATE_DIALING -> R.string.dialing
Call.STATE_DISCONNECTED -> R.string.call_ended
Call.STATE_DISCONNECTING -> R.string.call_ending
else -> R.string.ongoing_call
}
val collapsedView = RemoteViews(context.packageName, R.layout.call_notification).apply {
setText(R.id.notification_caller_name, callerName)
setText(R.id.notification_call_status, context.getString(contentTextId))
setVisibleIf(R.id.notification_accept_call, callState == Call.STATE_RINGING)
setOnClickPendingIntent(R.id.notification_decline_call, declinePendingIntent)
setOnClickPendingIntent(R.id.notification_accept_call, acceptPendingIntent)
if (callContactAvatar != null) {
setImageViewBitmap(R.id.notification_thumbnail, callContactAvatarHelper.getCircularBitmap(callContactAvatar))
}
}
val builder = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_phone_vector)
.setContentIntent(openAppPendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setCategory(Notification.CATEGORY_CALL)
.setCustomContentView(collapsedView)
.setOngoing(true)
.setSound(null)
.setUsesChronometer(callState == Call.STATE_ACTIVE)
.setChannelId(channelId)
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
val notification = builder.build()
notificationManager.notify(CALL_NOTIFICATION_ID, notification)
}
}
fun cancelNotification() {
notificationManager.cancel(CALL_NOTIFICATION_ID)
}
}