当前位置: 首页 > 知识库问答 >
问题:

Android中的易访问性服务一直处于禁用状态

龙景澄
2023-03-14

我开发了一个基于可访问性服务的Android应用程序。但是我有个问题,我在网上找不到任何帮助。当我在任何设备上安装应用程序时,很明显,它直到:

  1. 我去无障碍设置
  2. 查找其无障碍服务
  3. 进入并按下开关打开服务

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

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

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

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

我的服务代码没有什么不寻常的,类似于任何其他可访问性服务,除了事件发生时的自定义操作。

下面是应用程序的清单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个答案

孔礼骞
2023-03-14

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

>

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

    为了防止从我们的服务或应用程序中撤销可访问性权限,我们必须通过浏览设置转到开发人员选项

    现在,当我们永远成为一名开发人员时,我们回到过去,然后导航到设置

    打开Running Services部分,浏览名为Security Center的应用程序,在其中我们可以看到4个正在运行的服务,然后停止名为CONTROL\u VERIFY\u service的服务(当然风险由您自己承担)。

    就是这样,现在只需进入设置

  • 林炫明
    2023-03-14

    这发生在我身上,小米红米纸条3(Marshmallow)上的Greenify,

    我做到了:

    设置

    ,并允许绿色化。这对我有用。

     类似资料:
    • 我已经为我的应用程序编写了自己的。在内部,它使用为通过我的应用导航的用户提供语音反馈。当打开和时,我从我的应用程序中获得口头反馈,然后是TalkBack的反馈。 有什么方法可以停止TalkBack为我的应用程序,因为我拥有我的应用程序的可访问性服务?

    • 我想以编程方式启用/禁用设置->辅助功能选项下列出的辅助功能服务。 我可以像下面这样开始可访问性意图: 但是对于如何通过我的代码启用视图中列出的服务,我没有任何想法。 请把你的观点告诉我。

    • 我的密码是 有什么办法解决这个问题吗

    • 到目前为止,我能找到的唯一解决办法是在发送数据后总是断开与服务器端的连接,并且在我的代码中,将整个包装在一个循环中,类似于 以便在服务器发送一些数据并断开客户端连接后立即启动新的连接。

    • 我正在开发缓存清理应用程序,在谷歌上做了研究后,我发现Android系统已经将“Clear_App_Cache”权限移到了“签名,特权”状态。所以我无法用方法清除缓存。 谷歌playstore上的应用程序,如CCleaner、Power Clean等。正在使用辅助功能服务删除缓存。 我也为我的应用程序创建了基本的可访问性服务,但不知道如何删除应用程序的缓存

    • 我正在开发一个运行辅助功能服务的Android应用程序。我在AndroidStudio中开发了服务java类和配置xml文件,将其作为本机应用程序进行测试。当我运行它时,辅助功能服务会按预期显示在Android辅助功能设置中,我可以启用它。 然而,我想把这项服务集成在Qt快速Android应用程序中。当我添加相同的java类、清单和配置xml文件时,项目编译并运行良好,但服务不会出现在Androi