I’m developing a widget-only app that consists of a button that, when pressed, locks the device’s screen. For this I’m using accessibility features. However, the app doesn’t appear in the accessibility settings menu.
Here are some files from my app’s source code:
The service class:
public class PowerService extends AccessibilityService {
private void guaranteeAccessibilityService() {
Context context = this;
// Checks if accessibility permission is enabled
AccessibilityManager am = (AccessibilityManager) getSystemService(Context.ACCESSIBILITY_SERVICE);
List<AccessibilityServiceInfo> enabledServices = am.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_ALL_MASK);
for (AccessibilityServiceInfo service: enabledServices) {
ServiceInfo si = service.getResolveInfo().serviceInfo;
if (si.packageName.equals(context.getPackageName()) && si.name.equals(PowerService.class.getName())) {
System.out.println("App has accessibility permission");
return;
}
}
// Otherwise...
System.out.println("App does not have accessibility permission");
Intent i = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(i);
}
private void lock() {
performGlobalAction(AccessibilityService.GLOBAL_ACTION_LOCK_SCREEN);
}
private void powerMenu() {
performGlobalAction(AccessibilityService.GLOBAL_ACTION_POWER_DIALOG);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int cmd = intent.getIntExtra("cmd", -1);
switch (cmd) {
case 0:
lock();
break;
case 1:
powerMenu();
break;
default:
System.out.println("No command was passed!");
}
return AccessibilityService.START_STICKY;
}
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
@Override
public void onCreate() {
super.onCreate();
System.out.println("Serviço criado!");
guaranteeAccessibilityService();
}
}
The widget class
public class Lock extends AppWidgetProvider {
public static final String ACTION_WIDGET_CLICKED = "ActionWidgetClicked";
private void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.lock);
Intent intent = new Intent(context, getClass());
intent.setAction(ACTION_WIDGET_CLICKED);
PendingIntent pIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_IMMUTABLE);
views.setOnClickPendingIntent(R.id.buttonLock, pIntent);
appWidgetManager.updateAppWidget(appWidgetId, views);
}
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId);
}
}
@Override
public void onReceive(Context context, Intent intent) {
if (ACTION_WIDGET_CLICKED.equals(intent.getAction())) {
System.out.println("Widget button clicked!");
Intent i = new Intent(context, PowerService.class);
i.putExtra("cmd", 0); // PowerService.powerOff()
context.startForegroundService(i);
}
super.onReceive(context, intent);
}
@Override
public void onEnabled(Context context) {
System.out.println("Widget created!");
}
}
The AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.lock.button"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="false"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/button_lock"
android:label="@string/app_name"
android:roundIcon="@mipmap/lock_button_round"
android:supportsRtl="true"
android:theme="@style/Theme.LockButton">
<receiver
android:name=".Lock"
android:exported="true">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name=".Lock.ACTION_WIDGET_CLICKED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/lock_info" />
</receiver>
<service
android:name="PowerService"
android:exported="false"
android:label="@string/app_name"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
<intent-filter>
<action android:name="android.accessibilityservice.AcessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/power_service_config" />
</service>
</application>
</manifest>
The power_service_config.xml
<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:packageNames="com.lock.button"
android:accessibilityEventTypes="typeAllMask"
android:accessibilityFlags="flagRequestFilterKeyEvents"
android:accessibilityFeedbackType="feedbackSpoken"
android:notificationTimeout="100"
/>
I followed exactly all the tutorials I found on the internet, especially regarding the AndroidManifest.xml
and power_service_config.xml
files, but my app does not appear in the accessibility menu. However, I compiled other similar projects that I found on GitHub with the AndroidManifest.xml
and the equivalent power_service_config.xml
files very similar to my project, and the app appeared in the accessibility menu.
You need to sign in to view this answers