I have written and published an app ("Sensor Recording") in the Google Play Store. It's about reading sensor data (such as position, accelerometer, gyroscopes, etc.), displaying them numerically or graphically and storing them into kml and csv files for further processing, e.g with Google Earth or MS Excel. I have established a service to read and process the data in the background even when the screen is switched OFF.
Everything was working fine until Android 8. But in Oreo, the service is stopped automatically by the operating system, approx. 5 minutes after the screen is switched OFF. This has been introduced by Google intentionally to save battery lifetime. I have found some measures in the internet which should avoid that, but nothing worked so far.
What I have done:
1.) in the calling activity I have replaced startService() with startForegroundService()
2.) in the service itself I have made some modifications in onStartCommand() according to the hints I have found.
Tests with wakeLock also led to nothing. Any further ideas are appreciated.
private NotificationManager notMan;
#Override
public int onStartCommand(Intent intent, int flags, int startId)
{
// show notification + startForeground
int id = 42;
String channelId = "42";
String text = "Sensors active";
Intent notificationIntent = new Intent(this, SensorService.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
Notification notification;
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O)
{
NotificationChannel channel = new NotificationChannel(channelId,
getString(R.string.app_name),
NotificationManager.IMPORTANCE_DEFAULT);
notMan = getSystemService(NotificationManager.class);
notMan.createNotificationChannel(channel);
Notification.Builder builder = new Notification.Builder(this, channelId);
builder.setSmallIcon(R.drawable.vector3d_bg_transp)
.setContentTitle("Sensor Service")
.setContentText(text)
.setTicker(text)
.setSubText("Start Service")
.setShowWhen(true);
notification = builder.build();
}
else
{
notMan = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
notification = new NotificationCompat.Builder(this)
.setSmallIcon(R.drawable.vector3d_bg_transp)
.setContentTitle("Sensor Service")
.setContentText(text)
.setTicker(text)
.setSubText("Start Service")
.setPriority(PRIORITY_DEFAULT)
.setShowWhen(true).build();
}
startForeground(id, notification);
return super.onStartCommand(intent, flags, startId); // = 1, same as START_STICKY
} // onStartCommand
Recently, I found the solution – after an essential hint by Thomas Künneth (author of various Android books). The remedy is not in the source code, but in the settings of the smartphone. There is an option to enable background processing. On my Huawei P10 Lite with Android 8.0 it is located in the following menu tree (probably other devices or android versions have similar options):
Settings
Battery
Launch
Select the app in question.
Set the switch from “Manage automatically” to “Manage manually”.
In the pop-up menu set the switch “Run in background”.
That’s it, quite easy – if you know how.
It is remarkable, that Google offers this option, but does not highlight it in lectures about Android 8. Of course, this is consistent with the new policy “Battery first”.
Related
I have an notification that works fine yesterday, the notification not appears and I don't remember I had touched the code..
that notification must be appears when I get the desired value and must open a pop up dialog we user touch it.
can anyone help please?
the notification code - in side service-:
Intent notifyIntent = new Intent(context.getApplicationContext(), PopUp.class);
notifyIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//how I tried to pass data
notifyIntent.putExtra("text1", text1);
notifyIntent.putExtra("text2", text2);
PendingIntent pIntent = PendingIntent.getActivity(context, 1, notifyIntent, 0);
// build notification
// the addAction re-use the same intent to keep the example short
Notification n = new NotificationCompat.Builder(context,CHANNEL_ID2)
.setContentTitle("check this")
.setSmallIcon(R.drawable.ic_delete)
.setContentIntent(pIntent)
.build();
NotificationManager notificationManager =(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(0, n);
I'm using android studio emulator API 30
in the same service class I have a Notification and it is appearing to indicate that the service is working in the background, except the Notification that I but its code above it is not working suddenly
I don't know what is the problem, please help
When Issuing the notification with notify the notificationId must be a unique int for each notification. Update your code to include a random unique notificationId
see below
//you can use the timestamp
int notificationId = Integer.parseInt(String.valueOf(System.currentTimeMillis()));
NotificationManager notificationManager =(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
// notificationId is a unique int for each notification that you must define
notificationManager.notify(notificationId, n);
Android Create a Notification
I want to turn On notification Access for my android app programitically.
In some android devices, Notification Access for my app is turned off by default. I want to turn On and turn Off the notification access for my app dynamically in the app itself.
But I don't have any idea on how to enable the service.
Please, provide me your views.
I don't think that this is possible. There are restrictions for android applications which you can pass only with root.
Use that kind of metod on your Activity
public void sendNotification() {
NotificationCompat.Builder builder = new NotificationCompat.Builder(getActivity());
builder.setSmallIcon(android.R.drawable.ic_dialog_alert);
Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.journaldev.com/"));
PendingIntent pendingIntent = PendingIntent.getActivity(getActivity(), 0, intent, 0);
builder.setContentIntent(pendingIntent);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setContentTitle("Notification title");
builder.setContentText("Your notification message.");
builder.setSubText("link for more info.");
NotificationManager notificationManager = (NotificationManager) getActivity().getSystemService(NOTIFICATION_SERVICE);
notificationManager.notify(1, builder.build());
}
public void cancelNotification() {
String ns = NOTIFICATION_SERVICE;
NotificationManager nMgr = (NotificationManager) getActivity().getApplicationContext().getSystemService(ns);
nMgr.cancel(1);
}
You can prompt user to set those permissions for proper functioning. Setting those within app sounds malicious. I highly doubt such thing is possible. (Why would google create permission in first place if they can be overridden by app?)
I've been struggling with this for 2 weeks now.
I'm developing an app that controls call duration.
I receive a braodcast where I start a foreground service to hang up the call.
but after five minutes or more android force stop my package then kills my process which cause the service to crash -I think - (don't know why) with no crash message or any kind of error.
it just disappear.
And it Schedules restart but it never start the service again.
here is the logcat
12-29 00:28:52.857 619-619/? I/ActivityManager: Force stopping package club.androidy.callcontrolfree appid=10006 user=0
12-29 00:28:52.858 619-619/? I/ActivityManager: Killing proc 433:club.androidy.callcontrolfree/u0a10006: force stop club.androidy.callcontrolfree
12-29 00:28:52.894 619-619/? W/ActivityManager: Scheduling restart of crashed service club.androidy.callcontrolfree/.PhoneCallService in 5000ms
12-29 00:28:52.919 619-619/? I/ActivityManager: Force stopping service ServiceRecord{422b1b18 u0 club.androidy.callcontrolfree/.PhoneCallService}
using adb shell dumpsys I got this which insures that my service is a foreground service with the right priority
*APP* UID 10088 ProcessRecord{41aefb98 27922:club.androidy.callcontrolfree/u0a10088}
user #0 uid=10088
class=club.androidy.callcontrolfree.AnalyticsApplication
dir=/data/app/club.androidy.callcontrolfree-1.apk publicDir=/data/app/club.androidy.callcontrolfree-1.apk data=/data/data/club.androidy.callcontrolfree
packageList=[club.androidy.callcontrolfree]
compat={240dpi}
thread=android.app.ApplicationThreadProxy#41cef800
pid=27922 starting=false lastPss=0
lastActivityTime=-11s768ms lruWeight=14097791 serviceb=false keeping=true hidden=false empty=true
oom: max=15 hidden=9 client=9 empty=15 curRaw=2 setRaw=2 nonStopping=2 cur=2 set=2
curSchedGroup=-1 setSchedGroup=-1 systemNoUi=false trimMemoryLevel=0
adjSeq=63108 lruSeq=10968
setIsForeground=false foregroundServices=true forcingToForeground=null
lastRequestedGc=-12s74ms lastLowMemory=-12s74ms reportLowMemory=false
Services:
- ServiceRecord{41fb2578 u0 club.androidy.callcontrolfree/.PhoneCallService}
and in Process LRU list (sorted by oom_adj): section
Proc #24: adj=prcp /FS trm= 0 27922:club.androidy.callcontrolfree/u0a10088 (fg-service)
I'm not binding my service to any activities
I start my service like this:
Intent srvIntent = new Intent(context, PhoneCallService.class);
context.stopService(srvIntent);
PhoneCallService.stopService = false;
context.startService(srvIntent);
and this is my onStartCommand :
#Override
public int onStartCommand(Intent intent, int flags, int startId) {
Context context = getApplicationContext();
String txtNotificationTicker = context.getString(R.string.strNotificationTicker);
String txtNotificationTitle = context.getString(R.string.strNotificationContexTitle);
String txtNotificationText = context.getString(R.string.strNotificationContexText);
String ns = Context.NOTIFICATION_SERVICE;
Intent cancelIntent = new Intent(this, StopServiceReceiver.class);
PendingIntent pendingIntentCancel = PendingIntent.getBroadcast(this, 0, cancelIntent
, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Action action =
new NotificationCompat.Action
.Builder(R.drawable.ic_cancel
, context.getString(R.string.stop_service), pendingIntentCancel)
.build();
Intent mIntent = new Intent(this,MainActivity.class);
int HELLO_ID = 1;
PendingIntent pendingIntent = PendingIntent.getActivity(this, HELLO_ID, mIntent , 0);
this.mNotificationManager = (NotificationManager) getSystemService(ns);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context);
Notification notification = builder
.setContentIntent(pendingIntent)
.setContentTitle(new StringBuilder(String.valueOf(txtNotificationTitle)))
.setSmallIcon(R.drawable.ic_launcher)
.setLargeIcon(getBitmap(context, R.drawable.ic_launcher))
.setContentText(new StringBuilder(String.valueOf(txtNotificationText))
.append(": ").append(PHONE_NUMBER).toString())
.setWhen(System.currentTimeMillis())
.setPriority(NotificationCompat.PRIORITY_MAX)
.addAction(action)
.build();
notification.flags |= Notification.FLAG_NO_CLEAR;
startForeground(1, notification);
this.pt = new PhoneThread();
this.pt.start();
return Service.START_STICKY;
}
I'm acquiring wake lock like this
if (PhoneCallService.sCpuWakeLock == null) {
PhoneCallService.sCpuWakeLock = ((PowerManager)
context.getSystemService(Context.POWER_SERVICE))
.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,"CCF");
PhoneCallService.sCpuWakeLock.acquire();
Log.e("androidy","wacklock acquired");
}
I have already tried many solutions from SO and google issues but nothing works for me.
I saw and tried all these :
Foreground service killed by OS
Foreground service gets killed every time
Android foreground service being killed under certain conditions
Foreground Service being killed on Notification click
Foreground service being killed by Android
Users who keep the app are only 30% from total installs.
What I'm doing wrong?
Edit:
If you have the same issue please check Power Saving Options in your phone settings if your phone has this feature it will kill your app after the screen is off and will not allow it to work in background.
Original answer:
After a lot of search I solved it myself
it turned out that my app was power-intensive as shown in the picture below
Hence, android was force stopping it after 5 minutes when there is no activity on the screen to save power.
I solved power consumption issues and everything became OK.
I have looked at all the other AUTO-CANCEL-not-working questions here, and they all seem to involve mistakes that I am not making. I have tried both
builder.setAutoCancel(true);
and
Notification notif = builder.build();
notif.flags |= Notification.FLAG_AUTO_CANCEL;
Neither works.
I am using NotificationCompat since my minimum API is 8. Here is my full code. In this particular notification, I am not calling an intent, since I don't need the user to do anything.
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setContentTitle(getString(R.string.app_name) + ": my title");
builder.setContentText(message);
builder.setSmallIcon(R.drawable.notification_icon);
Bitmap bitmap = BitmapFactory.decodeResource(getResources(), R.drawable.prog_icon);
builder.setLargeIcon(bitmap);
builder.setAutoCancel(true); // dismiss notification on user click
NotificationManager notiManager = (NotificationManager)getSystemService(NOTIFICATION_SERVICE);
notiManager.notify(MY_NOTI_MANAGER_ID, builder.build());
The notification displays just perfectly. You can swipe to clear it. But simply tapping it does not dismiss the notification. It just lights up and stay there.
Some possible differences between my code and others' posted here:
1) I am using NotificationCompat (which should not make a difference, but we've heard that before).
2) Since my notification is simple, I do not attach an intent.
Please let me know if you have any insights.
Edit: My purpose is to dismiss a notification without foregrounding my background app.
So apparently you do need a pending intent.
At Android - notification manager, having a notification without an intent, I found a solution that grabs the current active application as your pending intent (so that you don't have to start your own activity in order to dismiss the notification).
I just added the following two lines of code (right after setting the auto-cancel):
PendingIntent notifyPIntent =
PendingIntent.getActivity(getApplicationContext(), 0, new Intent(), 0);
builder.setContentIntent(notifyPIntent);
It worked great. I would say that if you don't want your activity to restart as a result of the user clicking your notification, then this is your best option.
You appear to be missing the PendingIntent and setContentIntent() call. I believe that is required for auto-cancel to work.
Here is some Notification-displaying logic from this sample project that works:
private void raiseNotification(Intent inbound, File output, Exception e) {
NotificationCompat.Builder b=new NotificationCompat.Builder(this);
b.setAutoCancel(true).setDefaults(Notification.DEFAULT_ALL)
.setWhen(System.currentTimeMillis());
if (e == null) {
b.setContentTitle(getString(R.string.download_complete))
.setContentText(getString(R.string.fun))
.setSmallIcon(android.R.drawable.stat_sys_download_done)
.setTicker(getString(R.string.download_complete));
Intent outbound=new Intent(Intent.ACTION_VIEW);
outbound.setDataAndType(Uri.fromFile(output), inbound.getType());
b.setContentIntent(PendingIntent.getActivity(this, 0, outbound, 0));
}
else {
b.setContentTitle(getString(R.string.exception))
.setContentText(e.getMessage())
.setSmallIcon(android.R.drawable.stat_notify_error)
.setTicker(getString(R.string.exception));
}
NotificationManager mgr=
(NotificationManager)getSystemService(NOTIFICATION_SERVICE);
mgr.notify(NOTIFY_ID, b.build());
}
Hai dear friend if you want to show non cancelable
notification(not cancelable for users) for a particular
time and after that you need clear it (like the music player) you can use this.
mNotificationBuilder .setSmallIcon(android.R.drawable.btn_plus);
mNotificationBuilder .setContentTitle("My notification");
mNotificationBuilder .setContentText("Notificattion From service");
mNotificationBuilder .setLights(0xFF0000FF, 500, 500);
Notification note = mNotificationBuilder.build();
note.flags = Notification.FLAG_ONGOING_EVENT; // For Non cancellable notification
mNotificationManager.notify(NOTIFICATION_ID, note);
I've got a service that scrapes a website for data then if necessary gives the user a notification.
The problem I'm having is that the notifications disappear as soon as the service closes (which could be instantly). The below code is all of the notification code the app has. I haven't put in any code to cancel the notifications.
public static void CreateNotificationCompat(int notificationID, String link, String title, String text, Context ctx)
{
Intent notificationIntent = new Intent("android.intent.action.VIEW", Uri.parse(link));
PendingIntent contentIntent = PendingIntent.getActivity(ctx.getApplicationContext(), 0, notificationIntent, 0);
NotificationManager nm = (NotificationManager) ctx
.getSystemService(Context.NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(ctx);
Resources res = ctx.getResources();
builder.setContentIntent(contentIntent)
.setSmallIcon(R.drawable.notify_icon)
.setWhen(System.currentTimeMillis())
.setContentTitle(title)
.setContentText(text)
.setAutoCancel(false);
Notification n = builder.getNotification();
nm.notify(notificationID, n);
}
If it makes any difference (pretty sure it doesn't) i'm using the application context here.
My services is started periodically, processes a website, notifies if needed and then closes.
At the end of my service instead of just calling stopSelf() i sleep for 30 or so seconds and then call stopSelf(). Then the notification stays for 30 seconds and then disappears. Nothing relevant appears in logcat at the time the notifications disappear.
I've only been able to test using ICS so far.
The code you have posted works. I tested it from both an activity and a service on jb, and the notification stays when the components are stopped. I even verified that I could kill the process and the notification stays. Try to strip down the app and see if the problem persists. Specifically check to see that you don't call cancel on the notification by mistake.
You seem to forgot check developer manual first. See here http://developer.android.com/guide/topics/ui/notifiers/notifications.html and look for FLAG_ONGOING_EVENT and FLAG_NO_CLEAR flags.
I've only been able to test using ICS so far.
That's why simulators are quite useful. Try it. It's part of SDK.
Please try the old way on the same device and tell us if it behaves the same way:
private static void CreateNotificationCompat(int notificationID, String link, String title, String text, Context ctx) {
String ns = Context.NOTIFICATION_SERVICE;
NotificationManager mNotificationManager = (NotificationManager) ctx.getSystemService(ns);
Notification notification = new Notification(R.drawable.notify_icon, title, System.currentTimeMillis());
notification.flags = Notification.FLAG_AUTO_CANCEL;
PendingIntent contentIntent;
Bundle bundle = new Bundle();
Intent notificationIntent = new Intent("android.intent.action.VIEW", Uri.parse(link));
contentIntent = PendingIntent.getActivity(ctx, notificationID,
notificationIntent, 0);
notification.setLatestEventInfo(ctx, title, text,
contentIntent);
mNotificationManager.notify(notificationID, notification);
}
Just aa note this behaviour occurs when startForeground() is used and then stopSelf() is called.