notification.setOngoing(true) does not work in Android 8.1 - java

build.setOngoing(true);
build.setAutoCancel(false);
notification.flags= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
setOngoing is not working
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
/* Create or update. */
_notificationChannel = new NotificationChannel("TubeMateGo",
"Downlaod File Notification",
NotificationManager.IMPORTANCE_DEFAULT);
mNotifyManager.createNotificationChannel(_notificationChannel);
build = new NotificationCompat.Builder(getBaseContext(),_notificationChannel.getId());
build.setContentTitle("Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_launcher_foreground);
build.setOngoing(true);
build.setChannelId(_notificationChannel.getId());
build.setVisibility(Notification.VISIBILITY_PUBLIC);
build.setAutoCancel(false);
build.setContentIntent(_pedingIntent);
Notification notification = build.build();
notification.flags= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
mNotifyManager.notify(id, notification);
}
else {
build = new NotificationCompat.Builder(getBaseContext());
build.setContentTitle("Download")
.setContentText("Download in progress")
.setSmallIcon(R.drawable.ic_launcher_foreground);
build.setOngoing(true);
build.setVisibility(Notification.VISIBILITY_PUBLIC);
Notification notification = build.build();
notification.flags=Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
mNotifyManager.notify(id, notification);
}
When I try to remove notification from notification bar its removed why ?
i dont know where i am going wrong
According to Docs
public Notification.Builder setOngoing (boolean ongoing)
Set whether this is an "ongoing" notification. Ongoing notifications
cannot be dismissed by the user, so your application or service must
take care of canceling them. They are typically used to indicate a
background task that the user is actively engaged with (e.g., playing
music) or is pending in some way and therefore occupying the device
(e.g., a file download, sync operation, active network connection).
Then Why Its Dismissed By User?
EDIT 2
This Happens in Custom OS ? Like Vivo
Test - RedMI note 5 Pro - working fine
Then Why ? Not working with Vivo ?

In a few words, that's due to fragmentation and customization.
Probably that phone has some kind of setting to configure that behavior. As someone said one day: Some phones are just -trash-. Don't waste your time trying to fix an issue for every possible phone.

Related

How to create more than one foreground notification?

Below is a snippet of code in my service class.
If a user "joins a team" (operation = 0) then it create a notification with its designated specifications however if a user shares their location (operation = 1) then its supposed to create a separate foreground notification. Instead one just replaces the other.
I don't know why, they have different ID's just same channel. I've also tried separating their channel ID, still the same issue
int id = NOTIFICATION_LOCATION;
int icon = R.drawable.ic_gps_on;
String message = "Tap to disable location updates";
if (operation == 0) {
id = NOTIFICATION_RESPONDER;
icon = R.drawable.ic_responder_icon;
message = "Tap to leave the responding team";
}
Notification notification = new NotificationCompat.Builder(this, CHANNEL_ID_1)
.setSmallIcon(icon)
.setContentTitle("Location established")
.setContentText(message)
.setContentIntent(PendingIntent.getBroadcast(getApplicationContext(), 0, getBroadcastIntent(operation), PendingIntent.FLAG_UPDATE_CURRENT))
.setColor(ContextCompat.getColor(getApplicationContext(), R.color.primaryColor))
.setDefaults(Notification.DEFAULT_SOUND)
.setVisibility(VISIBILITY_PUBLIC)
.build();
startForeground(id, notification);
The notification you manipulate with startForeground() is meant to be the one "official" notification that corresponds to the foreground service; the one that Android insists you have up at all times the service is running.
It doesn't surprise me that, if you supply a different notification channel ID on a subsequent call to startForeground(), it erases and replaces the original notification. Otherwise, you might end up with multiple foreground notifications for a single service, and things could get confusing.
Instead, just use NotificationManager.notify() to manage any notifications that occur in excess of the original foreground service notification. Use distinct IDs for these extra notifications.
A good practice is to use a fixed ID for your foreground service notification. You can still change the Notification at will; it's just easier to remember which Notification is your "official" one, when you have a fixed ID.
You can also manipulate your "official foreground service notification" using notify(); you don't have to use startForeground(). A call to startForeground() is only needed once, at the beginning, to associate the service with a specific notification ID.

How to handle onNotificationReceived from Firebase every 10 minutes while app is in background. Android 9.0

