My app contain lock screen which will be come up when app brought from background.
I am facing a problem particularly onwards kitkat 4.4.
While app goes in background, i am checking that the Is application going in background? in onPause() method of activity which was on foreground by following code.
private boolean isApplicationBroughtToBackground()
{
ActivityManager am = (ActivityManager)getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(getPackageName())) {
return true;
}
}
return false;
}
I am calling above method in onPause() and on basis of returning value i am taking decision to show lock screen.
As per my observation this method is returning true in below 4.4 OS, but its returned false onword 4.4.
If i make a call in onStop() method i am getting true in all the cases.
I want to know whats the changes made in kitkat in context of activity life cycle?
Need to know reason why its behaving differently in kitkat?
Related
I have an app which has a single activity which has a checkbox the starts and stops a foreground service. The activity also has some other settings which control that service.
The problem is that after some time navigating other apps the service continues to run fine but the activity gets killed. If I restart the activity the checkbox will be set to default, off. If I switch it to on, a second service starts, while the first one is still running and can't be controlled anymore.
I can't figure out how to handle this situation. It's necessary for the service to run indefinitely and there doesn't seem to be anyway to keep the activity from dying. Maybe there's a way for the new activity to find the old service?
Try to kill the service in OnPause() method of your activity .that solve my problem few times ago.
To check if particular service is running, write the below method your activity, and call it when you want to check the state of the service
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
"service continues to run fine but the activity gets killed"
services are given more importance than activities, if android where given a choice to kill an activity or a service it always kill an activity first.
"a second service starts"
services can only be started once no matter how many times you start a service.
"checkbox will be set to default"
use sharedpreferences to persist values.
I have a Foreground Service for my app, which must run the whole time and never stops. While I was testing it few times, it seems after 3-4 days Android decides it just to stop it, and never restart it again, and in my Activity I have a check for the service if its running, and if it isnt to start it.
Even though, the service is not starting, and I can't debug it, because this is not happening immidiatelly.
So this is my check, is there something wrong in it?
if (!isMyServiceRunning(MyService.class)) {
startService(new Intent(this, MyService.class));
}
private boolean isMyServiceRunning(Class<?> serviceClass) {
ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE);
for (RunningServiceInfo service : manager.getRunningServices(Integer.MAX_VALUE)) {
if (serviceClass.getName().equals(service.service.getClassName())) {
return true;
}
}
return false;
}
I call this check in onResume() of the Activity, and I can't just run it everytime when the activity starts, because I have a constantly running Thread in the service, which will get more than one instance if started several times...
So here is what I want:
Either have more reliable way to check for the service if its running
or
Just start the service every time the activity starts, to prevent problems, and the thread inside of it must always have just 1 instance (I have already declared is as static)
You can make your service Bindable and bind your Activity to the service when the Activity starts/resumes. This way you will be sure the service is running. But I think you have a problem with your service. My I ask you to post more information about the service? It is not normal the OS to kill a foreground service with no traces.
I searched a lot in the net about it, the solutions are based on onPause and onDestroy. I want to give a library to a developer who just needs to paste a few lines of code from the library in his app which will enable the developer to create a service and destroy it when his entire app is in the background.
Does the Android OS send some kind of signals or intents when the app or the activity is changed (other than onPause or onStop method), so that i can catch that in a broadcast receiver from my library and do some actions.
If you know the package name of your app, try this (put this following snippet in the onCreate method of your app):
ActivityManager am= (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
Then,
boolean exit = false;
while(!exit)
{
List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if(!componentInfo.getPackageName().equals("Your package name"))
{
//Do your work here
exit = true;
}
}
When you start your app, this will be put into componentInfo. The taskInfo.get(0).topActivity will return the activity in the foreground. Hence you can know that your app has gone to the background by comparing package using the second code snippet.
Note:Put this second code snippet in an Asynctask so that the checking of whether the app has started can be done in the background.
From within the code of a particular service I want to determine if the service is in the foreground. I looked at:
ActivityManager.RunningServiceInfo
specifically RunningServiceInfo.foreground, but the documentation says, "Set to true if the service has asked to run as a foreground process."
So can I rely on RunningServiceInfo.foreground? Or is there another way?
PS: I'm not having other issues, my service is running fine. This question is more out of curiosity. Already browsed ASOP and didn't see anything, but maybe I missed something...
If you have a similar question, this may help:
How to determine if an Android Service is running in the foreground?
...Though I found the accepted solution to be incomplete.
The only thing I can think of is checking whether the service's process importance indicates that it's running a foreground service or the foreground activity:
private boolean isForegroundOrForegroundService() {
//Equivalent of RunningAppProcessInfo.IMPORTANCE_FOREGROUND_SERVICE on API 23
//On prior versions to API 23, maybe the OS just uses 100 as foreground service importance?
int IMPORTANCE_FOREGROUND_SERVICE = 125;
return findThisProcess().importance <= IMPORTANCE_FOREGROUND_SERVICE;
}
private ActivityManager.RunningAppProcessInfo findThisProcess() {
List<ActivityManager.RunningAppProcessInfo> runningAppProcesses = activityManager.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo proc : runningAppProcesses)
if (proc.pid == Process.myPid())
return proc;
throw new RuntimeException("Couldn't find this process");
}
For this to work, there are a few constraints:
The service must be the only service in the process that tries to run in the foreground since otherwise you won't know which service caused the process to enter foreground mode.
There mustn't be any activities that run in the same process since having an activity open also causes the process to enter foreground mode.
Nothing else must be able to make the process enter foreground mode other than the service itself for the same reasons as above.
So you'll probably want to put the service in its own dedicated process. Unfortunately, this makes your app structure difficult since multi-process app development is a lot more complicated than single-process.
Note that this is mostly just theory; I haven't tested this much or used it in any real-world applications. Let me know how it goes if you pursue this approach.
Try this code:
private boolean isActivityRunning() {
List<ActivityManager.RunningTaskInfo> tasks = activityManager.getRunningTasks(1);
ComponentName runningActivity = tasks.get(0).topActivity;
return runningActivity.getPackageName().startsWith("com.mypackage");
}
if I understood your question correctly and if we assume that foreground means that your application has some activity, you could declare global static variable in your application, e.g. boolean bIsForeground.
On you activity you can set:
#Override
protected void onResume() {
super.onResume();
bIsForeground = true;
}
#Override
protected void onPause() {
super.onResume();
bIsForeground = false;
}
so every time your activity is foreground or "on screen" this variable should be true and this way your service can know is foreground active.
In my application I need to detect whether my application is going to background or is switching to another activity of the same application... I know that I have to use the onPause method... but how can I distinguish the two cases?
private static boolean isApplicationGoingToBackground(final Context context) {
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> tasks = am.getRunningTasks(1);
if (!tasks.isEmpty()) {
ComponentName topActivity = tasks.get(0).topActivity;
if (!topActivity.getPackageName().equals(context.getPackageName())) {
return true;
}
}
return false;
}
UPDATE: getRunningTasks has been declared to not be guaranteed to be accurate.
Call in onStop. onStop gets called after onStart of whatever takes over the screen - if its an activity in the same apk package then you're not going into the background. This does require the GET_TASKS permission.
Or bind to a service onStart & unbind onStop - the service will then be onDestroyed when all your activities are stopped (or track binds vs unbinds if you don't want to rely on onDestroyed getting called - because it might not..).
There is no direct approach to get the app status while background or foreground, but even i have faced this issue, and found the solution with onWindowFocusChanged and onStop. For more details: http://vardhan-justlikethat.blogspot.in/2013/05/android-solution-to-detect-when-android.html