There are lots of reasons why detecting if application is on foreground.
for example - as a trigger to GCM/C2DM push notification - lot's of apps would have good reason implementing different behavior when app is foreground and background.
Other reason could be - shotting down services consuming precious resources, such as querying servers in background task for instance.
Just to be clear: the definition (as I see it) for background app is:
application which none of it activities are invoked the onStart() method, and did not invoke yet the onStop() method.
that's because activity is visible to the user in it life cycle only at that time.
From the other hand -
seems like Google don't want application to react to the home button (it's not part of the API)
reacting to the onBackPressed() on the "root / main" activity as indicator for leaving Activity certainly not good idea (because lots of users using the home button, and not the back button)
there is no method in the API allowing determine if app is foreground (according to my definition..)
if I didn't miss something in the API, and it's really the case - Why there is no why to determine easily if the application is foreground or not????!!!!
what I know I can do to determine if the application is foreground is described in this thread - How to detect when an Android app goes to the background and come back to the foreground
but as #Emil saying - it's requiring special permission, or requiring some tricky logic's which very fast becoming problematic to maintain, and it smells like bad approach (although that's what I'm doing for now, because I don't have better idea...)
my questions basically are:
Is there no such API method from good reason?
Is taking into account if application is foreground or not is a bad approach?
Is there any other way to know if application is foreground or not?
is taking into account if application is foreground or not is a bad approach?
Taking foreground versus background into account is reasonable.
is there any other way to know if application is foreground or not?
You can roughly divide the scenarios for this into two groups:
Cases where you want to take an action immediately upon a change in the foreground/background status
Cases where some other event occurs (AlarmManager alarm, incoming system broadcast, etc.), and at that point you want to take different actions based upon whether or not you are in the foreground
In the former case, onUserLeaveHint() is your most reliable simple option. I cannot guarantee that it will cover all cases, but it should handle the HOME scenario, for example. You are also welcome to maintain a reference count of started activities in a static data member and try to use it instead.
In the latter case, an ordered broadcast can be useful.
With the new Android Architecture Components there is an easy way to know if your app is in the foreground or the background.
Just like with the activity scope lifecycle owner there is a general process lifecycle owner which you can subscribe to and get lifecycle updates.
For example:
Add this code in order to register as a lifecycle observer
ProcessLifecycleOwner.get().lifecycle.addObserver(lifecycleListener)
And this code in order to receive the relevant callbacks
#OnLifecycleEvent(Lifecycle.Event.ON_START)
public void onApplicationOnStartEvent() {
}
#OnLifecycleEvent(Lifecycle.Event.ON_STOP)
public void onApplicationOnStopEvent() {
}
Don't forget to remove the observer once you don't need it
ProcessLifecycleOwner.get().getLifecycle().removeObserver(lifecycleListener);
More information and examples can be found in this excellent article:
https://proandroiddev.com/detecting-when-an-android-app-backgrounds-in-2018-4b5a94977d5c
I had the same issue. I want to display push notification when my activity is not in foreground mode. Please go through following code and you will get your answer.
Context ctx = context.getApplicationContext();
ActivityManager am = (ActivityManager) context
.getSystemService(ACTIVITY_SERVICE);
// get the info from the currently running task
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
PackageManager pm = this.getPackageManager();
try {
/**
* take fore ground activity name
*/
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (printLog == true) {
Log.d("Home", "CURRENT Activity ::"
+ taskInfo.get(0).topActivity.getClassName());
Log.d("Home", "Number Of Activities : "
+ taskInfo.get(0).numRunning);
Log.d("Home",
"Componenet Info : " + componentInfo.getPackageName());
Log.d("Home",
"Componenet Info : " + componentInfo.getClassName());
}
/**
* All activities name of a package to compare with fore ground
* activity. if match found, no notification displayed.
*/
PackageInfo info = pm.getPackageInfo(
"<PackageName>",
PackageManager.GET_ACTIVITIES);
ActivityInfo[] list = info.activities;
for (int i = 0; i < list.length; i++) {
Log.d("TAG","Activity : "+list[i].name);
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
To use this, you have to take permission in your manifest file.
uses-permission android:name="android.permission.GET_TASKS"
Pardon me if I can't get your question.
If it is necessery for you to know if the app is on backround or foreground from a service that is running on the background(doesnt make sense otherwise), then you can just use binding, that is - bind to it on all your activities onResume, and unbind on all activities onPause. then in your service you can manage not only your application visibility to the user, but also which of the activities are open at any time. it is also leak-proof and more stable then a static variable (which can be cleaned up if necessery) as you are using android's API and relying on the correctness of the android OS code itself.
Related
I currently have two applications.
App A has a list of existing applications that you can click on and open. Including which is App B. Now I want to only run App B for a set amount of time ~30 minutes.
Is there a way to automatically close App B and reopen App A? I want to fully close App B. Kind of like when you press the soft button on your android and close out the app by swiping left/right.
I have tried using KillBAckgroundProcess and killProcess, but it does not fully simulate the "swiping left/right" of the app. I have looked at other issues on stack overflow, but none have the answer of how to do it this specific way.
Example Code:
//process
for (ActivityManager.RunningAppProcessInfo process : processes) {
if(process.processName.equals("com.example.adam2392.helloworld")) {
processToKill = process.processName;
processId = process.pid;
}
}
//packages
for (ApplicationInfo packageInfo : packages) {
if (packageInfo.packageName.equals("com.example.adam2392.helloworld")) {
packageToKill = packageInfo.packageName;
}
}
am.killBackgroundProcesses(packageToKill);
android.os.Process.killProcess(processId);
I believe what would work better for your situation is to set an alarm in App B's onStart() or onCreate() method that goes off after 30 minutes and runs whatever code you need it to run to kill processes and then terminate App B. I've never done this myself, but this link has a nice tutorial about using Alarms in Android to schedule an app to do something. For your situation, you most likely will want to use
AlarmManager.set(AlarmManager.ELAPSED_REALTIME_WAKEUP,
SystemClock.elapsedRealtime() + 60 * 1000, PendingIntent)
as the trigger for your alarm because there's probably no reason that App B has to begin its shutdown process at EXACTLY 30 min.
As far as closing the App, I believe this should work for you:
public void killApp() {
Intent goHomeIntent = new Intent(Intent.ACTION_MAIN);
goHomeIntent.addCategory(Intent.CATEGORY_HOME);
goHomeIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(goHomeIntent);
finish();
}
This may not force quite the app like you're wanting, but usually you want to just let Android terminate the app at its own discretion after it has been closed.
The title is bad, sorry. Could figure out how to say this in short.
So, I'm developing an application for Android which will only be used in my own couple tablets which are going to public use.
I need a service running in the background (or so I currently believe, prove me wrong if possible) which keeps track which application is foreground, and when that application goes to background the service starts activity which will go foreground and show something to the user(for example like some ad, or some review window which asks for start rating).
How could this be done?
Thank you.
E: The other applications can be 3rd party, so I can't modify the code of those.
When u start other activity at that time you current activity is OnPause() state and other activity goes onCreate() State.
You Must refer Activity LifeCycle for this.
You have to use Accessibility service. Starting from Android Lollipop you can't gather this kind of information. The only way is via accessibility docs.
to check other running tasks you should use ActivityManager.
ActivityManager acm = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
List<RunningTaskInfo> Ru_tasks = acm.getRunningTasks(NUMBER_OF_TASKS_U_WANT);
if (!Ru_tasks .isEmpty()) {
LOOP FOR EACH TASK (i is counter)
ComponentName topActivity = tasks.get(i).topActivity; // Or replace .topactivity with task name
if (topActivity.getPackageName().equals(WHAT_YOU LOOK FOR)) {
//Do WHAT YOU WANT!
}
}
get GET_TASKS permission
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.
I want to know what activity is being displayed in android device
if the activity that I will search I execute code
if not I execute another code
purpose is to make an android service to check this task
This should work for you:
Get active Application name in Android
Just tweak it with the functionality you want, and you should be able to check rather easily.
Are you sure that's what you want?
purpose is to make an android service to check this task
If you told us what was the reason behind your "purpose", I'm almost sure we could help you with a better way of doing what you want (probably we could find a way which would waste less battery and which would antagonize less your users).
In any case, here is the answer to your question:
Use getRunningTasks of ActivityManager to get a list of the recently launched activities.
public
List
getRunningTasks (int maxNum)
Return a list of the tasks that are
currently running, with the most
recent being first and older ones
after in order. Note that "running"
does not mean any of the task's code
is currently loaded or activity -- the
task may have been frozen by the
system, so that it can be restarted in
its previous state when next brought
to the foreground.
You might also want to use the flag RECENT_WITH_EXCLUDED to make sure you get all the activities, even the ones that purposefully exclude themselves from that list.
public static final int RECENT_WITH_EXCLUDED
Added in API level 1 Flag for use with getRecentTasks(int, int):
return all tasks, even those that have set their
FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS flag.
I found this code it works very well
Log.i("---------------", "----------onCreate--------------");
Log.i("-----test------", "----------1--------------");
ActivityManager am = (ActivityManager) this .getSystemService(ACTIVITY_SERVICE);
Log.i("-----test------", "----------2-------------");
List<RunningTaskInfo> taskInfo = am.getRunningTasks(1);
Log.i("-----test------", "---------3--------------");
ComponentName componentInfo = taskInfo.get(0).topActivity;
Log.i("-----test------", "----------4--------------");
Log.i("------------------", "CURRENT Activity ::" + taskInfo.get(0).topActivity.getClassName()+" Package Name : "+componentInfo.getPackageName());
Log.i("-----test------", "----------5--------------");
I got a service that start a new activity, while screen is off.
I want the activity to stay on paused mode, and not get to the stopped mode.
Is there a way to achieve this?
No. You don't have control over the Activity lifecycle. Any processes that you need to run while the screen is off must be executed in a Service. You must rebuild the application state whenever the screen is turned back on. Always assume the Activity can be wiped from memory at any time.
You can't do that. it will be killed anyway.
but you can use a Service to receive Broadcast of Intent.ACTION_SCREEN_ON and relaunch activity from Service.
to restart your Activity from service check here
There is no way to achieve this. Your app is tied to the Activity lifecycle, and has to break down/restore the Activities to work with the lifecycle.
You can't override the onDestroy() method, and each OS version handles how an application is "killed" differently.
The Android developer documentation makes reference to an application being in a “killable” state. While Android tries to keep the process of an application resident even after it has exited (i.e. after onDestroy), it does need to be able to kill these processes in low-resource situations to reclaim memory. The states in which an application is killable differ per OS version. On all versions of Android, applications that have returned from onStop or onDestroy are silently killable. On versions of Android prior to Honeycomb, applications that had returned from onPause were also killable. Being killable simple means that Android reserves the right to terminate your application’s process at any time without running even another instruction of your app’s code. In other words, if you have any state that must be recoverable (such as a player’s game progress, items, awards, etc) you must save those to persistent storage no later than the last callback before entering a killable state.
In addition, while applications can run native threads even when they are in a killable
state and even post-onDestroy, this is to be avoided, since the process kill will also kill those threads. This could cause all manner of corruption and shutdown issues.
Source
I do not exactly now what you mean with paused mode or stopped mode. If you mean that the cpu keep wake up take a look at this.
With partial_wake_look you can have a long running AsyncTask for example also when the screen is of. Dont't forget to release the wakelook.
Why do you need to do this? Maybe best solution is to run it as a service as suggested by #DeeV. However, depending of what you need to do, this could help:
Ask Android to notify you when screen is turned on (and off if required). So your activity can be resumed and started immediately and you can perform any action.
To do that:
Create a class which extends Application
Register it in your Manifest:
In public void onCreate() {..., add this:
IntentFilter ioff = new IntentFilter(Intent.ACTION_SCREEN_OFF);
IntentFilter ion = new IntentFilter(Intent.ACTION_SCREEN_ON);
broadcastReceiver = new BroadcastReceiver() {
#Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
if (Intent.ACTION_SCREEN_OFF.equals(action)) {
//TODO
} else {
//TODO
}
}
};
context.registerReceiver(broadcastReceiver, ioff);
context.registerReceiver(broadcastReceiver, ion);
in public void onTerminate() {..., add this:
if (broadcastReceiver != null) {
context.unregisterReceiver(broadcastReceiver);
}
Lame hack would be to call onPause() method inside onStop() of activity