Add contact image to MessagingStyle notification 'Person' - android

I would like my notifications to include the contact's image.
I am using NotificationCompat and MessagingStyle do display chat messages for contacts.
This works when using the .setIcon on the person, but the image is square, so I would like to use the setUri but it doesn't display the image, instead I see the contact's first initial in a circle.
Here is the code I'm using for the notification.
Person person = new Person.Builder()
// .setIcon(contactIcon)
.setName(displayName)
.setUri(contentLookupURI)
.setKey(contactDetail)
.build();
NotificationCompat.MessagingStyle chatMessageStyle = new NotificationCompat.MessagingStyle(person);
NotificationCompat.MessagingStyle.Message notificationMessage = new
NotificationCompat.MessagingStyle.Message(
contentText,
System.currentTimeMillis(),
person
);
chatMessageStyle.addMessage(notificationMessage);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context, NOTIFICATION_MESSAGES_CHANNEL_ID)
.setSmallIcon(icon) // notification icon
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setStyle(chatMessageStyle)
.setOnlyAlertOnce(true)
.setContentTitle(displayName);
And for the contact URI used in the .setUri I'm using a library to obtain the contact id and lookupkey then use the method:
contactLookupURI =
ContactsContract.Contacts.getLookupUri(contactsList.get(0).getId(),
contactsList.get(0).getLookupKey());
Which produces this: content://com.android.contacts/contacts/lookup/3118r4-2F294339313F5B16.3789r5-2F294339313F5B16/6 which looks correct to me.
I'm not sure how new this form of the MessagingStyle method is as I can't find many examples of it's usage with a Person object.

Here is a solution for those using Remote URL with Glide
Step 1: Get Bitmap from Remote URL
private fun getAvatarFromUrl(photoUrl: String): Bitmap? {
return try {
val futureTarget = Glide.with(this)
.asBitmap()
.load(photoUrl)
.submit()
futureTarget.get()
} catch (e: Exception) {
Timber.e(e)
null
}
}
Step 2: Set Bitmap as Person.Icon
val avatar = getAvatarFromUrl(user.avatar)
val sender = Person.Builder()
.setName(msg.from?.name)
.setIcon(IconCompat.createWithBitmap(avatar))
.setImportant(true)
.build()

If you want to use resource id instead of bitmap:
val person = Person.Builder()
.setName("Name")
.setKey("Key")
.setIcon(IconCompat.createWithResource(this, R.drawable.ic_resource)).build()

Related

AppAuth-Android - Response state param did not match request state

Recently we tried to update the AppAuth-Android version used on our project from version 0.5.1.5 to 0.11.1.
When successfully login from the browser and come back to the app, there is error data and we can't continue the process.
This is how we request:
AuthorizationServiceConfiguration configuration = new AuthorizationServiceConfiguration(Uri.parse(getAuthorizationRequestUrlWithParams(getBaseUrl(), getAuthorizationUrlParameters())), Uri.parse(getAccessTokenUrl()), null);
AuthorizationRequest.Builder authRequestBuilder = new AuthorizationRequest.Builder(
configuration,
mClientId,
"code token id_token",
Uri.parse(getCallbackURI()))
.setScope(getHybridScope());
Intent completionIntent = new Intent(context, tokenActivity);
Intent cancelIntent = getCancelIntent(context, cancelActivity);
CustomTabColorSchemeParams colorSchemeParams = new CustomTabColorSchemeParams.Builder()
.setToolbarColor(ContextCompat.getColor(context,R.color.grey120))
.setSecondaryToolbarColor(ContextCompat.getColor(context,R.color.black))
.build();
int flags = 0;
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
flags |= PendingIntent.FLAG_MUTABLE;
}
mAuthService.performAuthorizationRequest(
authRequestBuilder.build(),
PendingIntent.getActivity(context, 0, completionIntent, flags),
PendingIntent.getActivity(context, 0, cancelIntent, flags),
mAuthService.createCustomTabsIntentBuilder()
.setDefaultColorSchemeParams(colorSchemeParams)
.build());
On authorization completed, the responseData has error data with description Response state param did not match request state.
After some debugging, we found out that on AuthorizationResponse.java there is a builder function that failed to get the query parameters from Uri which result in null value although the Uri string already contains all the data.
We also tried to setResponseMode to "form_post" on authRequestBuilder when requesting but it looks like it's still not supported.
Does anyone happen to solved this before?
Thanks in advance.

