admin 管理员组

文章数量: 1184232

Android 辅助功能(AccessibilityService) 为我们提供了一系列的事件回调,帮助我们指示一些用户界面的状态变化。 我们可以派生辅助功能类,进而对不同的 AccessibilityEvent 进行处理。同样的,这个服务就可以用来判断当前的前台应用,这就是我所谓的“方法6”。

优势

  • AccessibilityService 有非常广泛的 ROM 覆盖,特别是非国产手机,从 Android API Level 18(Android 2.2) 到 Android Api Level 23(Android 6.0)
  • AccessibilityService 不再需要轮询的判断当前的应用是不是在前台,系统会在窗口状态发生变化的时候主动回调,耗时和资源消耗都极小
  • 不需要权限请求
  • 它是一个稳定的方法,与 “方法5”读取 /proc 目录不同,它并非利用 Android 一些设计上的漏洞,可以长期使用的可能很大
  • 可以用来判断任意应用甚至 Activity, PopupWindow, Dialog 对象是否处于前台

劣势

  • 需要要用户开启辅助功能
  • 辅助功能会伴随应用被“强行停止”而剥夺

步骤

1. 派生 Accessibility Service,创建窗口状态探测服务

创建 DetectionService.java

/**
 * Created by shawn
 * Data: 2/3/2016
 * Blog: effmx
 */
public class DetectionService extends AccessibilityService {

    final static String TAG = "DetectionService";

    static String foregroundPackageName;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        return 0; // 根据需要返回不同的语义值
    }


    /**
     * 重载辅助功能事件回调函数,对窗口状态变化事件进行处理
     * @param event
     */
    @Override
    public void onAccessibilityEvent(AccessibilityEvent event) {
        if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            /*
             * 如果 与 DetectionService 相同进程,直接比较 foregroundPackageName 的值即可
             * 如果在不同进程,可以利用 Intent 或 bind service 进行通信
             */
            foregroundPackageName = event.getPackageName().toString();

            /*
             * 基于以下还可以做很多事情,比如判断当前界面是否是 Activity,是否系统应用等,
             * 与主题无关就不再展开。
             */
            ComponentName cName = new ComponentName(event.getPackageName().toString(),
                    event.getClassName().toString());
        }
    }

    @Override
    public void onInterrupt() {
    }

    @Override
    protected  void onServiceConnected() {
        super.onServiceConnected();
    }
}

2. 创建 Accessibility Service Info 属性文件

创建 res/xml/detection_service_config.xml

<?xml version="1.0" encoding="utf-8"?>
<!-- 根据的 Service 的不同功能需要,你可能需要不同的配置 -->
<accessibility-service
    xmlns:android="http://schemas.android/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagIncludeNotImportantViews" />

3. 注册 Detection Service 到 AndroidManifest.xml

在 AndroidManifest.xml 里添加

<service
    android:name="your_package.DetectionService"
    android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">

    <intent-filter>
        <action android:name="android.accessibilityservice.AccessibilityService"/>
    </intent-filter>

    <meta-data
        android:name="android.accessibilityservice"
        android:resource="@xml/detection_service_config"/>

</service>

4. 使用 Detection Service 判断应用是否在前台

创建 isForegroundPkgViaDetectionService() 函数

    /**
     * 方法6:使用 Android AccessibilityService 探测窗口变化,跟据系统回传的参数获取 前台对象 的包名与类名
     *
     * @param packageName 需要检查是否位于栈顶的App的包名
     */
    public static boolean isForegroundPkgViaDetectionService(String packageName) {
        return packageName.equals(DetectingService.foregroundPackageName);
    }

记得去设置里开启辅助功能,现在你就可以通过 isForegroundPkgViaDetectService() 判断应用是否在前台了,只需要传入相应应用的包名为参数即可。

当然,你也可以参照以下方式引导用户开启辅助功能↓

引导用户开启辅助功能

    final static String TAG = "AccessibilityUtil";

    // 此方法用来判断当前应用的辅助功能服务是否开启
    public static boolean isAccessibilitySettingsOn(Context context) {
        int accessibilityEnabled = 0;
        try {
            accessibilityEnabled = Settings.Secure.getInt(context.getContentResolver(),
                    android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
        } catch (Settings.SettingNotFoundException e) {
            Log.i(TAG, e.getMessage());
        }

        if (accessibilityEnabled == 1) {
            String services = Settings.Secure.getString(context.getContentResolver(),
                    Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
            if (services != null) {
                return services.toLowerCase().contains(context.getPackageName().toLowerCase());
            }
        }

        return false;
    }

    private void anyMethod() {
        // 判断辅助功能是否开启
        if (!isAccessibilitySettingsOn(getContext())) {
            // 引导至辅助功能设置页面
            startActivity(new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS));
        } else {
            // 执行辅助功能服务相关操作
        }
    }

效果如下:


代码下载地址:http://download.csdn/detail/yishifu/9595297

本文标签: 前台 界面 AcessibilityService