Skip to content

Commit

Permalink
feat: add caller name and thumbnail
Browse files Browse the repository at this point in the history
  • Loading branch information
SuhasDissa committed Apr 21, 2024
1 parent 8bbf71e commit 5077e94
Showing 1 changed file with 79 additions and 7 deletions.
86 changes: 79 additions & 7 deletions app/src/main/java/com/bnyro/contacts/services/CallService.kt
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,12 @@ package com.bnyro.contacts.services
import android.annotation.SuppressLint
import android.app.Notification
import android.app.PendingIntent
import android.content.ContentResolver
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.provider.ContactsContract.PhoneLookup
import android.telecom.Call
import android.telecom.InCallService
import android.view.View
Expand All @@ -17,11 +22,17 @@ import com.bnyro.contacts.receivers.CallActionReceiver.Companion.DECLINE_CALL
import com.bnyro.contacts.ui.activities.CallActivity
import com.bnyro.contacts.util.CallManager
import com.bnyro.contacts.util.NotificationHelper
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext


class CallService : InCallService() {

private lateinit var acceptPendingIntent: PendingIntent
private lateinit var declinePendingIntent: PendingIntent
val scope = CoroutineScope(Dispatchers.Main)

override fun onCreate() {
super.onCreate()
Expand Down Expand Up @@ -50,32 +61,93 @@ class CallService : InCallService() {
call.registerCallback(callCallback)
CallManager.setCall(call)

val notification = buildNotification(call)
NotificationManagerCompat.from(this).notify(CALL_NOTIFICATION_ID, notification)
scope.launch {
val callerNumber = CallManager.callerDisplayNumber
val (thumbnailUri, contactName) = withContext(Dispatchers.IO) {
getContactName(callerNumber)
}
val contactPhoto = if (thumbnailUri != null) {
withContext(Dispatchers.IO) {
getContactPhotoThumbnail(thumbnailUri)
}
} else {
null
}

val notification = buildNotification(call, callerNumber, contactName, contactPhoto)
NotificationManagerCompat.from(this@CallService)
.notify(CALL_NOTIFICATION_ID, notification)

}
val intent = Intent(applicationContext, CallActivity::class.java)
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK)
startActivity(intent)
}

private fun getContactName(phoneNumber: String): Pair<String?, String?> {
val cr: ContentResolver = this.contentResolver
val uri = Uri.withAppendedPath(PhoneLookup.CONTENT_FILTER_URI, Uri.encode(phoneNumber))
val query =
cr.query(
uri,
arrayOf(PhoneLookup.DISPLAY_NAME, PhoneLookup.PHOTO_THUMBNAIL_URI),
null,
null,
null
)
?: return null to null
var contactName: String? = null
var contactThumbnail: String? = null

query.use { cursor ->
if (cursor.moveToFirst()) {
val nameIndex = cursor.getColumnIndex(PhoneLookup.DISPLAY_NAME)
val thumbnailIndex = cursor.getColumnIndex(PhoneLookup.PHOTO_THUMBNAIL_URI)
contactName = cursor.getString(nameIndex)
contactThumbnail = cursor.getString(thumbnailIndex)
}
}

return contactThumbnail to contactName
}

private fun getContactPhotoThumbnail(uri: String): Bitmap? {
val contentResolver = this.contentResolver
val photoThumbnailUri = Uri.parse(uri)
val assetFileDescriptor =
contentResolver.openAssetFileDescriptor(photoThumbnailUri, "r") ?: return null
val fileDescriptor = assetFileDescriptor.fileDescriptor
val bitmap = BitmapFactory.decodeFileDescriptor(fileDescriptor)
assetFileDescriptor.close()
return bitmap
}

override fun onCallRemoved(call: Call) {
super.onCallRemoved(call)
NotificationManagerCompat.from(this).cancel(CALL_NOTIFICATION_ID)
call.unregisterCallback(callCallback)
CallManager.setCall(null)
}

private fun buildNotification(call: Call): Notification {
private fun buildNotification(
call: Call,
callerNumber: String,
callerName: String?,
callersPhoto: Bitmap?
): Notification {
val collapsedView = RemoteViews(packageName, R.layout.call_notification).apply {
setTextViewText(R.id.notification_caller_name, "TODO: Get Contact Name")
setTextViewText(R.id.notification_call_status, CallManager.callerDisplayNumber)
setTextViewText(R.id.notification_caller_name, callerName ?: "Unknown Number")
setTextViewText(R.id.notification_call_status, callerNumber)
setViewVisibility(
R.id.notification_accept_call,
if (call.state == Call.STATE_RINGING) View.VISIBLE else View.GONE
)

// TODO: Set Contact Photo Bitmap
setImageViewResource(R.id.notification_thumbnail, R.drawable.round_person)
if (callersPhoto != null) {
setImageViewBitmap(R.id.notification_thumbnail, callersPhoto)
} else {
setImageViewResource(R.id.notification_thumbnail, R.drawable.round_person)
}
setOnClickPendingIntent(R.id.notification_decline_call, declinePendingIntent)
setOnClickPendingIntent(R.id.notification_accept_call, acceptPendingIntent)
}
Expand Down

0 comments on commit 5077e94

Please sign in to comment.