Why do notifications on Oreo not display unless an icon is set

Is this a platform bug or some problem in my implementation? It appears to be regardless of importance level. Version of Android is 8.1.0. Target SDK is 22 (I am stuck on that unfortunately).
val defaultChannelId = AppConstants.NOTIFICATION_DEFAULT_ID
val defaultChannelName = "New Orders - high priority"
val defaultChannel = NotificationChannel(
defaultChannelId,
defaultChannelName,
NotificationManager.IMPORTANCE_HIGH
)
defaultChannel.setSound(defaultSound, attributes)
defaultChannel.description = "When a new order arrives"
val notificationManager = NotificationManagerCompat.from(this)
notificationManager.createNotificationChannel(defaultChannel)
On button click:
Notification appears:
val builder = NotificationCompat.Builder(requireContext(), AppConstants.NOTIFICATION_DEFAULT_ID).apply {
setContentTitle("New Order Received")
setContentText("Fetching order...$payload")
setSmallIcon(R.drawable.outline_receipt_white_24)
setSound(Uri.parse("android.resource://" + activity?.packageName + "/" + R.raw.notification_decorative))
setCategory(NotificationCompat.CATEGORY_STATUS)
priority = NotificationCompat.PRIORITY_HIGH
setProgress(0, 0, true)
}
val notificationManager = NotificationManagerCompat.from(requireContext())
notificationManager.notify(payload, builder.build())
Notification does not appear:
val builder = NotificationCompat.Builder(requireContext(), AppConstants.NOTIFICATION_DEFAULT_ID).apply {
setContentTitle("New Order Received")
setContentText("Fetching order...$payload")
setSound(Uri.parse("android.resource://" + activity?.packageName + "/" + R.raw.notification_decorative))
setCategory(NotificationCompat.CATEGORY_STATUS)
priority = NotificationCompat.PRIORITY_HIGH
setProgress(0, 0, true)
}
val notificationManager = NotificationManagerCompat.from(requireContext())
notificationManager.notify(payload, builder.build())
Is this a platform bug or some problem in my implementation?
Neither, assuming that you are implying that the bug is in Oreo. You were always supposed to supply a small icon to show in the status bar. There was a bug in older versions of Android whereby you could hack a Notification such that it would not show such an icon. Malware authors thought this was great, and Google eventually fixed it.

How to play sometimes sound in notifications

