I have a broadcast receiver, which launches a service, and in this service I should check, if my main application is active, or in background. Are there any methods how to do this?
You can extend the Application class and store the current state of your application. You will need to update it from every Activity's onPause() and onResume() methods.
public class MyApplication extends Application {
public static boolean isAppVisible() {
return visible;
}
public static void inForeground() {
visible = true;
}
public static void inBackground() {
visible = false;
}
private static boolean visible;
}
Register your application class in AndroidManifest.xml:
<application
android:name="your.app.package.MyApplication"
android:icon="#drawable/icon"
android:label="#string/app_name" >
Add onPause and onResume to every Activity in the project (you may create a common superclass for your Activities if you'd like to, but if your activity is already extended from MapActivity/ListActivity etc. you still need to write the following by hand):
#Override
protected void onResume() {
super.onResume();
MyApplication.inBackground();
}
#Override
protected void onPause() {
super.onPause();
MyApplication.inForeground();
}
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();
boolean flag = false;
try {
/**
* take fore ground activity name
*/
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (printLog) {
Log.d("Tag", "CURRENT Activity ::"
+ taskInfo.get(0).topActivity.getClassName());
Log.d("Tag", "Number Of Activities : "
+ taskInfo.get(0).numRunning);
Log.d("Tag",
"Componenet Info : " + componentInfo.getPackageName());
Log.d("Tag",
"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(
"com.package_name",
PackageManager.GET_ACTIVITIES);
ActivityInfo[] list = info.activities;
for (int i = 0; i < list.length; i++) {
Log.d("Tag","Activity : "+list[i].name);
if (list[i].name.equals(componentInfo.getClassName())) {
flag = true;
}
}
if(flag)
{
//activity is running
}
} catch (NameNotFoundException e) {
e.printStackTrace();
}
And take <uses-permission android:name="android.permission.GET_TASKS" /> permission in manifest.
Considering implementing an application that keep track if the app goes front or back using onPause() and onResume().
Have a look at this solution.
Hope it helps.
Related
In the app having background service running, periodical it will trigger some event that app needs to show an activity.
The issue is if that activity is already on top how to not open another one.
The following snippet whenever the event is triggered, the showAlertActivity() will try to open the activity (it is not just a alert).
Any way to check if there is one has been opened? Thanks!
public void showAlertActivity(String title, String msg……) {
// this does not work, throws a exception
//“ava.lang.SecurityException: Permission Denial: getTasks() from pid=24139, uid=10048 requires android.permission.GET_TASKS”
ActivityManager mngr = (ActivityManager) mContext.getSystemService( Activity.ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
for (ActivityManager.RunningTaskInfo info: taskList) {
Log.d(“+++ info.numActivities:" + info.numActivities +", info.topActivity.getClassName():"+info.topActivity.getClassName()+", info.baseActivity:"+info.baseActivity.getClassName());
}
Intent intent = new Intent(mContext, TheAlertActivity.class);
dialogIntent.putExtra(Constants.LAYOUT_RESOURCE_ID, R.layout.alert_form);
dialogIntent.putExtra(Constants.TILTLE, title);
dialogIntent.putExtra(Constants.TEXT, msg);
……
dialogIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
mContext.startActivity(intent);
}
Add something along the lines of this to your Activity you want to check and isOpen will tell you if it is currently on top.
public static boolean isOpen = false;
private static int countOpen = 0;
public void onStart() {
super.onStart();
countOpen++;
isOpen = countOpen > 0;
}
public void onStop() {
super.onStop();
countOpen--;
isOpen = countOpen > 0;
}
The count is added to secure the boolean being correct even if you open the activity for some reason in front of itself and the system sometimes calling the new activities onStart() before the old activities onStop().
I am opening a link in my app and once back is pressed I want to show HomePage to retain user for some more time. I have been trying to acheive this but unable to do so. I get homeLauncher activity as my top as well as baseActivity.
DeepLink Tap > Open desired Activity > user presses back button > Check if its last activity but not homeActivity > If yes, Navigate user to homeActivity.
Tried following code:
#Override
public void onBackPressed() {
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 && taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())){
//// This is last activity
}
else{
//// There are more activities in stack
}
super.onBackPressed();
}
I have also tried isTaskRoot but result is same. It doesn't give right answer.Please help
Use isTaskRoot() method. (From a h9kdroid comment - here)
#Override
public void onBackPressed() {
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(isTaskRoot()){
//// This is last activity
} else{
//// There are more activities in stack
}
super.onBackPressed();
}
You could simply use the ActivityManager it keeps track of which activity is and is not here is a piece of code I stumbled on that I use always:
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 &&
taskList.get(0).topActivity.getClassName().equals(this.getClass().getName())) {
Log.i(TAG, "This is last activity in the stack");
}
Quoting From ActivityManager.RunningTaskInfo
Information you can retrieve about a particular task that is currently
"running" in the system. Note that a running task does not mean the
given task actually has a process it is actively running in; it simply
means that the user has gone to it and never closed it, but currently
the system may have killed its process and is only holding on to its
last state in order to restart it when the user returns.
String getLastOpenClass ;// Global
ActivityManager am = (ActivityManager) this.getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
componentInfo.getPackageName();
getLastOpenClass=taskInfo.get(0).topActivity.getClassName();
if(getLastOpenClass.equals("Your_Class_Name"))
{
}else{
}
Give permission
<uses-permission android:name="android.permission.GET_TASKS" />
The ActivityManager keeps a record of the runnings task and the topmost task .
ActivityManager mngr = (ActivityManager) getSystemService( ACTIVITY_SERVICE );
List<ActivityManager.RunningTaskInfo> taskList = mngr.getRunningTasks(10);
if(taskList.get(0).numActivities == 1 && taskList.get(0).topActivity.getClassName().equals(this.getClass().getName()))
{
Log.i(TAG, "This is Last activity in the stack");
}
Courtesy How to check if an activity is the last one in the activity stack for an application?
Please Check How can I get the current foreground activity package name
http://developer.android.com/intl/es/reference/android/app/ActivityManager.html#getRunningTasks%28int%29
Please note that the below solution will only work on API14+.
Create a custom application class;
public class App extends Application {
private int created;
#Override
public void onCreate() {
registerActivityLifecycleCallbacks(new Callbacks());
}
public int getCreated() {
return created;
}
private class Callbacks implements ActivityLifecycleCallbacks {
#Override
public void onActivityCreated(Activity activity, Bundle savedInstanceState) {
created++;
}
#Override
public void onActivityDestroyed(Activity activity) {
created--;
}
}
}
Register it in your AndroidManifest.xml in the application element;
<application name=".App"/>
And in your activity opened through a deep link use the following piece of code;
#Override
public void onBackPressed() {
if (((App) getApplicationContext()).getCreated() == 1) {
// start your home activity
}
super.onBackPressed();
}
I wrote this off the top of my head so I haven't had a chance to test it, but theoretically it should work.
Specify parent activity for desired Activity, like :
<activity
android:name=".DesiredActivity"
android:parentActivityName="com.packagename.HomePage" >
<!-- The meta-data element is needed for versions lower than 4.1 -->
<meta-data
android:name="android.support.PARENT_ACTIVITY"
android:value="com.packagename.HomePage" />
</activity>
With the parent activity declared, you can use the NavUtils APIs to
synthesize a new back stack by identifying which activity is the
appropriate parent for each activity.
override onBackPressed as :
#Override
public void onBackPressed() {
Intent intent = NavUtils.getParentActivityIntent(this);
startActivity(intent);
super.onBackPressed();
}
Android developer's site has a very good resource for same problem. Please refer to link http://developer.android.com/training/implementing-navigation/temporal.html#SynthesizeBackStack
I have created a service which starts from an activity's onCreate and stops on the activity's onDestroy method. Now I have to check from a method of the service that whether the activity is running in foreground/background(for some cases like application is forcefully closed). How can I do that?
I need to do this coz as far I know there is no guarantee of calling onDestroy method of an activity if any the application is forcefully closed or any kind of crash. So, my service which starts when my activity launches won't stop after any crash or any forceful closing event.
I have seen this link where foreground activities can be checked. But I need to check a running activity in whatever state (either foreground or background)
Final Update
To check for all activities:
#Override
protected void onStop() {
super.onStop();
if (AppConstants.isAppSentToBackground(getApplicationContext())) {
// Do what ever you want after app close simply Close session
}
}
Method to check our app is running or not:
public static boolean isAppSentToBackground(final Context context) {
try {
ActivityManager am = (ActivityManager) context
.getSystemService(Context.ACTIVITY_SERVICE);
// The first in the list of RunningTasks is always the foreground
// task.
RunningTaskInfo foregroundTaskInfo = am.getRunningTasks(1).get(0);
String foregroundTaskPackageName = foregroundTaskInfo.topActivity
.getPackageName();// get the top fore ground activity
PackageManager pm = context.getPackageManager();
PackageInfo foregroundAppPackageInfo = pm.getPackageInfo(
foregroundTaskPackageName, 0);
String foregroundTaskAppName = foregroundAppPackageInfo.applicationInfo
.loadLabel(pm).toString();
// Log.e("", foregroundTaskAppName +"----------"+
// foregroundTaskPackageName);
if (!foregroundTaskAppName.equals("Your App name")) {
return true;
}
} catch (Exception e) {
Log.e("isAppSentToBackground", "" + e);
}
return false;
}
Answer updated again
Use the below method with your package name.It will return true if any of your activity is in foreground.
public boolean isForeground(String myPackage){
ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List< ActivityManager.RunningTaskInfo > runningTaskInfo = am.getRunningTasks(1);
ComponentName componentInfo = runningTaskInfo.get(0).topActivity;
if(componentInfo.getPackageName().equals(myPackage)) return true;
return false;
}
Answer Updated
Check this link first Checking if an Android application is running in the background
http://developer.android.com/guide/topics/fundamentals.html#lcycles is a description of the Life Cycle of an android application.
The method onPause() gets called when the activity goes into the background. So you can deactivate the update notifications in this method.
public static boolean isApplicationSentToBackground(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;
}
add permisions in the menifest as well
<uses-permission android:name="android.permission.GET_TASKS" />
Unfortunately, getRunningTasks() has been deprecated since Android API 21 (Android Lollipop):
This method was deprecated in API level 21. As of LOLLIPOP, this
method is no longer available to third party applications: the
introduction of document-centric recents means it can leak person
information to the caller. For backwards compatibility, it will still
return a small subset of its data: at least the caller's own tasks,
and possibly some other tasks such as home that are known to not be
sensitive.
Try this method to check your app is in background or not:
public boolean isAppIsInBackground(Context context) {
boolean isInBackground = true;
ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT_WATCH) {
List<ActivityManager.RunningAppProcessInfo> runningProcesses = am.getRunningAppProcesses();
for (ActivityManager.RunningAppProcessInfo processInfo : runningProcesses) {
if (processInfo.importance == ActivityManager.RunningAppProcessInfo.IMPORTANCE_FOREGROUND) {
for (String activeProcess : processInfo.pkgList) {
if (activeProcess.equals(context.getPackageName())) {
isInBackground = false;
}
}
}
}
} else {
List<ActivityManager.RunningTaskInfo> taskInfo = am.getRunningTasks(1);
ComponentName componentInfo = taskInfo.get(0).topActivity;
if (componentInfo.getPackageName().equals(context.getPackageName())) {
isInBackground = false;
}
}
return isInBackground;
}
check this link & especially check the Answer Which shows this part of code
public class MyApplication extends Application {
public static boolean isActivityVisible() {
return activityVisible;
}
public static void activityResumed() {
activityVisible = true;
}
public static void activityPaused() {
activityVisible = false;
}
private static boolean activityVisible;
}
Hope this help you.
I want to detect and count when Activity goes from background to foreground (when activity is visible, increase count).I tried to use flag in onPause() and onResume() like this:
void onPause(){
flag = true;
}
void onResume(){
if(flag){
//save to shared reference.
saveCount(getCount(count) + 1);
flag = false;
}
}
It works when user press home key and relaunches the app, but when I transfer Activity then goes back, it still increases the count, because it calls onPause(). How to prevent that? Or is there anyway to count this?
Use this method to check wheter app is brought to background:
private boolean isApplicationBroughtToBackground(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;
}
It requires the GET_TASKS permission:
<uses-permission android:name="android.permission.GET_TASKS" />
I want to detect and count when Activity goes from background to foreground (when activity is visible, increase count).I tried to use flag in onPause() and onResume() like this:
void onPause(){
flag = true;
}
void onResume(){
if(flag){
//save to shared reference.
saveCount(getCount(count) + 1);
flag = false;
}
}
It works when user press home key and relaunches the app, but when I transfer Activity then goes back, it still increases the count, because it calls onPause(). How to prevent that? Or is there anyway to count this?
Use this method to check wheter app is brought to background:
private boolean isApplicationBroughtToBackground(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;
}
It requires the GET_TASKS permission:
<uses-permission android:name="android.permission.GET_TASKS" />