Fixed custom incoming call notification layout not working on some Xiaomi devices...
This commit is contained in:
parent
9572da70d4
commit
b48b9e42ed
4 changed files with 133 additions and 37 deletions
|
@ -22,10 +22,7 @@ package org.linphone.compatibility
|
||||||
import android.Manifest
|
import android.Manifest
|
||||||
import android.annotation.SuppressLint
|
import android.annotation.SuppressLint
|
||||||
import android.annotation.TargetApi
|
import android.annotation.TargetApi
|
||||||
import android.app.Activity
|
import android.app.*
|
||||||
import android.app.NotificationChannel
|
|
||||||
import android.app.NotificationManager
|
|
||||||
import android.app.PictureInPictureParams
|
|
||||||
import android.content.Context
|
import android.content.Context
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.media.AudioAttributes
|
import android.media.AudioAttributes
|
||||||
|
@ -33,10 +30,19 @@ import android.os.VibrationEffect
|
||||||
import android.os.Vibrator
|
import android.os.Vibrator
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
import android.view.inputmethod.EditorInfo
|
import android.view.inputmethod.EditorInfo
|
||||||
|
import android.widget.RemoteViews
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
|
import androidx.core.content.ContextCompat
|
||||||
|
import org.linphone.LinphoneApplication
|
||||||
import org.linphone.R
|
import org.linphone.R
|
||||||
|
import org.linphone.contact.Contact
|
||||||
|
import org.linphone.core.Call
|
||||||
import org.linphone.core.tools.Log
|
import org.linphone.core.tools.Log
|
||||||
|
import org.linphone.notifications.NotificationsManager
|
||||||
import org.linphone.telecom.NativeCallWrapper
|
import org.linphone.telecom.NativeCallWrapper
|
||||||
|
import org.linphone.utils.ImageUtils
|
||||||
|
import org.linphone.utils.LinphoneUtils
|
||||||
|
|
||||||
@TargetApi(26)
|
@TargetApi(26)
|
||||||
class Api26Compatibility {
|
class Api26Compatibility {
|
||||||
|
@ -128,6 +134,43 @@ class Api26Compatibility {
|
||||||
return WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY
|
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")
|
@SuppressLint("MissingPermission")
|
||||||
fun eventVibration(vibrator: Vibrator) {
|
fun eventVibration(vibrator: Vibrator) {
|
||||||
val effect = VibrationEffect.createWaveform(longArrayOf(0L, 100L, 100L), intArrayOf(0, VibrationEffect.DEFAULT_AMPLITUDE, 0), -1)
|
val effect = VibrationEffect.createWaveform(longArrayOf(0L, 100L, 100L), intArrayOf(0, VibrationEffect.DEFAULT_AMPLITUDE, 0), -1)
|
||||||
|
|
|
@ -25,15 +25,20 @@ import android.content.Intent
|
||||||
import android.content.pm.PackageManager
|
import android.content.pm.PackageManager
|
||||||
import android.graphics.Bitmap
|
import android.graphics.Bitmap
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
|
import android.os.Build
|
||||||
import android.os.Vibrator
|
import android.os.Vibrator
|
||||||
import android.telephony.TelephonyManager
|
import android.telephony.TelephonyManager
|
||||||
import android.view.View
|
import android.view.View
|
||||||
import android.view.WindowManager
|
import android.view.WindowManager
|
||||||
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.fragment.app.Fragment
|
import androidx.fragment.app.Fragment
|
||||||
|
import java.util.*
|
||||||
|
import org.linphone.core.Call
|
||||||
import org.linphone.core.ChatRoom
|
import org.linphone.core.ChatRoom
|
||||||
import org.linphone.core.Content
|
import org.linphone.core.Content
|
||||||
import org.linphone.mediastream.Version
|
import org.linphone.mediastream.Version
|
||||||
|
import org.linphone.notifications.NotificationsManager
|
||||||
import org.linphone.telecom.NativeCallWrapper
|
import org.linphone.telecom.NativeCallWrapper
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
|
@ -165,6 +170,17 @@ class Compatibility {
|
||||||
return WindowManager.LayoutParams.TYPE_PHONE
|
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 */
|
/* Call */
|
||||||
|
|
||||||
fun canDrawOverlay(context: Context): Boolean {
|
fun canDrawOverlay(context: Context): Boolean {
|
||||||
|
|
|
@ -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))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
|
@ -28,7 +28,6 @@ import android.graphics.Bitmap
|
||||||
import android.net.Uri
|
import android.net.Uri
|
||||||
import android.os.Bundle
|
import android.os.Bundle
|
||||||
import android.webkit.MimeTypeMap
|
import android.webkit.MimeTypeMap
|
||||||
import android.widget.RemoteViews
|
|
||||||
import androidx.core.app.NotificationCompat
|
import androidx.core.app.NotificationCompat
|
||||||
import androidx.core.app.NotificationManagerCompat
|
import androidx.core.app.NotificationManagerCompat
|
||||||
import androidx.core.app.Person
|
import androidx.core.app.Person
|
||||||
|
@ -397,7 +396,7 @@ class NotificationsManager(private val context: Context) {
|
||||||
return notifiable
|
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) {
|
return if (contact != null) {
|
||||||
contact.getPerson()
|
contact.getPerson()
|
||||||
} else {
|
} else {
|
||||||
|
@ -419,19 +418,12 @@ class NotificationsManager(private val context: Context) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
val address = LinphoneUtils.getDisplayableAddress(call.remoteAddress)
|
|
||||||
val notifiable = getNotifiableForCall(call)
|
val notifiable = getNotifiableForCall(call)
|
||||||
|
|
||||||
if (notifiable.notificationId == currentForegroundServiceNotificationId) {
|
if (notifiable.notificationId == currentForegroundServiceNotificationId) {
|
||||||
Log.w("[Notifications Manager] Incoming call notification already displayed by foreground service [${notifiable.notificationId}], skipping")
|
Log.w("[Notifications Manager] Incoming call notification already displayed by foreground service [${notifiable.notificationId}], skipping")
|
||||||
return
|
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)
|
val incomingCallNotificationIntent = Intent(context, IncomingCallActivity::class.java)
|
||||||
incomingCallNotificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
incomingCallNotificationIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
|
||||||
val pendingIntent = PendingIntent.getActivity(
|
val pendingIntent = PendingIntent.getActivity(
|
||||||
|
@ -441,33 +433,11 @@ class NotificationsManager(private val context: Context) {
|
||||||
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
|
||||||
)
|
)
|
||||||
|
|
||||||
val notificationLayoutHeadsUp = RemoteViews(context.packageName, R.layout.call_incoming_notification_heads_up)
|
val builder = Compatibility.createIncomingCallNotificationBuilder(context, call, this)
|
||||||
notificationLayoutHeadsUp.setTextViewText(R.id.caller, displayName)
|
builder
|
||||||
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))
|
|
||||||
.setFullScreenIntent(pendingIntent, true)
|
.setFullScreenIntent(pendingIntent, true)
|
||||||
.addAction(getCallDeclineAction(notifiable))
|
.addAction(getCallDeclineAction(notifiable))
|
||||||
.addAction(getCallAnswerAction(notifiable))
|
.addAction(getCallAnswerAction(notifiable))
|
||||||
.setCustomHeadsUpContentView(notificationLayoutHeadsUp)
|
|
||||||
|
|
||||||
if (!corePreferences.preventInterfaceFromShowingUp) {
|
if (!corePreferences.preventInterfaceFromShowingUp) {
|
||||||
builder.setContentIntent(pendingIntent)
|
builder.setContentIntent(pendingIntent)
|
||||||
|
|
Loading…
Reference in a new issue