Android: How can I get the current foreground activity (from a service)?

前端 未结 12 1824
北恋
北恋 2020-11-22 07:53

Is there a native android way to get a reference to the currently running Activity from a service?

I have a service running on the background, and I would like to up

12条回答
  •  旧时难觅i
    2020-11-22 08:16

    Warning: Google Play violation

    Google has threatened to remove apps from the Play Store if they use accessibility services for non-accessibility purposes. However, this is reportedly being reconsidered.


    Use an AccessibilityService

    • You can detect the currently active window by using an AccessibilityService.
    • In the onAccessibilityEvent callback, check for the TYPE_WINDOW_STATE_CHANGED event type to determine when the current window changes.
    • Check if the window is an activity by calling PackageManager.getActivityInfo().

    Benefits

    • Tested and working in Android 2.2 (API 8) through Android 7.1 (API 25).
    • Doesn't require polling.
    • Doesn't require the GET_TASKS permission.

    Disadvantages

    • Each user must enable the service in Android's accessibility settings.
    • This isn't 100% reliable. Occasionally the events come in out-of-order.
    • The service is always running.
    • 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.
    • The AccessibilityService won't know the current activity until the first change of activity.

    Example

    Service

    public class WindowChangeDetectingService extends AccessibilityService {
    
        @Override
        protected void onServiceConnected() {
            super.onServiceConnected();
    
            //Configure these here for compatibility with API 13 and below.
            AccessibilityServiceInfo config = new AccessibilityServiceInfo();
            config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
            config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
    
            if (Build.VERSION.SDK_INT >= 16)
                //Just in case this helps
                config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
    
            setServiceInfo(config);
        }
    
        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {
            if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
                if (event.getPackageName() != null && event.getClassName() != null) {
                    ComponentName componentName = new ComponentName(
                        event.getPackageName().toString(),
                        event.getClassName().toString()
                    );
    
                    ActivityInfo activityInfo = tryGetActivity(componentName);
                    boolean isActivity = activityInfo != null;
                    if (isActivity)
                        Log.i("CurrentActivity", componentName.flattenToShortString());
                }
            }
        }
    
        private ActivityInfo tryGetActivity(ComponentName componentName) {
            try {
                return getPackageManager().getActivityInfo(componentName, 0);
            } catch (PackageManager.NameNotFoundException e) {
                return null;
            }
        }
    
        @Override
        public void onInterrupt() {}
    }
    

    AndroidManifest.xml

    Merge this into your manifest:

    
        
            
                
            
            
        
    
    

    Service Info

    Put this in res/xml/accessibilityservice.xml:

    
    
    
    

    Enabling the Service

    Each user of the app will need to explicitly enable the AccessibilityService in order for it to be used. See this StackOverflow answer for how to do this.

    Note that the user won't be able to press the OK button when trying to enable the accessibility service if an app has placed an overlay on the screen, such as Velis Auto Brightness or Lux.

提交回复
热议问题