2016-05-30 96 views
1

我已經開發了一種基於無障礙服務的Android應用程序。但是我有一個問題,我在互聯網上找不到任何幫助。當我安裝任何設備上的應用,顯然它不會開始工作,直到:輔助服務不斷得到禁用

  1. 我去輔助功能設置
  2. 找到它的輔助服務
  3. 進入並推開關打開服務

問題有點複雜: 啓用無障礙服務後,我可以在輔助功能設置屏幕中看到該服務顯示「已啓用」。實際上應用程序正在工作。但是如果我進入服務,頂部和右側有一個開關,顯示爲OFF。爲什麼?沒有任何意義,該服務已啓用並正常工作,並且該開關顯示爲OFF。

我曾嘗試與另一服務對講自帶內置。當我打開開關,返回到輔助功能設置屏幕,然後再次進入對講服務,開關保持ON狀態。爲什麼它不適合我的服務?

我再次解釋說,雖然激活開關不爲我服務的正常工作,我的應用程序確實工作,唯一的問題是,交換機,它混淆了炫耀的用戶時,我的服務已經打開。

有什麼緣由,這可能發生?也許我錯過了什麼時候告訴系統何時啓用服務或類似的東西?

我服務的代碼有什麼不尋常的,類似於除了我的自定義操作的任何其他輔助服務時,事件出現。

這裏是應用程序的清單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); 
      } 
     } 
    } 
} 

我很抱歉代碼的評論是用西班牙文寫的。那是因爲它是我的母語。

+0

請張貼您的代碼。 – Lampard

+0

我已經發布了我的代碼。你認爲它錯過了什麼?我通過Android Developers網站上的示例構建了它。 – user3289695

回答

0

它發生在我Greenify上小蜜紅米手機附註3(棉花糖),

我做 :

Settings->apps setting->permissions-> autostart

,並允許Greenify。它爲我工作。

0

在我的情況下,OPPO F1S,我發現了一個解決方案 首先設備要紮根的,最好的 辦法做到這一點是通過重置固件工廠或更新到新OPPO系統映像,然後安裝自定義恢復BIOS或任何它的名字, 然後生根恢復模式下使用Magisc ... 所有這一切都在一些xda-developers論壇主題中描述。 但是這不是我們現在的問題, 爲了防止從我們的服務或應用程序中撤消對可訪問性許可的禁止,我們必須瀏覽設置>>設備信息,然後在BUIL NUMBER上單擊約8次或更多來開發開發人員, ...現在我們 已經變成DEVELOPPER好,我們回去然後 我們導航到設置>>高級設置>>開發者設置...然後啓用開發者選項,打開部分運行服務,瀏覽名爲安全中心的應用程序,我們可以看到4個正在運行的服務,然後停止服務名爲 CONTROL_VERIFY_SERVICE(當然,您自己承擔風險) ,就是這樣,現在只需進入設置>>設置>>可訪問性,併爲您的應用程序啓用輔助功能,並享受它.....

+0

這看起來像一個堅實的答案,但它可以使用一些格式(編號的步驟或項目符號等) – C8H10N4O2