Android中的辅助功能服务不断被禁用

时间:2016-05-30 06:47:12

标签: android accessibilityservice

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

  1. 我转到辅助功能设置
  2. 找到其辅助功能服务
  3. 进入并按下开关以打开服务
  4. 问题有点复杂: 启用辅助功能服务后,我可以在辅助功能设置屏幕中看到该服务显示"已启用"。事实上,该应用程序正在运行。但是,如果我进入该服务,则顶部和右侧有一个开关,显示为OFF。为什么?没有任何意义,该服务已启用并正常工作,并且交换机显示为OFF。

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

    再次,我解释说,虽然激活开关对我的服务没有正常工作,但我的应用程序确实有效,唯一的问题是切换,当我的服务已经开启时,这会让显示OFF的用户感到困惑。< / p>

    有什么理由可以发生这种情况吗?也许我错过了一些事情,比如告诉系统何时启用服务或类似的东西?

    我的服务代码没有什么异常,类似于任何其他辅助功能服务,但事件发生时我的自定义操作除外。

    以下是应用程序的清单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>
    

    清单声明了辅助功能服务,它引用了以下配置文件:

    <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);
                }
            }
        }
    }
    

    我很抱歉代码的评论是西班牙语。那是因为它是我的母语。

2 个答案:

答案 0 :(得分:0)

在小米redmi note 3(棉花糖)上,Greenify发生了这件事,

我做到了 :

Settings->apps setting->permissions-> autostart

允许Greenify 。它对我有用。

答案 1 :(得分:-1)

就我而言,oppo f1s,我找到了一个解决方案:

  1. 首先,您的设备应该是root用户,最好的方法是将固件重置为出厂设置或更新到更新的oppo系统映像,然后安装自定义恢复BIOS或其名称, 然后使用Magisc在恢复模式下生根。 所有这些都在一些xda-developers论坛主题中进行了描述。 但是现在这不是我们的问题。

  2. 要阻止从我们的服务或应用撤消访问权限,我们必须通过浏览设置&gt;&gt;进入开发人员选项。 设备信息,然后在构建版本上点击大约8次或更多次。

  3. 现在,当我们成为好的开发者时,我们会返回,然后我们导航到设置&gt;&gt; 高级设置&gt;&gt; 开发人员设置并启用开发人员选项。

  4. 打开正在运行的服务部分,浏览名为安全中心的应用程序,在其中我们可以看到4个正在运行的服务,然后命名STOP服务 CONTROL_VERIFY_SERVICE(当然风险自负)。

  5. 就是这样,现在只需转到设置&gt;&gt; 高级设置&gt;&gt; 辅助功能,并为您的应用程序启用辅助功能并享受它。