I have this code to show a notification which is working as far as to show the notification, but when i run this function again, i dont get any sound.
public NotificationManager nm;
...
void ShowNotification(string title = "", string message = "", string header = "", bool notify = false)
{
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
CreateSilentNotificationChannel();
}
var text = GetText(Resource.String.Local_service_label);
// Set the icon, scrolling text and timestamp
var sinceEpoch = DateTime.UtcNow - new DateTime(1970, 1, 1);
var msSinceEpoch = (long)sinceEpoch.TotalMilliseconds;
PendingIntent contentIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(MainActivity)), 0);
PendingIntent refreshIntent = PendingIntent.GetActivity(this, 0, new Intent(this, typeof(LocalService)), 0);
Android.Net.Uri uri = RingtoneManager.GetDefaultUri(RingtoneType.Notification);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, currentNotId);
builder.SetContentTitle(GetString(Resource.String.OddEven_Notifications_AlertTitle))
.SetContentIntent(contentIntent)
.SetSmallIcon(Resource.Mipmap.ic_launcher)
.SetTicker(text)
.SetWhen(msSinceEpoch)
.SetAutoCancel(false)
.SetOngoing(true)
.SetUsesChronometer(true)
.SetShowWhen(true)
.SetContentTitle(title)
.SetVisibility((int)NotificationVisibility.Public)
.SetSubText(header)
.SetLargeIcon(BitmapFactory.DecodeResource(this.Resources, Resource.Mipmap.ic_launcher))
.SetContentText(message);
if (notify)
{
builder.SetVibrate(new long[] { 0, 400, 200, 200 });
builder.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification));
}
StickyNotification = builder.Build();
if (Build.VERSION.SdkInt < BuildVersionCodes.O && notify)
{
StickyNotification.Vibrate = new long[] { 0, 400, 200, 200 };
}
nm.Notify(NOTIFICATION, StickyNotification);
}
private void CreateSilentNotificationChannel()
{
var channelDescription = "SilentChannelForOddEvenNotification";
var chan1 = new NotificationChannel(notIDSilent, GetString(Resource.String.app_name), NotificationImportance.High)
{
Description = channelDescription,
Name = GetString(Resource.String.app_name),
};
// set the channel properties
chan1.EnableLights(true);
chan1.LightColor = Color.Red;
chan1.SetSound(null, null);
chan1.EnableVibration(false);
chan1.SetBypassDnd(true);
chan1.LockscreenVisibility = NotificationVisibility.Public;
// finally create the notification channel
//var manager = (NotificationManager)GetSystemService(NotificationService);
nm.CreateNotificationChannel(chan1);
}
i'm running the function ShowNotification() every 5 minutes but if i have the property notify true or false, i don't get any sound, why?
What is the proper way to have a sticky notification that we update regularly and sometimes we want to also have sound?
In the notification payload of the notification there is a sound key.
From the official documentation its use is:
Indicates a sound to play when the device receives a notification. Supports default or the filename of a sound resource bundled in the app. Sound files must reside in /res/raw/anySound.
{
"to" : "bk3RNwTe3H0:CI2k_HHwgIpoDKCIZvvDMExUdFQ3P1...",
"notification" : {
"body" : "great match!",
"title" : "Portugal vs. Denmark",
"icon" : "myicon",
"sound" : "default"
}
}
In the notification payload either you can use "sound" : "default" OR "sound" : "anySound"
In your case might be these lines are problematic
chan1.SetSound(null, null);
if (notify){
builder.SetVibrate(new long[] { 0, 400, 200, 200 });
builder.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Notification));
}
Beginning with Android 8.0 (Oreo), it would better to set the sound or the proority in Channel. And use the two ways below instead of chan1.SetSound(null, null);.
Use the specific ringtone for notification.
void CreateNotificationChannel()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
var channel = new NotificationChannel(CHANNEL_ID, "FCM Notifications", NotificationImportance.Default)
{
Description = "Firebase Cloud Messages appear in this channel"
};
channel.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Ringtone),alarmAttributes);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
For more details, please refer to the link below. specific ringtone firebase notification xamarin.android
Use the custom sound for notification.
void CreateNotificationChannel1()
{
if (Build.VERSION.SdkInt < BuildVersionCodes.O)
{
// Notification channels are new in API 26 (and not a part of the
// support library). There is no need to create a notification
// channel on older versions of Android.
return;
}
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
var path = Android.Net.Uri.Parse("android.resource://com.companyname.NotificationChannelsDemo/" + Resource.Raw.Hello);
var name = Resources.GetString(Resource.String.channel_name);
var description = GetString(Resource.String.channel_description);
var channel = new NotificationChannel(CHANNEL_ID1, name, NotificationImportance.Max)
{
Description = description
};
channel.SetSound(path, alarmAttributes);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
For more info, please check the link below. Custom Notification Sound FireBase

How to play different sound files on local notifications

Local notifications pop up when my Xamarin phone app receives a new event. This works fine, and it also plays a sound. However I want to play different sounds depending on the type of event that my app has received. I thought this would be simple enough, but whatever sound is played first after I rebuild the app, that is the sound that then plays for every notification regardless of the code.
For example, after rebuild, if Priority enum is Priority.Temp then TempNotif.wav will play. But if the code calls this method again to show another notification and Priority enum isn't Priority.Temp, TempNotif.wav still plays, even though I have set it to play StandardNotif.wav. It seems like android takes a copy of the first sound and doesn't bother updating it once there is a sound in place. Whatever is happening, surely I can play different sounds for different notifcations?
Here is code:
public void CreateNotification(string title, string message, Priority priority)
{
Android.Net.Uri sound = null;
if (priority == Priority.Temperature)
{
sound = global::Android.Net.Uri.Parse($!{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.TempNotif}");
}
else
{
sound = global::Android.Net.Uri.Parse($!{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.StandardNotif}");
}
var alarmAttributes = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
builder = new NotificationCompat.Builder(context, notificationChannelId);
builder.SetContentTitle(title)
.SetAutoCancel(true)
.SetContentText(message)
.SetPriority((int)NotificationPriority.High)
.SetSmallIcon(Resource.Drawable.MetroIcon)
.SetColor(00255)
.SetVibrate(new long[0])
.SetSound(sound)
.SetVisibility((int)NotificationVisibility.Public);
notificationManager = context.GetSystemService(Context.NotificationService) as
NotificationManager;
if (global::Android.OS.Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
NotificationImportance importance = NotificationImportance.High;
NotificationChannel notificationChannel = new NotificationChannel(notificationChannelId,
title, importance);
notificationChannel.Importance = NotificationImportance.High;
notificationChannel.EnableLights(true);
notificationChannel.EnableVibration(true);
notificationChannel.SetSound(sound, alarmAttributes);
notificationChannel.SetShowBadge(true);
notificationChannel.SetVibrationPattern(new long[] { 100, 200, 300, 400, 500, 400, 300, 200, 400 });
if (notificationManager != null)
{
builder.SetChannelId(notificationChannelId);
notificationManager.CreateNotificationChannel(notificationChannel);
}
}
notificationManager.Notify(0, builder.Build());
}
Credit to #Mooniean for the answer!
The answer is to provide a different channel ID for each type of notification I want to display.
I set two static values for channel ID's and provide one depending on the type of notification I want to display.
private static string StandardchannelId = "1000";
private static string TempChannelId = "2000";
Here I assign my channelID depending on an enum I made:
if (priority == Priority.Temperature)
{
this.channelId = TempChannelId;
sound = global::Android.Net.Uri.Parse($"{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.TempNotif}");
}
else
{
this.channelId = StandardchannelId;
sound = global::Android.Net.Uri.Parse($"{ContentResolver.SchemeAndroidResource}://{context.PackageName}/{Resource.Raw.StandardNotif}");
}
And here I assign the channelID:
builder.SetChannelId(this.channelId);

How to set notification channels default values ​in >= Android O

I am struggling with this problem for a banch days and cannot find proper way to do it.
I would like to set default channel settings (like sound on, lights on, vibration, lock screen notification etc.)
When I create a channel (already tried with different channel id and different package names) I always get channel with only vibration on - rest of stuff is off.
I try to create channel with this code (changing importance value makes no change in new channels):
object DefaultNotificationChannel {
#RequiresApi(Build.VERSION_CODES.O)
fun createChannel(applicationContext: Context) {
val notificationManager = applicationContext.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val sound = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + "://" + applicationContext.packageName + "/" + R.raw.notification)
createNotificationChannel(applicationContext, notificationManager, sound)
}
#TargetApi(Build.VERSION_CODES.O)
private fun createNotificationChannel(applicationContext: Context, notificationManager: NotificationManager, sound: Uri) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val name = applicationContext.getString(R.string.notification_channel_name)
val id = applicationContext.getString(R.string.default_notification_channel_id)
val importance = NotificationManager.IMPORTANCE_HIGH
val channel = NotificationChannel(id, name, importance)
channel.enableLights(true)
channel.lightColor = Color.RED
channel.enableVibration(true)
val attributes = AudioAttributes.Builder()
.setUsage(AudioAttributes.USAGE_NOTIFICATION)
.build()
channel.setSound(sound, attributes)
channel.enableVibration(true)
channel.lockscreenVisibility = Notification.VISIBILITY_PUBLIC
notificationManager.createNotificationChannel(channel)
}
}
}
I know that once channel is created the app cannot change its settings - thats why I already have tried with different ids and pacakge names.
I also have tried with application example from (Google Codelabs Notification Channels and Badges) but with the same results.
I already noticed that in some others phones everythig is ok, with Importance.HIGHT - all of switch are turned on - but not on my device.
When I install apps like Whatsapp or Viber, they channels have all settings already on - so I guess it is possible to do automatically.
I know I can always add button to open channel settings in my app, but it will be better to do it automatically when channel is registered.
Thanks in advance! :)

Categories

Resources