Discovering if Android activity is running
Asked Answered
P

4

7

I'm using C2DM, my BroadcastReceivers propagate the C2DM events to a local service. the service complete the registration by sending the id to my webserver pus it's responsible for letting the device know about new messages, however if the application (one of the activities) is up we want to send an intent to that activity with the new data so it can be updated, if not than the NotificationManager is used to notify the user.

The issue is, how to know the activity is running ? the Application object is not an option since the Service is part of the application it's obviously going to be present. unregister in the onDesroy of each application is also not an option since it may occur in orientation change...

Any standard way to get it done ?

Perennial answered 27/5, 2012 at 5:33 Comment(0)
L
19

Solution 1: You can use ActivityManager for Checking if Activity is Running or not:

public boolean isActivityRunning() { 

ActivityManager activityManager = (ActivityManager)Monitor.this.getSystemService (Context.ACTIVITY_SERVICE); 
    List<RunningTaskInfo> activitys = activityManager.getRunningTasks(Integer.MAX_VALUE); 
    isActivityFound = false; 
    for (int i = 0; i < activitys.size(); i++) { 
        if (activitys.get(i).topActivity.toString().equalsIgnoreCase("ComponentInfo{com.example.testapp/com.example.testapp.Your_Activity_Name}")) {
            isActivityFound = true;
        }
    } 
    return isActivityFound; 
} 

need to add the permission to your manifest..

<uses-permission  android:name="android.permission.GET_TASKS"/>

Solution 2: Your can use an static variable in your activity for which you want to check it's running or not and store it some where for access from your service or broadcast receiver as:

static boolean CurrentlyRunning= false;
      public void onStart() {
         CurrentlyRunning= true; //Store status of Activity somewhere like in shared //preference 
      } 
      public void onStop() {
         CurrentlyRunning= false;//Store status of Activity somewhere like in shared //preference 
      }

I hope this was helpful!

Lysenkoism answered 27/5, 2012 at 6:50 Comment(5)
the first method looks intresting, but i want to know if any activity is running or more like if my application is running (service excluded) the static method os not good since Activity may have more than one instance maybe an Application mutex would do the trick...Perennial
I might be wrong but I think this only checks the current top activity in a task. If so, what about the other activities (paused or stopped) in the same task?Crunode
DO NOT use the first method. From ActivityManager documentation: "Note: this method is only intended for debugging and presenting task management user interfaces. This should never be used for core logic in an application, such as deciding between different behaviors based on the information found here. "Northernmost
also, it's deprecated and broken now: @deprecated 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 sensitiveOgdon
Solution 1 doesn't work when you have a BroadcastReceiver / Service running. The app appears to always be running. However, Solution 2 worked great for us, after trying countless other methods.Nuss
B
4

The next approach would work well if you want to handle incoming Google Cloud message (C2DM) by your activity (if any is running) or issue a notification if no activities are running.

Register one BroadcastReceiver in the manifest file. This receiver will handle C2D messages whenever application not running. Register another BroadcastReceiver programmatically in your activity. This receiver will handle C2D messages whenever activity is running.

AndoroidManifest.xml

<receiver
    android:name=".StaticReceiver"
    android:permission="com.google.android.c2dm.permission.SEND" >
    <intent-filter>
        <action android:name="com.google.android.c2dm.intent.RECEIVE" />
        <category android:name="com.mypackage" />
    </intent-filter>
</receiver>

MyReceiver.java

public class StaticReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        // TODO Trigger a Notification
    }
}

MyActivity.java

public class MyActivity extends ActionBarActivity {

    @Override
    protected void onResume() {
    super.onResume();

        final IntentFilter filter = new 
                IntentFilter("com.google.android.c2dm.intent.RECEIVE");
        filter.addCategory("com.mypackage");
        filter.setPriority(1); 
        registerReceiver(dynamicReceiver, filter, 
                "com.google.android.c2dm.permission.SEND", null);
    }

    @Override
    protected void onPause() {
        super.onPause();
        unregisterReceiver(dynamicReceiver);
    }

    private final BroadcastReceiver dynamicReceiver 
            = new BroadcastReceiver() 
    {
        @Override
        public void onReceive(Context context, Intent intent) {

            // TODO Handle C2DM

            // blocks passing broadcast to StaticReceiver instance
            abortBroadcast();
       }
    };
}

Note! To catch broadcasts first, the priority of dynamicReceiver IntentFilter must be higher than priority of StaticReceiver instance IntentFilter (default priority is '0').

PS. It looks like broadcasts issued by Google Cloud Messaging Service are ordered broadcasts. Original idea author: CommonsWare

Boudicca answered 27/3, 2014 at 12:46 Comment(0)
P
0

Copied from here.

you can use a static variable within the activity.

class MyActivity extends Activity {
     static boolean active = false;

      public void onStart() {
         active = true;
      } 

      public void onStop() {
         active = false;
      }
}
Papillote answered 27/5, 2012 at 7:40 Comment(1)
If you find a perfect match in another question and its answers, you should not answer here, but flag this question as duplicate...Comeuppance
S
0

Easiest way to check that whether an Activity is running or not is:

Context context = MyActivity.this; 

if (! ((Activity) context).isFinishing()) {
    //  Activity is running
} else {
    //  Activity has been finished
}

Note: If activity is not running you should not perform any UI related operation.

Sorrell answered 22/8, 2016 at 12:30 Comment(2)
When issued from a background service, Context context = MyActivity.this; will result in an error saying that MyActivity "is not an enclosing class"Mcleod
Well if you already hold a MyActivity.this then there are much better/easier ways to check the activity state anyway :DOgdon

© 2022 - 2024 — McMap. All rights reserved.