Have the activity supply a PendingIntent (e.g., via createPendingResult()) that the service invokes

Have the activity register a callback or listener object with the service via bindService(), and have the service call an event method on that callback/listener object

Send an ordered broadcast Intent to the activity, with a low-priority BroadcastReceiver as backup (to raise a Notification if the activity is not on-screen) -- here is a blog post with more on this pattern

Thanks, but as I do have a looot of activities, and don't want to update them all, I was looking for an android way to get the foregroundActivity. As you say, I should not be able to do that. Means I have to get my way around this.
– GeorgeOct 7 '10 at 11:36

1

@George: What you want wouldn't help you, anyway. As you point out, you have "a looot of activities". Hence, those are all separate classes. Hence, there is nothing your service can do with them without either a massive if-block of instanceof checks or refactoring the activities to share a common superclass or interface. And if you're going to refactor the activities, you may as well do it in a way that fits better with the framework and covers more scenarios, such as none of your activities being active. #4 is probably the least work and most flexible.
– CommonsWareOct 7 '10 at 11:43

2

Thanks, but I have a better solution. All my activities extends a customised BaseActivity class. I have set a ContextRegister that registeres the activity as current whenever it is on the foreground, with literraly 3 lines in my BaseActivity class. Still, thanks for the support.
– GeorgeOct 8 '10 at 12:33

3

@George: Watch out for memory leaks. Mutable static data members are to be avoided in Java wherever possible.
– CommonsWareOct 8 '10 at 13:06

I have tightly encapsualted the object, though I will indeed keep this in mind. Thanks.
– GeorgeOct 8 '10 at 13:22

Here's a good way to do it using the activity manager.
You basically get the runningTasks from the activity manager. It will always return the currently active task first. From there you can get the topActivity.

There's an easy way of getting a list of running tasks from the ActivityManager service.
You can request a maximum number of tasks running on the phone, and by default, the currently active task is returned first.

Once you have that you can get a ComponentName object by requesting the topActivity from your list.

@ArtOfWarfare haven't verified but yes, the number of fragments you have is irrelevant as they are always hosted by a single activity.
– Nelson RamirezSep 9 '12 at 0:59

1

If i need the current activity more frequently, I have to poll very frequently right? Is there a way to get a callback event whenever the foreground activity changes?
– nizam.spMar 28 '13 at 20:42

42

Just so everybody is aware, the docs state this about the getRunningTasks() method. -------- 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. Such uses are not supported, and will likely break in the future. For example, if multiple applications can be actively running at the same time, assumptions made about the meaning of the data here for purposes of control flow will be incorrect. ------------
– RyanJul 3 '13 at 21:55

28

semifake on api 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.
– sherpyaDec 22 '14 at 21:21

Disadvantages

When a user tries to enable the AccessibilityService, they can't press the OK button if an app has placed an overlay on the screen. Some apps that do this are Velis Auto Brightness and Lux. This can be confusing because the user might not know why they can't press the button or how to work around it.

Service Info

Put this in res/xml/accessibilityservice.xml:

<?xml version="1.0" encoding="utf-8"?>
<!-- These options MUST be specified here in order for the events to be received on first
start in Android 4.1.1 -->
<accessibility-service
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews"
android:description="@string/accessibility_service_description"
xmlns:android="http://schemas.android.com/apk/res/android"
tools:ignore="UnusedAttribute"/>

@lovemint, what I meant is: I specified an example settingsActivity of your.app.ServiceSettingsActivity, so you should change that to your own settings activity for your accessibility service. I think the settings activity is optional anyway, so I've removed that part from my answer to make it simpler.
– SamJun 4 '15 at 11:00

1

Thanks very much, only last question. If i need to deal from API 8 to the current i should do that work in the code instead using XML?
– HoperJun 8 '15 at 13:57

1

@lovemint, that's right. I just updated the example code to do this.
– SamJun 9 '15 at 11:20

1

@Sam I can confirm that this Service works perfectly. One strange behavior, I used an intent in the main activity to enable Accessibility Service. After this first activation the service it's activated but onAccessibilityEvent does not receive any event, but if i disable, and enable again Accessibility Service the service it is re-activated and onAccessibilityEvent begins to work.
– HoperJun 11 '15 at 17:43

2

Thank you for your code. I created this app for you :)
– vaultAug 12 '16 at 22:15

Implement your own application class, register for ActivityLifecycleCallbacks - this way you can see what is going on with our app. On every on resume the callback assigns the current visible activity on the screen and on pause it removes the assignment. It uses method registerActivityLifecycleCallbacks() which was added in API 14.

In your service call getApplication() and cast it to your app class name (App in this case). Than you can call app.getActiveActivity() - that will give you a current visible Activity (or null when no activity is visible). You can get the name of the Activity by calling activeActivity.getClass().getSimpleName()

I am getting Nullpointer exeception at activeActivity.getClass().getSimpleName().can you please help
– beginnerJun 1 '17 at 9:29

Well as you can see from the ActivityLifecycleCallbacks - in case the activity is not visible, application.getActiveActivity() returns null. That means that no activity is visible. You need to check for this in your service or wherever else you use this.
– Vit VeresJun 2 '17 at 11:07

ok..but in case the activity resumes then this should not return null ?? My activity had launched and in its on resume I got so
– beginnerJun 2 '17 at 11:16

Hard to guess, try to put breakpoints at onActivityResumed(), onActivityPaused() and to getActiveActivity() to see how is it callet, if ever so.
– Vit VeresJun 3 '17 at 12:40

@beginner one must check if activity and activeActivity are same before assigning activeActivity with null in order to avoid errors due to intermingled calling order of lifecycle methods of various activities.
– Rahul TiwariJan 25 at 17:33

one must check if activity and currentActivity are same before assigning currentActivity with null in order to avoid errors due to intermingled calling order of lifecycle methods of various activities.
– Rahul TiwariJan 25 at 17:31

You should be able to get current Activity in this way...
If you structure your app with a few Activities with many fragments and you want to keep track of what is your current Activity, it would take a lot of work though. My senario was I do have one Activity with multiple Fragments. So I can keep track of Current Activity through Application Object, which can store all of the current state of Global variables.

Here is a way. When you start your Activity, you store that Activity by
Application.setCurrentActivity(getIntent());
This Application will store it.
On your service class, you can simply do like
Intent currentIntent = Application.getCurrentActivity();
getApplication().startActivity(currentIntent);

I don't know if it's a stupid answer, but resolved this problem by storing a flag in shared preferences every time I entered onCreate() of any activity, then I used the value from shered preferences to find out what it's the foreground activity.