I am trying to provide local notification into my App with my custom sound.
I created simple app in Visual Studio, and I want show notification on FAB Click.
My problem is that, notification is displaying, but without sound.
But... After phone restart - notification works properly with sound!
My code - create channel method called in OnCreate():
string channelId = "1";
string channelName = "a";
int notificationId = 0;
private void createNotificationChannel()
{
var notMgr = (NotificationManager)GetSystemService(NotificationService);
var uri = new Android.Net.Uri.Builder()
.Scheme(ContentResolver.SchemeAndroidResource)
.Authority(Resources.GetResourcePackageName(Resource.Raw.neworder4))
.AppendPath(Resources.GetResourceTypeName(Resource.Raw.neworder4))
.AppendPath(Resources.GetResourceEntryName(Resource.Raw.neworder4))
.Build();
if (Build.VERSION.SdkInt >= BuildVersionCodes.O)
{
if (notMgr.GetNotificationChannel(channelId) == null)
{
var channel = new NotificationChannel(channelId, channelName, NotificationImportance.Default);
channel.Description = channelName;
var aa = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
channel.SetSound(uri, aa);
notMgr.CreateNotificationChannel(channel);
}
}
}
Show notification on FAB click:
private void FabOnClick(object sender, EventArgs eventArgs)
{
var notMgr = (NotificationManager)GetSystemService(NotificationService);
notificationId = notificationId + 1;
var not = new NotificationCompat.Builder(this, channelId)
.SetSmallIcon(Resource.Mipmap.ic_launcher)
.SetContentText("test")
.SetContentTitle("test")
.Build();
notMgr.Notify(notificationId, not);
}
What I'm doing wrong?
I don't want to require my users to reboot phones after app install.
Resource.Raw.neworder4 is mp3 file, and is set as Android Resource.
I use the following code to play custom sound for Local Notification, it works fine, you can take a look:
Creating channel:
string channelId = "location_notification";
string channelName = "localnotification";
int notificationId = 1000;
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;
}
Android.Net.Uri sound = Android.Net.Uri.Parse("android.resource://" + Application.Context.PackageName + "/" + Resource.Raw.MyAudio);
var aa = new AudioAttributes.Builder()
.SetContentType(AudioContentType.Sonification)
.SetUsage(AudioUsageKind.Notification).Build();
var channelDescription = "local notification!!!!";
var channel = new NotificationChannel(channelId, channelName, NotificationImportance.Max)
{
Description = channelDescription
};
channel.SetSound(sound,aa);
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
Building the notification:
private void Button3_Click(object sender, System.EventArgs e)
{
// Build the notification:
var builder = new NotificationCompat.Builder(this, channelId)
.SetAutoCancel(true) // Dismiss the notification from the notification area when the user clicks on it
.SetDefaults((int)NotificationDefaults.All)
.SetContentTitle("Button Clicked") // Set the title
//.SetSound(RingtoneManager.GetDefaultUri(RingtoneType.Alarm))
.SetSmallIcon(Resource.Drawable.addreminder); // This is the icon to display
// Finally, publish the notification:
var notificationManager = NotificationManagerCompat.From(this);
notificationManager.Notify(notificationId, builder.Build());
}
I found solution for one part of my problem (for Emulator):
https://stackoverflow.com/a/56935747
I tested notifications on physical phone with android 9.0, and there is no sound for notifications without restart phone.
For now I think provided solution is close enough for me.
Related
I has created an application to control devices and receive notifications from Firebase. There is a problem when receive notification on Android and iOS. When application is open i can received notification with sound, but on android when app to stoped, i received notification but not have sound, when app run background i received notification and sound, on iOS when app run background and stoped, both have notification but not ring.
enviroment:
react: 16.8.6
react-native: 0.60.5,
react-native-firebase: 5.5.6
Looking support to hearing from everyone. Thanks everyone!
i did it and my way is to create 1 new channel with priority = PRIORITY_MAX , and ios just enable sound when sending notification.
public class MainActivity extends NavigationActivity {
private void createNotificationChannel() {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
String id = getString(R.string.channel_id);
String name = getString(R.string.channel_name);
String description = getString(R.string.channel_description);
// Log.d("ReactNative", "MEAPP: Creating channel: " + id +", name: " + name + ", description: " + description + " .");
int importance = NotificationManager.IMPORTANCE_MAX;
NotificationChannel channel = new NotificationChannel(id, name, importance);
channel.setDescription(description);
NotificationManager notificationManager = getSystemService(NotificationManager.class);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
this.createNotificationChannel();
SplashScreen.show(this); // here
super.onCreate(savedInstanceState);
// ServiceUtil.createNotificationChannel(this);
}
}
I am trying to use ListenableWorker to perform some background API calls.
During this process I want to display notification with a progress.
I use setForegroundAsync() function as per this documentation google docs
The problem is when my ListenableWorker stops, i can still see my ongong notification and i cant remove it.
This is my refresh fucntion where I change notification parameters:
private void updateRefreshStatus(float objectsProcessed, int totalObjects) {
if (totalObjects == 0) {
setProgressAsync(new Data.Builder().putFloat(PROGRESS_CONSTANT_ID, 100.0f).build());
setForegroundAsync(createForegroundInfo(FloatFormatter.roundFloatTwoDigitsAsString(100f)));
} else {
setProgressAsync(new Data.Builder().putFloat(PROGRESS_CONSTANT_ID, (objectsProcessed / (float) totalObjects) * 100f).build());
setForegroundAsync(createForegroundInfo(FloatFormatter.roundFloatTwoDigitsAsString((objectsProcessed / (float) totalObjects) * 100f)));
}
}
This is how I create my foregroundInfo:
private ForegroundInfo createForegroundInfo(#NonNull String progress) {
Notification notification = WorkerUtils.prepareProgressNotification("Update",
"Update progress " + progress + " %",
getApplicationContext());
return new ForegroundInfo(NOTIFICATION_PROGRESS_ID,notification);
}
This is my progress notification code:
static Notification prepareProgressNotification(String title, String message, Context context) {
// Make a channel if necessary
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// Create the NotificationChannel, but only on API 26+ because
// the NotificationChannel class is new and not in the support library
CharSequence name = WorkerConstants.VERBOSE_NOTIFICATION_CHANNEL_NAME;
String description = WorkerConstants.VERBOSE_NOTIFICATION_CHANNEL_DESCRIPTION;
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel =
new NotificationChannel(WorkerConstants.CHANNEL_ID, name, importance);
channel.setDescription(description);
// Add the channel
NotificationManager notificationManager =
(NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
if (notificationManager != null) {
notificationManager.createNotificationChannel(channel);
}
}
// Create the notification
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, WorkerConstants.CHANNEL_ID)
.setContentTitle(title)
.setSmallIcon(R.drawable.ic_launcher)
.setContentText(message)
.setTicker(title)
.setOngoing(true)
.setAutoCancel(true)
.setPriority(NotificationCompat.PRIORITY_HIGH)
.setVibrate(new long[0]);
// Show the notification
return builder.build();
}
I tried calling cancelAll, cancel(id), but it does nothing in my case.
UPDATE: Removing .setOngoing(true) from builder, does nothing for me its seems like setForegroundAsync() issue?
I am developing a service using Xamarin Android 3.5. Our app targets Android 8.1 (API 27 - Oreo). I want the service to run as a foreground service. However I am getting the following error when I run the service.
Bad notification for startForeground: java.lang.RuntimeException: invalid channel for service notification: Notification(channel=null pri=1 contentView=null vibrate=null sound=null defaults=0x0 flags=0x42 color=0x00000000 vis=PRIVATE)
Here is the code for the service.
public override StartCommandResult OnStartCommand(Intent intent, StartCommandFlags flags, int startId)
{
base.OnStartCommand(intent, flags, startId);
var context = Application.Context;
const int pendingIntentId = 0;
PendingIntent pendingIntent = PendingIntent.GetActivity(context, pendingIntentId, intent, PendingIntentFlags.OneShot);
var notification = new NotificationCompat.Builder(context)
.SetContentTitle("Testing")
.SetContentText("location tracking has begun.")
.SetSmallIcon(Resource.Drawable.icon)
.SetContentIntent(pendingIntent)
.SetOngoing(true)
.Build();
// Enlist this instance of the service as a foreground service
const int Service_Running_Notification_ID = 935;
StartForeground(Service_Running_Notification_ID, notification);
return StartCommandResult.NotSticky;
}
I have updated the AndroidManifest.xml with the following.
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
In the MainActivity.cs I have the follwing code which we use to create a notification channel for sending app notifications (and which correctly creates the notification channel).
private 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 channel = new NotificationChannel(ApplicationConstants.ChannelId, ApplicationConstants.ChannelName, NotificationImportance.Default)
{
Description = ApplicationConstants.ChannelDescription
};
var notificationManager = (NotificationManager)GetSystemService(NotificationService);
notificationManager.CreateNotificationChannel(channel);
}
For Xamarin.Forms and Xamarin.Android
========Put this code in public override StartCommandResult OnStartCommand ===========
if (Build.VERSION.SdkInt >= Build.VERSION_CODES.O)
RegisterForegroundServiceO();
else { RegisterForegroundService(); }
========================================END=============================
void RegisterForegroundService()
{
var notification = new Notification.Builder(this)
.SetContentTitle(Resources.GetString(Resource.String.app_name))
.SetContentText(Resources.GetString(Resource.String.notification_text))
.SetSmallIcon(Resource.Drawable.icon_userProfile)
.SetContentIntent(BuildIntentToShowMainActivity())
.SetOngoing(true)
.Build();
const int Service_Running_Notification_ID = 936;
StartForeground(Service_Running_Notification_ID, notification);
}
void RegisterForegroundServiceO()
{
String NOTIFICATION_CHANNEL_ID = "com.Your.project.id";
NotificationChannel chan = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "Your Channel Name", NotificationManager.ImportanceHigh);
NotificationManager manager = (NotificationManager)GetSystemService(Context.NotificationService);
manager.CreateNotificationChannel(chan);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID);
Notification notification= notificationBuilder.SetOngoing(true)
.SetContentTitle(Resources.GetString(Resource.String.app_name))
.SetContentText(Resources.GetString(Resource.String.notification_text))
.SetSmallIcon(Resource.Drawable.icon_userProfile)
.SetContentIntent(BuildIntentToShowMainActivity())
.SetOngoing(true)
.Build();
const int Service_Running_Notification_ID = 936;
StartForeground(Service_Running_Notification_ID, notification);
}
Happy Coding. :-)
invalid channel for service notification
You are creating a notification channel but never assigning it in your NotificationCompat.Builder:
var notification = new NotificationCompat.Builder(context)
~~~
.SetChannelId(ApplicationConstants.ChannelId)
~~~
Docs: https://developer.android.com/reference/android/support/v4/app/NotificationCompat.Builder
Here is a shot solution.
NotificationChannel chan = new NotificationChannel( "my_service_urgent", "My Channel", NotificationImportance.None );
chan.EnableVibration( false );
chan.LockscreenVisibility = NotificationVisibility.Secret;
NotificationManager notificationManager = GetSystemService( NotificationService ) as NotificationManager;
notificationManager.CreateNotificationChannel( chan );
var notification = new Notification.Builder( this, "my_service_urgent" )
.SetContentTitle( Resources.GetString( Resource.String.app_name ) )
.SetContentText( Resources.GetString( Resource.String.notification_text ) )
.SetSmallIcon( Resource.Drawable.ic_stat_name )
.SetContentIntent( BuildIntentToShowMainActivity() )
.SetOngoing( true )
.AddAction( BuildRestartTimerAction() )
.AddAction( BuildStopServiceAction() )
.Build();
// SERVICE_RUNNING_NOTIFICATION_ID = 101
// Enlist this instance of the service as a foreground service
StartForeground( Constants.SERVICE_RUNNING_NOTIFICATION_ID, notification );
In my case it was the missing of .SetSmallIcon(Resource.Drawable.icon)
After adding this line to Notification.Builder() it worked.
Strangely I did not face the problem in Debug builds but only in Release builds.
In summary I'm using Firebase Messaging Service and I'm trying to get my messages to show when the app is closed/killed. The weird problem is this sort of works. If I close the application and press send in the Azure Messaging Portal I'll get a notification as you should, however, that is the only notification I'll receive until I open the app and close it again and then I can receive one more. If the app is open I can spam send and I'll get all of the Notifications.
[Service]
[IntentFilter(new[] { "com.google.firebase.MESSAGING_EVENT" })]
[IntentFilter(new string[] { "com.google.android.c2dm.intent.RECEIVE" },
Categories = new string[] { "PACKAGEIDENTIFIER" })]
public class MyFirebaseMessagingService : FirebaseMessagingService
{
const string TAG = "MyFirstBaseMessagingService";
private int Notification_ID = 2;
public override void OnMessageReceived(RemoteMessage message)
{
Log.Debug(TAG, "From: " + message.From);
if (message.GetNotification() != null)
{
Log.Debug(TAG, "Notification Message Body: " + message.GetNotification().Body);
SendNotification(message.Data);
}
else
{
SendNotification(message.Data);
}
}
void SendNotification(IDictionary<string,string> message)
{
Drawable drawable = ContextCompat.GetDrawable(this, Resource.Drawable.lsbu);
Bitmap bitmap = ((BitmapDrawable)drawable).Bitmap;
string title = message["title"];
string body = message["body"];
NotificationManager notificationManager = GetSystemService(NotificationService) as NotificationManager;
string ChannelID = GetString(Resource.String.LocalChannelID);
string AppName = GetString(Resource.String.AppName);
NotificationImportance Importance = NotificationImportance.Default;
NotificationChannel mChannel = new NotificationChannel(ChannelID, AppName, Importance);
notificationManager.CreateNotificationChannel(mChannel);
Notification.Builder builder = new Notification.Builder(this, ChannelID)
.SetWhen(DateTime.Now.Second)
.SetSmallIcon(Resource.Drawable.miniwozzad)
.SetLargeIcon(bitmap)
.SetContentTitle(title)
.SetContentText(body)
.SetChannelId(ChannelID);
var notification = builder.Build();
notificationManager.Notify(Notification_ID, notification);
Notification_ID++;
}
}
This being my payload in the Azure Test Portal
{"data":{"body": "Another big message", "test": 1, "title": "A Big Title2" }}
This is my FirebaseMessagingService class, I'm not sure what I'm missing here. Any help would be appreciated!
I am sending push notification message from Firebase console to my app running on emulator.
The MyFirebaseMessagingService class looks like this:
public class MyFirebaseMessagingService extends FirebaseMessagingService {
private static final String TAG = MyFirebaseMessagingService.class.getSimpleName();
#Override
public void onMessageReceived(RemoteMessage remoteMessage) {
Log.d(TAG, "From: " + remoteMessage.getFrom());
if(remoteMessage.getData().size() > 0) {
Log.d(TAG, "Message data payload: " + remoteMessage.getData());
}
if(remoteMessage.getNotification() != null) {
Log.d(TAG, "Message Notification Body: " + remoteMessage.getNotification().getBody());
}
Intent intent = new Intent(this, SplashActivity.class);
intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_ONE_SHOT);
NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, "my_channel_01");
notificationBuilder.setContentTitle("FCM Notification");
notificationBuilder.setContentText(remoteMessage.getNotification().getBody());
notificationBuilder.setAutoCancel(true);
notificationBuilder.setSmallIcon(R.mipmap.ic_launcher_round);
notificationBuilder.setContentIntent(pendingIntent);
notificationBuilder.setChannelId("my_channel_01");
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
notificationManager.notify(0, notificationBuilder.build());
}
}
The constructor for NotificationCompat.Builder for API 26 now takes two params one is Context and another is String channelId. So I just assigned a random string to my channel.
But when I send the message from the firebase console the app on emulator gives me an error TOAST saying:
Failed to post notification on channel "my_channel_01"
What am I doing wrong?
When your build specifies a targetSdkVersion of 26, and you run on an API level 26 device or emulator, you must both specify a channel ID when constructing NotificationCompat.Builder, and also create the channel.
You could use a method like this:
public static final String NOTIF_CHANNEL_ID = "my_channel_01";
...
#RequiresApi(Build.VERSION_CODES.O)
private void createNotifChannel(Context context) {
NotificationChannel channel = new NotificationChannel(NOTIF_CHANNEL_ID,
"MyApp events", NotificationManager.IMPORTANCE_LOW);
// Configure the notification channel
channel.setDescription("MyApp event controls");
channel.setShowBadge(false);
channel.setLockscreenVisibility(Notification.VISIBILITY_PUBLIC);
NotificationManager manager = context.getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
Log.d(TAG, "createNotifChannel: created=" + NOTIF_CHANNEL_ID);
}
And because it is only needed for API 26 and requires that level, invoke it like this:
// The channel need only be created for API 26 devices. For devices
// running an API less the 26, there is no way to create a channel and the
// channel ID specified in the constuctor to NotificationCompat.Builder is
// merely a placeholder.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
createNotifChannel(this);
}
It does no harm to recreate the NotificationChannel, which provides some flexibility in where you do it. If your app has multiple entry points (activity, broadcast receiver, etc) take care to ensure the channel is created for all cases. You can also ensure it is only created once using NotificationManager.getNotificationChannel():
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
if (manager.getNotificationChannel(NOTIF_CHANNEL_ID) == null) {
createNotifChannel(this);
}
}