Any idea why these media controls appear fuzzy?
I'm creating the icons so:
start = Icon.createWithResource(this, android.R.drawable.ic_media_play);
pause = Icon.createWithResource(this, android.R.drawable.ic_media_pause);
reset = Icon.createWithResource(this, android.R.drawable.ic_media_previous);
finish = Icon.createWithResource(this, R.drawable.ic_media_stop);
then creating the various Notification.Action instances:
public Notification.Action getStartAction() {
PendingIntent pendingIntent = getPendingIntent(NOTI_START_CLICKED);
return new Notification.Action.Builder(start, "Start", pendingIntent).build();
}
then adding to the Notification.Builder:
Notification noti = getNotificationBuilder(time, description)
.addAction(getResetAction())
.addAction(getFinishAction())
.addAction(getStartAction())
.setStyle(new Notification.MediaStyle().
setShowActionsInCompactView(0, 1, 2))
.build();
notificationManager.notify(MEDITATION_NOTIFICATION_ID, noti);
The finish icon is my own but the others are all from the framework so I don't understand why they aren't sharp. This is built with compileSdkVersion 27 Oreo and running on Nexus 5X running 8.1.0.
Related
Here is the code for showing push notification:
// receiverUid = unique uid for a receiver
// notificationUid = unique notification_uid
// receiverName, title, body are String variables.
NotificationCompat.Builder groupBuilder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_app_icon_24)
.setColor(ColorUtils.getColor(getApplicationContext(), R.color.blue_700))
.setGroupSummary(true)
.setGroup(receiverUid)
.setAutoCancel(true)
.setSubText(receiverName)
.setContentIntent(pendingIntentGroup);
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_app_icon_24)
.setColor(ColorUtils.getColor(getApplicationContext(), R.color.blue_700))
.setContentTitle(title)
.setContentText(body)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setContentIntent(pendingIntentNotification)
.setGroup(receiverUid)
.setSubText(receiverName)
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
// group notification is based on receiverUid, so the notifications are grouped under different receipients
notificationManager.notify(receiverUid, 0, groupBuilder.build());
notificationManager.notify(receiverUid + "_" + notificationUid, 0, builder.build());
This works fine on higher android versions, but the notification text is not shown for Lollipop versions. Here is screenshot on a Lollipop device:
I debugged and verified that the text is passed here. Please suggest. Thanks in Advance.
From official doc :
Set a group summary
On Android 7.0 (API level 24) and higher, the system automatically
builds a summary for your group using snippets of text from each
notification. The user can expand this notification to see each
separate notification, as shown in figure 1. To support older
versions, which cannot show a nested group of notifications, you must
create an extra notification that acts as the summary. This appears as
the only notification and the system hides all the others. So this
summary should include a snippet from all the other notifications,
which the user can tap to open your app
The text is not displayed because the groupBuilder is the one that is displayed and it does not contain any text so for the lesser version of API 27 add your text to the groupBuilder or create a style to summarize the contents of the other notification for example :
NotificationCompat.Builder groupBuilder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_app_icon_24)
.setColor(ColorUtils.getColor(getApplicationContext(), R.color.blue_700))
.setGroupSummary(true)
.setGroup(receiverUid)
.setAutoCancel(true)
.setSubText(receiverName)
.setContentIntent(pendingIntentGroup)
.setStyle(new NotificationCompat.InboxStyle()
.addLine("Alex Faarborg Check this out")
.setBigContentTitle("2 new messages")
.setSummaryText("janedoe#example.com"));
Update :
implement the notification count and the messages summary in the Style
public class MainActivity extends AppCompatActivity {
private int notificationCount = 0;
private NotificationCompat.InboxStyle style;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// also you can Save the Notification count on the sharePreference
// for simulate the notification with multiple message
String[][] person = {{"Bill", "Jones"}, {"Janet", "Kline"}, {"George", "Bailey"},
{"Ellan", "Sanches"}, {"Tom", "Nguyen"}, {"William", "Walters"}, {"Author", "James"},
{"Henry", "Daniels"}, {"Mike", "Franklin"}, {"Julie", "Andrews"}};
// i have just testing with the TimeDownCount to add notifications every 20 seconds
CountDownTimer countDownTimer = new CountDownTimer(2000, 10) {
#Override
public void onTick(long millisUntilFinished) {
}
#Override
public void onFinish() {
// get random person from the array person
Random random = new Random();
int randomInt = random.nextInt(person.length - 1);
// show notification
showNotification(person[randomInt][0] + " " + person[randomInt][1]);
if (notificationCount < 10) {
this.start();
}
}
};
countDownTimer.start();
style = new NotificationCompat.InboxStyle();
}
private void showNotification(String message) {
notificationCount++;
style.addLine(message); // add person to the style
style.setBigContentTitle(notificationCount + " new messages"); // show Notification count in the Title
NotificationCompat.Builder groupBuilder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_baseline_mic_24)
.setColor(Color.BLUE)
.setGroupSummary(true)
.setGroup("receiverUid")
.setAutoCancel(true)
.setStyle(style)
.setSubText("Your Action");
NotificationCompat.Builder builder =
new NotificationCompat.Builder(this, "NOTIFICATION_CHANNEL")
.setSmallIcon(R.drawable.ic_baseline_mic_24)
.setColor(Color.BLUE)
.setContentTitle("title")
.setContentText("body")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setGroup("receiverUid")
.setSubText("receiverName")
.setAutoCancel(true);
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this);
notificationManager.notify("receiverUid", 0, groupBuilder.build());
notificationManager.notify("receiverUid" + "_" + "notificationUid", 0, builder.build());
}
}
overview of how the code works :
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);
I am building Notification with remote views. I have given NotificationCompat.VISIBILITY_PUBLIC. but Notification is not showing on lock screen in Oreo.
My compileSdkVersion and targetSdkVersion is 27
remoteViews = new RemoteViews(getPackageName(), R.layout.player_noti_layout);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel("default",
getString(R.string.player_channel),
NotificationManager.IMPORTANCE_LOW);
channel.setDescription("Notification, Play/pause & Next/Prev");
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
notificationmanager.createNotificationChannel(channel);
}
builder = new NotificationCompat.Builder(this, "default");
Notification foregroundNote;
// Set Icon
foregroundNote = builder.setSmallIcon(R.drawable.ic_radio)
.setTicker(getResources().getString(R.string.app_name))
.setAutoCancel(false).setOngoing(true)
.setContent(remoteViews)
.setContentTitle("app name").setContentText("").setWhen(0).setPriority(NotificationCompat.PRIORITY_MAX)
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.build();
Help appreciated!!! Thanks
try this:
Notification.Builder.setVisibility(Notification.VISIBILITY_PUBLIC);
What I found working for me is in your notificationchannel you change the LockscreenVisibility to this
channel.LockscreenVisibility = NotificationVisibility.Public;
And in your NotificationCompat.Builder
.setVisibility(NotificationCompat.VisibilityPublic)
You do seem to be using a slightly different Syntax as for me I had to capitalise .SetVisibility
I hope this still helps.
PS: Keep in mind that your phone might not allow lockscreen notifications. This also happened to me where the code worked but my phone still didn't show the notifications. ;)
I am trying to play a custom sound on the Android platform when a local notification is being displayed, the code below is based on the Xamarin Local Notification Documentation, but some fields I'm being nagged are obsolete/deprecated.
In particular, SetSound 😢
I have however tried using SetSound in the hope that it could still work, even if deprecated. But I am not sure how to reference either the mp3 files in the Android / Xamarin 'Asset' folder or the copy that I have in Android / Xamarin 'Resources/raw' folder.
/Asset contents has build action AndroidAsset
/Resources/raw contents has build action AndroidResource
This line is what is causing me the headaches ...
.SetSound(Android.Net.Uri.Parse("android.resource://MyAssemblyName.Droid/Assets/filename"));
also tried
.SetSound(Android.Net.Uri.Parse("android.resource://MyAssemblyName.Resources/raw/filename"));
Q1) What do I need to do to correctly play a custom notification sound using either the Assets or Resources folder?
Q2) Because SetSound deprecated, what am I meant to do instead?
I have cheated, partially successfully, I have a Xamarin Plugin that plays sounds, which references the same files in the portable class library (PCL) and that mechanism works (when un-commented), but only if the app is in the foreground.
It seems that my scheduled local notifications do not trigger if I swipe to 'kill' the app, even though the app will not die because I have a persistent notification that prevents the app closing (until a certain time in the future that releases the persistent notification which could be minutes later).
Q3) Why don't the scheduled local notifications trigger once the user swipes the app, even though a persistent system notification keeps the app running? Here's how that persistent notification is set up. If it wasn't for this issue I could probably get by with the hack detailed above to play the sound from the PCL.
var activity = new Intent(Android.App.Application.Context, typeof(MainActivity));
var pIntent = PendingIntent.GetActivity(this, 0, activity, 0);
var notification = new Notification.Builder(this)
.SetContentTitle("Persistent Notification Test")
.SetContentText("This is always running to ensure that you are safe.")
.SetSmallIcon(Resource.Drawable.icon)
.SetOngoing(true)
.SetDefaults(0) // no sounds
.SetContentIntent(pIntent)
.Build();
// Enlist this instance of the service as a foreground service
StartForeground(SERVICE_RUNNING_NOTIFICATION_ID, notification);
For those interested, the commented out line
// PlatformDifferences.PlaySound(soundFilename, Logger);
calls through to this method that uses the SimpleAudioPlayer plugin
public virtual void PlaySound(string soundFilenameExcludingPath, Logger logger) {
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(App)).Assembly;
Stream audioStream = assembly.GetManifestResourceStream("<my-pcl-assembly-name>.Sounds." + soundFilenameExcludingPath);
if (audioStream != null)
{
logger.Log(this, "playing sound:" + soundFilenameExcludingPath);
var player = Plugin.SimpleAudioPlayer.CrossSimpleAudioPlayer.Current;
player.Load(audioStream);
player.Play();
}
else
{
logger.Log(this, "failed - playing sound:" + soundFilenameExcludingPath);
}
}
Here's a screenshot that shows my project structure
And here's the method that I invoke whenever I want to display a notification, whether because I wanted a scheduled local notification, or because I've received a push notification and wish to show the details to the user.
private async Task DisplayLocalNotification(String title, String message, String soundFilename)
{
Logger.Log(this, "DisplayLocalNotification title:" + title + " message:" + message);
// Ensure the main activity is lauched when the app is started.
Intent secondIntent = new Intent(Android.App.Application.Context, typeof(MainActivity));
Notification.BigTextStyle textStyle = new Notification.BigTextStyle();
textStyle.BigText(message);
int length = message.Length;
if (length > 80)
{
length = 80;
}
textStyle.SetSummaryText(message.Substring(0, length));
const int pendingIntentId = 0;
PendingIntent pendingEventForMainActivity =
PendingIntent.GetActivity(Android.App.Application.Context, pendingIntentId, secondIntent, PendingIntentFlags.OneShot);
Notification.Builder builder = new Notification.Builder(Android.App.Application.Context)
.SetContentTitle(title)
.SetContentText(message)
.SetAutoCancel(true)
.SetContentIntent(pendingEventForMainActivity)
//.SetWhen () // - Now
.SetSmallIcon(Resource.Drawable.icon)
.SetVisibility(NotificationVisibility.Public)
.SetCategory(Notification.CategoryEvent)
.SetStyle(textStyle)
//.SetSound(Asset);?? What import?
//.SetSound(RingtoneManager.) ?? Looks like it's a fixed list of alert sounds
.SetDefaults(NotificationDefaults.Sound | NotificationDefaults.Vibrate) // << DEPRECATD
.SetSound(Android.Net.Uri.Parse("android.resource://My-Assembly.Droid/Assets/" + soundFilename)); // << DEPECATD
// Hack - Works (if in foreground, but no if swipe-to-kill)...
// PlatformDifferences.PlaySound(soundFilename, Logger);
// Example: .SetSound(Uri.Parse("android.resource://" + this.PackageName + "/Raw/" + Resource.Raw.woop));
if (Build.VERSION.SdkInt >= BuildVersionCodes.Lollipop)
{
builder.SetSmallIcon(Resource.Drawable.icon);// Resource.Drawable.icon_transparent);
}
else
{
builder.SetSmallIcon(Resource.Drawable.icon);
}
// Create a task stack builder to manage the back stack:
TaskStackBuilder stackBuilder = TaskStackBuilder.Create(Android.App.Application.Context);
// Add all parents of SecondActivity to the stack:
stackBuilder.AddParentStack(Java.Lang.Class.FromType(typeof(MainActivity)));
// Push the intent that starts SecondActivity onto the stack:
stackBuilder.AddNextIntent(secondIntent);
// Build the notification:
Notification androidNotification = builder.Build();
NotificationManager notificationManager =
Android.App.Application.Context.GetSystemService(Android.Content.Context.NotificationService) as NotificationManager;
// Publish the notification:
int notificationId = await StorageService.increment(Constants.STORAGE_KEY_NOTIFICATION_COUNTER);
notificationManager.Notify(notificationId, androidNotification);
Console.Out.WriteLine("DisplayLocalNotification title:" + title + " message:" + message + " published as id:" + notificationId + "?");
}
Please refer to the comments from #SushiHangover
Your screen shot is showing a API-27 device and if targetSdkVersion
was set, you would be required to use NotificationChannels (you would
need to if/else test the API levels as in my linked example). I have
seen a lot of different type of notification failures on different
(API-26+) devices, even notifications in the emulators behave
different when not using NotificationChannels.
So I am making my app compatible with Oreo and facing issue with notification.
I added notification channel according to documentation and everything is working smooth except notification keep making sound on every posting, tried setting defaults to 0 as well.
I am testing my app in emulator, any help is highly appreciated.
Used this code for creating channel
NotificationCompat.Builder builder = new NotificationCompat.Builder(PlayerService.this, "channel_01")
.setAutoCancel(false)
.setContentIntent(pendingIntent)
.setContent(viewsSmall)
.setCustomBigContentView(viewsExpanded)
.setDeleteIntent(pSwipeToDismiss);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
builder.setVisibility(Notification.VISIBILITY_PUBLIC);
}
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
builder.setPriority(Notification.PRIORITY_MAX);
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
/* Create or update. */
NotificationChannel channel = new NotificationChannel("channel_01",
"Playback Notification",
NotificationManager.IMPORTANCE_DEFAULT);
mNotificationManager.createNotificationChannel(channel);
mBuilder.setChannelId("channel_01");
}
final Notification notification = builder.build();
startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE,notification);
Take a look at the notification channel settings (swipe your notification and press the settings icon under it and then select your channel). Those settings are set the first time you create the channel and then not modified unless you do it manually in the device (at least that is my experience from uninstalling and reinstalling my app to see what settings I get by default).
Basically, channel.setSound(null, null) will only have effect when you create the channel on a fresh installation. That might be what they try to explain in the official guide:
Attempting to create an existing notification channel with its original values performs no operation
If you tried to follow that guide and set NotificationManager.IMPORTANCE_HIGH and didn't use channel.setSound(null, null), the channel would get importance level Urgent Make sound and pop on screen with the default sound.
^Benjamin answer works but he is missing some important detail! You must change your channel ID each time you adjust your code or Oreo will not make the changes. Not sure why.
My code below and you can see where the chnage must be made with this <-------here
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String channelID = "My Channel I"; <-------here
String appName = mContext.getResources().getString(R.string.app_name);
NotificationCompat.Builder notificationCompatBuilder = new NotificationCompat.Builder(mContext );
notificationCompatBuilder
.setOngoing(true)
.setContentTitle(mContext.getResources().getString(R.string.app_name))
.setContentText(mContext.getString(R.string.clocked_in))
.setSmallIcon(R.drawable.ic_action_name)
.setChannelId(channelID)
.setSound(null);
NotificationManager notificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationChannel notificationChannel = new NotificationChannel(channelID, appName, NotificationManager.IMPORTANCE_LOW);
notificationChannel.setSound(null, null);
notificationManager.createNotificationChannel(notificationChannel);
notificationManager.notify(ONGOINGNOTIFICATION_ID, notificationCompatBuilder.build());
}
Replace your code with this
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
/* Create or update. */
NotificationChannel channel = new NotificationChannel("channel_01",
"Playback Notification",
NotificationManager.IMPORTANCE_LOW);
channel.setSound(null, null);
mNotificationManager.createNotificationChannel(channel);
mBuilder.setChannelId("channel_01");
}
My scene is the first time there is a sound, and the update notification does not require a sound.
I use this setOnlyAlertOnce() method
Reference: https://developer.android.com/training/notify-user/build-notification#Updating
Test pass version 26