Fixed custom incoming call notification layout not working on some Xiaomi devices...

This commit is contained in:
Sylvain Berfini 2021-12-11 09:55:18 +01:00
parent 9572da70d4
commit b48b9e42ed
4 changed files with 133 additions and 37 deletions

View file

@ -22,10 +22,7 @@ package org.linphone.compatibility
import android.Manifest
import android.annotation.SuppressLint
import android.annotation.TargetApi
import android.app.Activity
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.PictureInPictureParams
import android.app.*
import android.content.Context
import android.content.pm.PackageManager
import android.media.AudioAttributes
@ -33,10 +30,19 @@ import android.os.VibrationEffect
import android.os.Vibrator
import android.view.WindowManager
import android.view.inputmethod.EditorInfo
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.content.ContextCompat
import org.linphone.LinphoneApplication
import org.linphone.R
import org.linphone.contact.Contact
import org.linphone.core.Call
import org.linphone.core.tools.Log
import org.linphone.notifications.NotificationsManager
import org.linphone.telecom.NativeCallWrapper
import org.linphone.utils.ImageUtils
import org.linphone.utils.LinphoneUtils
@TargetApi(26)
class Api26Compatibility {
@ -128,6 +134,43 @@ class Api26Compatibility {
return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
}
fun createIncomingCallNotificationBuilder(
context: Context,
call: Call,
notificationsManager: NotificationsManager
): NotificationCompat.Builder {
val contact: Contact? = LinphoneApplication.coreContext.contactsManager.findContactByAddress(call.remoteAddress)
val pictureUri = contact?.getContactThumbnailPictureUri()
val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri)
val displayName = contact?.fullName ?: LinphoneUtils.getDisplayName(call.remoteAddress)
val address = LinphoneUtils.getDisplayableAddress(call.remoteAddress)
val notificationLayoutHeadsUp = RemoteViews(context.packageName, R.layout.call_incoming_notification_heads_up)
notificationLayoutHeadsUp.setTextViewText(R.id.caller, displayName)
notificationLayoutHeadsUp.setTextViewText(R.id.sip_uri, address)
notificationLayoutHeadsUp.setTextViewText(R.id.incoming_call_info, context.getString(R.string.incoming_call_notification_title))
if (roundPicture != null) {
notificationLayoutHeadsUp.setImageViewBitmap(R.id.caller_picture, roundPicture)
}
return NotificationCompat.Builder(context, context.getString(R.string.notification_channel_incoming_call_id))
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.addPerson(notificationsManager.getPerson(contact, displayName, roundPicture))
.setSmallIcon(R.drawable.topbar_call_notification)
.setContentTitle(displayName)
.setContentText(context.getString(R.string.incoming_call_notification_title))
.setCategory(NotificationCompat.CATEGORY_CALL)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setShowWhen(true)
.setOngoing(true)
.setColor(ContextCompat.getColor(context, R.color.primary_color))
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
}
@SuppressLint("MissingPermission")
fun eventVibration(vibrator: Vibrator) {
val effect = VibrationEffect.createWaveform(longArrayOf(0L, 100L, 100L), intArrayOf(0, VibrationEffect.DEFAULT_AMPLITUDE, 0), -1)

View file

@ -25,15 +25,20 @@ import android.content.Intent
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import android.os.Build
import android.os.Vibrator
import android.telephony.TelephonyManager
import android.view.View
import android.view.WindowManager
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.fragment.app.Fragment
import java.util.*
import org.linphone.core.Call
import org.linphone.core.ChatRoom
import org.linphone.core.Content
import org.linphone.mediastream.Version
import org.linphone.notifications.NotificationsManager
import org.linphone.telecom.NativeCallWrapper
@Suppress("DEPRECATION")
@ -165,6 +170,17 @@ class Compatibility {
return WindowManager.LayoutParams.TYPE_PHONE
}
fun createIncomingCallNotificationBuilder(
context: Context,
call: Call,
notificationsManager: NotificationsManager
): NotificationCompat.Builder {
if (Build.MANUFACTURER.lowercase(Locale.getDefault()) == "xiaomi") {
return XiaomiCompatibility.createIncomingCallNotificationBuilder(context, call, notificationsManager)
}
return Api26Compatibility.createIncomingCallNotificationBuilder(context, call, notificationsManager)
}
/* Call */
fun canDrawOverlay(context: Context): Boolean {

View file

@ -0,0 +1,67 @@
/*
* Copyright (c) 2010-2021 Belledonne Communications SARL.
*
* This file is part of linphone-android
* (see https://www.linphone.org).
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.linphone.compatibility
import android.annotation.TargetApi
import android.app.*
import android.content.Context
import android.graphics.BitmapFactory
import androidx.core.app.NotificationCompat
import androidx.core.content.ContextCompat
import org.linphone.LinphoneApplication
import org.linphone.R
import org.linphone.contact.Contact
import org.linphone.core.Call
import org.linphone.notifications.NotificationsManager
import org.linphone.utils.ImageUtils
import org.linphone.utils.LinphoneUtils
@TargetApi(26)
class XiaomiCompatibility {
companion object {
fun createIncomingCallNotificationBuilder(
context: Context,
call: Call,
notificationsManager: NotificationsManager
): NotificationCompat.Builder {
val contact: Contact? = LinphoneApplication.coreContext.contactsManager.findContactByAddress(call.remoteAddress)
val pictureUri = contact?.getContactThumbnailPictureUri()
val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri)
val displayName = contact?.fullName ?: LinphoneUtils.getDisplayName(call.remoteAddress)
val address = LinphoneUtils.getDisplayableAddress(call.remoteAddress)
return NotificationCompat.Builder(context, context.getString(R.string.notification_channel_incoming_call_id))
.addPerson(notificationsManager.getPerson(contact, displayName, roundPicture))
.setSmallIcon(R.drawable.topbar_call_notification)
.setLargeIcon(roundPicture ?: BitmapFactory.decodeResource(context.resources, R.drawable.avatar))
.setContentTitle(displayName)
.setContentText(address)
.setSubText(context.getString(R.string.incoming_call_notification_title))
.setCategory(NotificationCompat.CATEGORY_CALL)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setShowWhen(true)
.setOngoing(true)
.setColor(ContextCompat.getColor(context, R.color.primary_color))
}
}
}

View file

@ -28,7 +28,6 @@ import android.graphics.Bitmap
import android.net.Uri
import android.os.Bundle
import android.webkit.MimeTypeMap
import android.widget.RemoteViews
import androidx.core.app.NotificationCompat
import androidx.core.app.NotificationManagerCompat
import androidx.core.app.Person
@ -397,7 +396,7 @@ class NotificationsManager(private val context: Context) {
return notifiable
}
private fun getPerson(contact: Contact?, displayName: String, picture: Bitmap?): Person {
fun getPerson(contact: Contact?, displayName: String, picture: Bitmap?): Person {
return if (contact != null) {
contact.getPerson()
} else {
@ -419,19 +418,12 @@ class NotificationsManager(private val context: Context) {
return
}
val address = LinphoneUtils.getDisplayableAddress(call.remoteAddress)
val notifiable = getNotifiableForCall(call)
if (notifiable.notificationId == currentForegroundServiceNotificationId) {
Log.w("[Notifications Manager] Incoming call notification already displayed by foreground service [${notifiable.notificationId}], skipping")
return
}
val contact: Contact? = coreContext.contactsManager.findContactByAddress(call.remoteAddress)
val pictureUri = contact?.getContactThumbnailPictureUri()
val roundPicture = ImageUtils.getRoundBitmapFromUri(context, pictureUri)
val displayName = contact?.fullName ?: LinphoneUtils.getDisplayName(call.remoteAddress)
val incomingCallNotificationIntent = Intent(context, IncomingCallActivity::class.java)
incomingCallNotificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
val pendingIntent = PendingIntent.getActivity(
@ -441,33 +433,11 @@ class NotificationsManager(private val context: Context) {
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
val notificationLayoutHeadsUp = RemoteViews(context.packageName, R.layout.call_incoming_notification_heads_up)
notificationLayoutHeadsUp.setTextViewText(R.id.caller, displayName)
notificationLayoutHeadsUp.setTextViewText(R.id.sip_uri, address)
notificationLayoutHeadsUp.setTextViewText(R.id.incoming_call_info, context.getString(R.string.incoming_call_notification_title))
if (roundPicture != null) {
notificationLayoutHeadsUp.setImageViewBitmap(R.id.caller_picture, roundPicture)
}
val builder = NotificationCompat.Builder(context, context.getString(R.string.notification_channel_incoming_call_id))
.setStyle(NotificationCompat.DecoratedCustomViewStyle())
.addPerson(getPerson(contact, displayName, roundPicture))
.setSmallIcon(R.drawable.topbar_call_notification)
.setContentTitle(displayName)
.setContentText(context.getString(R.string.incoming_call_notification_title))
.setCategory(NotificationCompat.CATEGORY_CALL)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setWhen(System.currentTimeMillis())
.setAutoCancel(false)
.setShowWhen(true)
.setOngoing(true)
.setColor(ContextCompat.getColor(context, R.color.primary_color))
val builder = Compatibility.createIncomingCallNotificationBuilder(context, call, this)
builder
.setFullScreenIntent(pendingIntent, true)
.addAction(getCallDeclineAction(notifiable))
.addAction(getCallAnswerAction(notifiable))
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
if (!corePreferences.preventInterfaceFromShowingUp) {
builder.setContentIntent(pendingIntent)