У меня есть сервис специальных возможностей, который я использую для отслеживания использования некоторых приложений и информирования пользователей. Все работало нормально. Не уверен, вдруг моя служба доступности перестала работать. Это даже не начало. Разрешение предоставлено. Но служба все равно не запускается.
в файле манифеста
<service android:name=".Services.AutoStartReceiverService" android:enabled="true"></service>
<service
android:name=".Services.WindowChangeDetectingService"
android:label="@string/accessibility_service_name"
android:enabled="true"
android:exported="false"
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/accessibilityservice" />
</service>
Код услуги доступности:
public class WindowChangeDetectingService extends AccessibilityService {
private static final String TAG = "APPCHANGESERV";
private SharedPreferences sharedpreferences;
@Override
protected void onServiceConnected() {
super.onServiceConnected();
//Configure these here for compatibility with API 13 and below.
AccessibilityServiceInfo config = new AccessibilityServiceInfo();
config.eventTypes = AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED;
config.feedbackType = AccessibilityServiceInfo.FEEDBACK_GENERIC;
if (Build.VERSION.SDK_INT >= 16)
//Just in case this helps
config.flags = AccessibilityServiceInfo.FLAG_INCLUDE_NOT_IMPORTANT_VIEWS;
setServiceInfo(config);
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
if (event.getPackageName() != null && event.getClassName() != null) {
ComponentName componentName = new ComponentName(
event.getPackageName().toString(),
event.getClassName().toString()
);
ActivityInfo activityInfo = tryGetActivity(componentName);
boolean isActivity = activityInfo != null;
ApplicationInfo applicationInfo = null;
ApplicationInfo savedApplicationInfo = null;
sharedpreferences = getSharedPreferences("virtual_virus", Context.MODE_PRIVATE);
if (isActivity) {
try {
applicationInfo = (getPackageManager().getApplicationInfo(componentName.getPackageName(), 0));
savedApplicationInfo = (getPackageManager().getApplicationInfo(sharedpreferences.getString("packageName", ""), 0));
} catch (PackageManager.NameNotFoundException e) {
e.printStackTrace();
}
if ((activityInfo.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
Log.i(TAG, "system");
} else {
SharedPreferences.Editor editor = sharedpreferences.edit();
// For Closing
Utlis.clearAllNotification(getApplicationContext());
if (savedApplicationInfo != null) {
AppInfo.updateAppInfo(sharedpreferences.getString("packageName", ""), new Date(), false, savedApplicationInfo.category);
}
// For Opening
if (activityInfo != null) {
if (applicationInfo.category == ApplicationInfo.CATEGORY_VIDEO || applicationInfo.category == ApplicationInfo.CATEGORY_SOCIAL || applicationInfo.category == ApplicationInfo.CATEGORY_GAME) {
AppInfo.updateAppInfo(componentName.getPackageName(), new Date(), true, applicationInfo.category);
AppLimit appLimit = AppLimit.getAppLimit(componentName.getPackageName());
if (appLimit.getLimit() > 0) {
AppInfo obj = AppInfo.getAppInfoByDateAndPackage(componentName.getPackageName(), new Date());
Log.v(TAG, "obj.getAppUsage(): " + obj.getAppUsage());
if ((appLimit.getLimit() * 60 * 1000) - obj.getAppUsage() > 0) {
Utlis.scheduleNotification(getApplicationContext(), Utlis.getNotification(getApplicationContext(), componentName.getPackageName()), (int) Math.abs((appLimit.getLimit() * 60 * 1000) - obj.getAppUsage()));
}
}
// else {
// Utlis.scheduleNotification(getApplicationContext(), Utlis.getNotification(getApplicationContext(), componentName.getPackageName()), 1000);
// }
}
}
editor.putString("packageName", componentName.getPackageName());
editor.commit();
Log.i(TAG, componentName.getPackageName() + " " + ApplicationInfo.FLAG_IS_GAME);
}
}
}
}
}
private ActivityInfo tryGetActivity(ComponentName componentName) {
try {
return getPackageManager().getActivityInfo(componentName, 0);
} catch (PackageManager.NameNotFoundException e) {
return null;
}
}
@Override
public void onInterrupt() {
}
}
в строковом файле:
<string name="accessibility_service_name">@string/app_name</string>
<string name="accessibility_service_description">ভার্চুয়াল অ্যান্টিভাইরাস er je karone ei permission ti dorkar</string>
XML-файл службы доступа:
<?xml version="1.0" encoding="utf-8"?><!-- These options MUST be specified here in order for the events to be received on first
start in Android 4.1.1 -->
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:accessibilityFlags="flagIncludeNotImportantViews"
android:description="@string/accessibility_service_description"
tools:ignore="UnusedAttribute" />
я получаю разрешение на доступ к моей основной деятельности, например:
accessPermissionButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent intent = new Intent(android.provider.Settings.ACTION_ACCESSIBILITY_SETTINGS);
startActivityForResult(intent, 0);
}
});
И заметил, что он отлично работает на симуляторе.