I need to be able to send my GPS-location to a server every time I receive a silent-push notification from Firebase. The timer for sending a notification is currently set to every 10 minutes. When the phone is charging this is not a problem, but when it's idle and the application is in the background, the onMessageReceived from FirebaseMessagingService is only called every few hours. This leads me to believe it has something to do with the new power management rules for Android 9.0. But for my application to work I need to be able to send my location every 10 minutes. Not just sometimes.
I have tried to set the battery optimisation to 'not optimised' using Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
This does not seem to have any effect.
I also tried setting the priority of the Firebase notification to High. This works, but only for 10 messages per day, which means it's not a solution for my application. (Source: Power Management restrictions)
I am now trying to always have the application in the 'Active' bucket by opening a foregroundService. This should make sure the app is never in any other bucket, where the notifications can be deferred for a few hours.
An app is in the active bucket if the user is currently using the app, for example:
The app has launched an activity
The app is running a foreground service
The app has a sync adapter associated with a content provider used by a foreground app
The user clicks on a notification from the app
If an app is in the active bucket, the system does not place any restrictions on the app's jobs, alarms, or FCM messages.
(Source: Power Buckets Android9).
This does not seem like a solution I should want, though, since it might not be best practice. And it doesn't seem to work either anyways.
This is my onMessageReceived function:
#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());
Map<String, String> params = remoteMessage.getData();
JSONObject object = new JSONObject(params);
PushNotificationManager.getInstance().handlePushNotification(object, getApplicationContext());
}
}
Right now I am clueless as to why the Firebase messages do not enter the onMessageReceived function.
Tim,
I think that the main problem is with how you send the push notification and what is its content.
If you check here - https://firebase.google.com/docs/cloud-messaging/android/receive
you will see that if the message contains notification data and the app is at background then the push notification goes to the Notification area.
You need to send a push notification that contains only data:
(Here you can find more information about the different types - https://firebase.google.com/docs/cloud-messaging/concept-options#notifications_and_data_messages)
Here is what is the explanation how to trigger it-
In a trusted environment such as Cloud Functions or your app server, use the Admin SDK or the FCM Server Protocols: Set the data key only.
Please note that if you need to do a long running operation, then you will need to start a separate service (the service should present a notification in the notification area that it is running, otherwise you will get a crash on the newer Android versions)
Fixed by using AlarmManager. Schedule an alarm in 10 minutes, and when completing the code within the alarm, schedule a new alarm in 10 minutes.
AlarmManager can wake the phone if it is in doze mode, which means all code inside the trigger will be executed properly.

Launch screen from native background service

I have a simple Flutter app that start a native background service using MethodChannel. This native background service notify my Flutter app using BasicMessageChannel<String> to display text when a particular native information is catched. All of this work perfectly when my app is in foreground. When an other app is in foreground, I can't see the text without having to switch to my app.
I want that my native service can display a particular Flutter screen even if an other application is running in foreground.
It can be perceived as not user friendly, but this is an message of utmost importance.
Any suggestion or solution will be welcome !
Note : Native service is for the moment only available in Java for Android, I'm working on C# for IOS side.
On Android you need to display a high priority notification. This displays the slide-down notification panel which will appear over the lock screen or another app. Since you are using native code already, you can create this notification there, or send a message to the Dart side (as you are doing, using MethodChannel) where it can use the flutter_local_notifications plugin to display it. When the user click the notification, your flutter app is brought to the foreground. In Java you might use code similar to this:
// Create an intent which triggers the fullscreen notification
Intent intent = new Intent(Intent.ACTION_MAIN, null);
intent.setAction("SELECT_NOTIFICATION");
Class mainActivityClass = getMainActivityClass(context);
intent.setClass(context, mainActivityClass);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Build the notification as an ongoing high priority item to ensures it will show as
// a heads up notification which slides down over top of the current content.
final Notification.Builder builder = new Notification.Builder(context, CHANNEL_ID);
builder.setOngoing(true);
// Set notification content intent to take user to fullscreen UI if user taps on the
// notification body.
builder.setContentIntent(pendingIntent);
// Set full screen intent to trigger display of the fullscreen UI when the notification
// manager deems it appropriate.
builder.setFullScreenIntent(pendingIntent, true);
// Setup notification content.
int resourceId = context.getResources().getIdentifier("app_icon", "drawable", context.getPackageName());
builder.setSmallIcon(resourceId);
builder.setContentTitle("Your notification title");
builder.setContentText("Your notification content.");
MyPlugin.notificationManager().notify(someId, builder.build());
Then, for Android 8.1 or higher, add the following to your MainActivity class, found under the android/app/src/main/java/packageName/ folder
GeneratedPluginRegistrant.registerWith(this);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
setShowWhenLocked(true);
setTurnScreenOn(true);
}
(This shows the Flutter app even when the screen is locked.)
Flutter only has one activity, so the above code will bring that Flutter activity to the foreground (note that you don't always see the notification, but sometimes you do - if you set it to autoCancel then touching it clears it). It's up to you to build the correct screen in Flutter, which you can do as you send the notification. Use Navigator.push or equivalent to change the page that Flutter is showing.

Android Oreo background limit

I'm using Eclipse's Paho android library. This library internally starts a Service to fetch data. Now when my app is in background and push notification comes, Paho's service works well for pre-oreo devices. But on Oreo device, this work for few minutes duration after app goes to the background state. After this duration, although I'm sending high priority GCM message, service won't starts and gives warning in logcat Background start not allowed. As stated in offical docs, for high priority GCM messages, app becomes whitelisted for few minutes. In this case, it should work for high priority GCM message.
From my understanding app should become whitelisted whenever high priority GCM arrives. Is it correct?
To be ready for Android O:
1) Instead of IntentService; your service needs to extend JobIntentService.
2) Instead of onHandleIntent; you need to use onHandleWork.
3) Instead of startService; you need to use enqueueWork.
Check this out.
https://developer.android.com/reference/android/support/v4/app/JobIntentService.html
When dealing with broadcasts, you need to make sure the intent is explicit.
private static void sendImplicitBroadcast(Context ctxt, Intent i) {
PackageManager pm=ctxt.getPackageManager();
List<ResolveInfo> matches=pm.queryBroadcastReceivers(i, 0);
for (ResolveInfo resolveInfo : matches) {
Intent explicit=new Intent(i);
ComponentName cn=
new ComponentName(resolveInfo.activityInfo.applicationInfo.packageName,
resolveInfo.activityInfo.name);
explicit.setComponent(cn);
ctxt.sendBroadcast(explicit);
}
}
This was from https://commonsware.com/blog/2017/04/11/android-o-implicit-broadcast-ban.html

