android - Android 中的无障碍服务不断被禁用

标签 android accessibilityservice

我开发了一个基于无障碍服务的 Android 应用程序。但是我有一个问题,我在 Internet 上找不到任何帮助。当我在任何设备上安装应用程序时,显然它不会开始工作,直到:

  • 我转到辅助功能设置
  • 找到它的无障碍服务
  • 进入并按下开关打开服务

  • 问题有点复杂:
    启用辅助功能服务后,我可以在辅助功能设置屏幕中看到该服务显示“已启用”。事实上,该应用程序正在运行。但是如果我进入服务,顶部和右侧有一个开关,显示为OFF。为什么?服务已启用并正常工作并且开关显示为关闭是没有意义的。

    我已经尝试过使用另一种服务作为内置的 Talkback。当我打开开关时,返回辅助功能设置屏幕,然后再次进入对讲服务,开关保持打开状态。为什么它不能与我的服务正常工作?

    再次,我解释说,虽然激活开关对我的服务不能正常工作,但我的应用程序确实可以工作,唯一的问题是那个开关,当我的服务已经打开时,它会混淆用户显示 OFF。

    有什么原因会发生这种情况吗?也许我错过了诸如在服务启用时告诉系统之类的事情?

    我的服务代码没有什么异常,与任何其他无障碍服务类似,除了我在事件发生时的自定义操作。

    这是应用程序的 list XML 文件:
    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
        package="bembibre.attractive"
        android:versionCode="1"
        android:versionName="1.0" >
    
        <uses-sdk
            android:minSdkVersion="11"
            android:targetSdkVersion="21" />
    
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
        <uses-permission android:name="android.permission.WAKE_LOCK" />
        <uses-permission android:name="android.permission.BIND_ACCESSIBILITY_SERVICE" />
        <uses-permission android:name="android.permission.READ_CALENDAR" />
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />
        <uses-permission android:name="android.permission.READ_CONTACTS" />
        <uses-permission android:name="android.permission.READ_CALL_LOG" />
        <uses-permission android:name="android.permission.RECEIVE_SMS"/>
        <uses-permission android:name="android.permission.READ_SMS" />
    
        <application
            android:allowBackup="true"
            android:icon="@drawable/ic_launcher"
            android:label="@string/app_name"
            android:theme="@style/AppTheme" >
            <activity
                android:name="bembibre.attractive.activities.MainActivity"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>
            <activity android:name="bembibre.attractive.activities.HelpActivity" >
            </activity>
            <activity android:name="bembibre.attractive.activities.NotesActivity" >
            </activity>
    
            <!-- BroadCastReceiver's -->
            <receiver
                android:name=".NotificationsWidget"
                android:icon="@drawable/ic_launcher"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
                </intent-filter>
    
                <meta-data
                    android:name="android.appwidget.provider"
                    android:resource="@xml/widget_provider" />
            </receiver>
            <receiver
                android:name="bembibre.attractive.events.receivers.DateChangedReceiver"
                android:icon="@drawable/ic_launcher"
                android:label="@string/app_name" >
                <intent-filter>
                    <action android:name="android.intent.action.TIMEZONE_CHANGED" />
                    <action android:name="android.intent.action.TIME_SET" />
                </intent-filter>
            </receiver>
            <receiver android:name="bembibre.attractive.events.scheduling.OnAlarmReceiver" />
            <receiver android:name="bembibre.attractive.events.receivers.CalendarChangedReceiver" >
                <intent-filter>
                    <action android:name="android.intent.action.PROVIDER_CHANGED" />
    
                    <data android:scheme="content" />
                    <data android:host="com.android.calendar" />
                </intent-filter>
            </receiver>
            <receiver
                android:name="bembibre.attractive.events.receivers.MissedCallsChangedReceiver"
                android:enabled="true" >
                <intent-filter>
                    <action android:name="android.intent.action.PHONE_STATE" />
                </intent-filter>
            </receiver>
            <receiver android:name="bembibre.attractive.events.receivers.SmsReceiver" >
                <intent-filter android:priority="500" >
                    <action android:name="android.provider.Telephony.SMS_RECEIVED" />
                </intent-filter>
            </receiver>
    
            <!-- Servicios -->
            <service android:name="bembibre.attractive.ui.WidgetPaintingService" />
            <service android:name="bembibre.attractive.events.wakelocks.DateChangedCpuLockTask" />
            <service android:name="bembibre.attractive.events.wakelocks.UpdateWhatsAppDataCpuLockTask" />
            <service android:name="bembibre.attractive.events.wakelocks.CalendarChangedCpuLockTask" />
            <service android:name="bembibre.attractive.events.wakelocks.MissedCallsChangedCpuLockTask" />
            <service android:name="bembibre.attractive.events.wakelocks.SmsChangedCpuLockTask" />
            <service android:name="bembibre.attractive.events.wakelocks.UpdateAllDataCpuLockTask" />
            <service
                android:name="bembibre.attractive.events.EventsAccessibilityService"
                android:label="@string/accessibility_service_label"
                android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE" >
                <meta-data
                    android:name="android.accessibilityservice"
                    android:resource="@xml/accessibility_service_config" />
    
                <intent-filter>
                    <action android:name="android.accessibilityservice.AccessibilityService" />
                </intent-filter>
            </service>
        </application>
    </manifest>
    

    list 声明了无障碍服务,它引用了以下配置文件:
    <accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
        android:description="@string/accessibility_service_description"
    />
    

    下面是实现无障碍服务的 Java 类的代码:
    package bembibre.attractive.events;
    
    import java.util.ArrayList;
    import java.util.List;
    
    import android.accessibilityservice.AccessibilityService;
    import android.accessibilityservice.AccessibilityServiceInfo;
    import android.annotation.SuppressLint;
    import android.app.Notification;
    import android.os.Build;
    import android.view.accessibility.AccessibilityEvent;
    import android.widget.RemoteViews;
    import bembibre.attractive.events.wakelocks.CpuLockTask;
    import bembibre.attractive.events.wakelocks.DeleteAllWhatsAppDataCpuLockTask;
    import bembibre.attractive.events.wakelocks.MissedCallsChangedCpuLockTask;
    import bembibre.attractive.events.wakelocks.SmsChangedCpuLockTask;
    import bembibre.attractive.events.wakelocks.UpdateWhatsAppDataCpuLockTask;
    import bembibre.attractive.logging.Logger;
    import bembibre.attractive.logic.ApplicationPackages;
    import bembibre.attractive.logic.whatsapp.WhatsAppNotificationContent;
    import bembibre.attractive.logic.whatsapp.WhatsAppNotificationExtractionStrategy;
    import bembibre.attractive.utils.AppUtils;
    import bembibre.attractive.utils.ArrayUtils;
    
    /**
     * Clase que representa un servicio que debe estar activo todo el tiempo para que el widget de notificaciones funcione
     * correctamente. Este servicio se encarga de capturar distintos eventos que hacen que aparezcan datos en el widget.
     * 
     * @author misines
     * 
     */
    public class EventsAccessibilityService extends AccessibilityService {
    
        private static final List<Integer> OPEN_WINDOW_EVENTS = new ArrayList<Integer>();
    
        private static final List<WhatsAppNotificationExtractionStrategy> STRATEGIES = new ArrayList<WhatsAppNotificationExtractionStrategy>();
        static {
            /*
             * Añadimos las estrategias para la extracción de contenido de notificaciones de WhatsApp.
             */
            // Aún no dispongo de las estrategias necesarias...
        }
    
        @SuppressLint("InlinedApi")
        @Override
        public void onServiceConnected() {
            AccessibilityServiceInfo info = new AccessibilityServiceInfo();
    
            OPEN_WINDOW_EVENTS.add(AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED);
            OPEN_WINDOW_EVENTS.add(AccessibilityEvent.TYPE_VIEW_FOCUSED);
            // if (Build.VERSION.SDK_INT >= 14) {
            // OPEN_WINDOW_EVENTS.add(AccessibilityEvent.TYPE_WINDOW_CONTENT_CHANGED);
            // OPEN_WINDOW_EVENTS.add(AccessibilityEvent.TYPE_VIEW_SCROLLED);
            // }
            // else {
            // OPEN_WINDOW_EVENTS.add(2048);
            // OPEN_WINDOW_EVENTS.add(4096);
            // }
    
            // Set the type of events that this service wants to listen to. Others
            // won't be passed to this service.
            int eventTypes = AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED;
            for (Integer openWindowEvent : OPEN_WINDOW_EVENTS) {
                eventTypes = eventTypes | openWindowEvent;
            }
            info.eventTypes = eventTypes;
    
            // If you only want this service to work with specific applications, set their
            // package names here. Otherwise, when the service is activated, it will listen
            // to events from all applications.
            info.packageNames = ApplicationPackages.getMergedPackages(ApplicationPackages.PKG_WHATSAPP,
                    ApplicationPackages.PKG_CALLS, ApplicationPackages.PKG_SMS);
    
            // Set the type of feedback your service will provide.
            info.feedbackType = AccessibilityServiceInfo.FEEDBACK_VISUAL;
    
            // Default services are invoked only if no package-specific ones are present
            // for the type of AccessibilityEvent generated. This service *is*
            // application-specific, so the flag isn't necessary. If this was a
            // general-purpose service, it would be worth considering setting the
            // DEFAULT flag.
    
            // info.flags = AccessibilityServiceInfo.DEFAULT;
    
            info.notificationTimeout = 100;
    
            this.setServiceInfo(info);
    
        }
    
        @Override
        public void onAccessibilityEvent(AccessibilityEvent event) {
            int eventType = event.getEventType();
            String packageName = event.getPackageName().toString();
            Logger.log("Evento de accesibilidad detectado de tipo: " + Integer.valueOf(eventType).toString()
                    + ", aplicación: " + packageName);
            if (isOpenWindowEvent(eventType)) {
                if (ArrayUtils.containsIgnoreCase(ApplicationPackages.PKG_WHATSAPP, packageName)) {
                    Logger.log("Se ha abierto la aplicación WhatsApp");
                    CpuLockTask.execute(this, DeleteAllWhatsAppDataCpuLockTask.class);
                }
    
                /*
                 * En llamadas y mensajes tenemos que introducir un retardo porque sino suele pasar que la recolección de
                 * datos se produce antes de que el sistema haya marcado las llamadas y mensajes como leídos.
                 */
                if (ArrayUtils.containsIgnoreCase(ApplicationPackages.PKG_CALLS, packageName)) {
                    Logger.log("Se ha abierto la aplicación de las llamadas.");
                    CpuLockTask.execute(this, MissedCallsChangedCpuLockTask.class, AppUtils.SLEEP_BEFORE_RECOLLECTION);
                }
                if (ArrayUtils.containsIgnoreCase(ApplicationPackages.PKG_SMS, packageName)) {
                    Logger.log("Se ha abierto la aplicación de los SMSs.");
                    CpuLockTask.execute(this, SmsChangedCpuLockTask.class, AppUtils.SLEEP_BEFORE_RECOLLECTION);
                }
            }
            if (((ArrayUtils.containsIgnoreCase(ApplicationPackages.PKG_WHATSAPP, packageName)) && (eventType == AccessibilityEvent.TYPE_NOTIFICATION_STATE_CHANGED))) {
                this.processWhatsAppNotificacion(event);
            }
        }
    
        @Override
        public void onInterrupt() {
    
        }
    
        private boolean isOpenWindowEvent(int event) {
            boolean result;
            if (OPEN_WINDOW_EVENTS.contains(event)) {
                result = true;
            } else {
                result = false;
            }
            return result;
        }
    
        @SuppressLint("NewApi")
        private void processWhatsAppNotificacion(AccessibilityEvent event) {
            Notification notification;
            try {
                notification = ((Notification) event.getParcelableData());
            } catch (ClassCastException e) {
                notification = null;
            }
            if (notification == null) {
                Logger.log("Se ha recibido una notificación de WhatsApp pero no es de clase \"Notification\" o está vacía.");
            } else {
                WhatsAppNotificationContent content = null;
                int index = 1;
                for (WhatsAppNotificationExtractionStrategy strategy : STRATEGIES) {
                    content = strategy.extract(notification);
                    if (content != null) {
                        Logger.log("Éxito en estrategia de extracción " + index + ".");
                        break;
                    }
                    index++;
                }
                if (content == null) {
                    Logger.log("Se ha recibido una notificación de WhatsApp pero la vista está vacía o ninguna de las estrategias de extracción han funcionado.");
                } else {
                    Logger.log("Se ha recibido una notificación de WhatsApp analizable.");
                    CpuLockTask.execute(this, UpdateWhatsAppDataCpuLockTask.class, 0, content);
                }
            }
        }
    }
    

    我很抱歉代码的注释是西类牙语的。那是因为它是我的母语。

    最佳答案

    我在小米红米笔记 3(棉花糖)上使用 Greenify,

    我做了
    :
    Settings->apps setting->permissions-> autostart
    , 和 允许绿化 .它对我有用。

    关于android - Android 中的无障碍服务不断被禁用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37519245/

    相关文章:

    java - android AccessibilityService 突然停止触发事件 - 请检查我的代码

    java - 如何获取点击复选框所在行的ListView位置和对应的SimpleAdapter数据?

    android - 位置参数必须出现在命名参数之前,并且 flutter 上的位置参数太多

    android - 检测我的无障碍服务是否启用

    java - 如何从另一个服务调用 AccessibilityService 方法?

    accessibilityservice - Android 无障碍服务在 Oreo 上一两天后停止工作

    android - 如何以编程方式使用默认的 AlertDialog 添加 TextView 和 EditText

    java - 无法解析 FragmentPagerAdapter 的父类(super class)

    android - 在异步任务中加载 View