Android foreground service notification not persistent

I have created a class which extends Service and runs as a foreground service. I would like my service notification to be persistent (i.e. not removed by swiping). However, my notification can be dismissed by swiping.
The Service documentation states: ...A foreground service must provide a notification for the status bar, which is placed under the Ongoing heading. This means that the notification cannot be dismissed unless the service is either stopped or removed from the foreground...
I did put break points to check whether onDestroy() or stopSelf() is hit, but this is not the case. The service is running in foreground mode, but I can dismiss the notification by swiping.
I have found quite a few questions regarding the opposite case, where it was not possible to dismiss the notification after the service was stopped, but did not find any question similar to my problem.
The service is started via an Intent and initialized as follows:
#Override
public void onCreate()
{
super.onCreate();
initialize();
}
private void initialize()
{
Notification n = get_service_notification();
startForeground(10, n);
LocalBroadcastManager.getInstance(this).registerReceiver(mMessageReceiver, new IntentFilter(BroadcastCodes.service_broadcast_intent_name));
}
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
startServing();
return START_STICKY;
}
where startServing() subscribes to location updates
The notification is built like this
private Notification get_service_notification()
{
Intent intent = new Intent(this, LoginActivity.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder b = new NotificationCompat.Builder(this);
b.setAutoCancel(false)
.setWhen(System.currentTimeMillis())
.setSmallIcon(R.drawable.app_icon)
.setTicker("some text")
.setContentTitle("some text")
.setContentText("some text")
.setContentIntent(contentIntent)
.setContentInfo("")
.setOngoing(true);
Notification res = b.build();
res.flags |= Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;
return res;
}
I have tried playing around with the flags and setOngoing/setAutoCancel, but the result stayed the same.
SDK versions are configured as minSdkVersion 18, targetSdkVersion 25
I would really appreciate any input regarding this issue - it might be just some stupid mistake, but I already did spend more than a few hours trying to research on my own...unfortunately to no avail.
EDIT 1
I still have not figured out the problem. I decided to try a dirty hack, but still no luck.
I made a PendingIntent and registered it via setDeleteIntent() the idea being to display a new notification once this one was dismissed by swipe. Unfortunately, I was not able to get this to work (the intent never fires when swiping).
I would also like to clarify, that the notification CAN BE swiped away, but IS NOT AFFECTED (i.e. is not deleted) by the clear-all button in the notification pane (the trash icon).
EDIT 2
As mentioned above I was not able to use setDeleteIntent() to recreate my notification when it is dismissed by swipe.
For now I settled with a workaround - my service does some periodical tasks. I am now calling
notificationManager.notify(10, service_notification);
when my task runs so that even if swiped away, my notification will be recreated after a while.
I still have a strong feeling that I just misread the documentation, since there are several notifications on my test device (Honor API23) that can not be swiped away.
EDIT 3
I have tried the same code on a different device (Lenovo API23) and the notification works as expected (can not be dismissed and can not be swiped). My problem seems to be device specific.
I made a few further tests (besides the ones mentioned in updates). I tried running various examples/tutorials from around the internet like this page here
On the Honor I was initially running my tests the notification could always be swiped, on the Lenovo and others the "ongoing" flag works as stated in the documentation, i.e. it can not be dismissed via swipe action.
To sum it up, my problem really seems to be device specific.

Categories