如何使用示例在 Android 中创建无障碍服务?
无障碍服务就像是 Android 框架提供的一根魔杖。尽管辅助功能服务的唯一目的是为不同能力的人提供访问其设备的便利,但它也可用于实现一些功能,以帮助任何用户进行日常电话使用。强烈建议您在继续阅读这篇文章之前,先阅读这篇 Android 中的无障碍服务文章。
1.创建服务类
首先创建一个常规类,使用 AccessibilityService 类扩展该类并覆盖必需的方法。无障碍服务既可以在常规项目中使用,也可以作为独立项目开发。
Java
/*package whatever //do not write package name here */
import android.accessibilityservice.AccessibilityService;
import android.view.accessibility.AccessibilityEvent;
public class MyService extends AccessibilityService {
...
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
}
@Override
public void onInterrupt() {
}
...
}
XML
XML
XML
...
Java
@Override
public void onServiceConnected() {
// pass the typeof events you want your service to listen to
// other will not be handledby thi service
info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED |
AccessibilityEvent.TYPE_VIEW_FOCUSED;
// In case you want your service to work only with a particular application
//or when that application is in foreground, you should specify those applications package
//names here, otherwise the service would listen events from all the applications
info.packageNames = new String[]
{"com.example.android.myFirstApp", "com.example.android.mySecondApp"};
// Set the type of feedback your service will provide.
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
// the notification timeout is the time interval after which the service would
// listen from the system. Anything happening between that interval won't be
// captured by the service
info.notificationTimeout = 100;
// finally set the serviceInfo
this.setServiceInfo(info);
}
XML
Java
import android.accessibilityservice.AccessibilityService;
import android.util.Log;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Toast;
public class MyService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
}
@Override
public void onInterrupt() {
}
@Override
protected boolean onKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
// the service listens for both pressing and releasing the key
// so the below code executes twice, i.e. you would encounter two Toasts
// in order to avoid this, we wrap the code inside an if statement
// which executes only when the key is released
if (action == KeyEvent.ACTION_UP) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
Log.d("Check", "KeyUp");
Toast.makeText(this, "KeyUp", Toast.LENGTH_SHORT).show();
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
Log.d("Check", "KeyDown");
Toast.makeText(this, "KeyDown", Toast.LENGTH_SHORT).show();
}
}
return super.onKeyEvent(event);
}
}
XML
Java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!checkAccessibilityPermission()){
Toast.makeText(MainActivity.this, "Permission denied", Toast.LENGTH_SHORT).show();
}
}
// method to check is the user has permitted the accessibility permission
// if not then prompt user to the system's Settings activity
public boolean checkAccessibilityPermission () {
int accessEnabled = 0;
try {
accessEnabled = Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (accessEnabled == 0) {
// if not construct intent to request permission
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// request permission via start activity for result
startActivity(intent);
return false;
} else {
return true;
}
}
}
2. 清单声明和权限
要被 Android 框架视为无障碍服务,提供无障碍服务的应用程序必须在其应用程序清单中包含特定声明。无障碍服务所需的权限与常规权限不同。像任何其他服务一样,我们需要在应用程序元素下的清单中声明它。为了将这项服务与其他常规服务区分开来,我们还必须包括无障碍服务意图过滤器。在服务内部,我们需要声明权限以确保只有系统可以绑定到它。服务中的标签属性是用户通过设备设置显式打开服务时出现的文本。这通常是您的应用程序名称或服务名称。
XML
3.无障碍服务配置
主要有两种配置服务的方法。
步骤 1:首先创建一个 XML 配置文件并声明和定义所有必需的属性。右键单击 res 文件夹,创建一个新的 android 资源目录 XML。现在在 XML 文件夹中创建accessibility_service_config.xml
XML
此代码定义了我们的应用程序可以响应的事件类型、应用程序可能提供的输入类型以及如果您希望应用程序仅管理特定应用程序产生的事件,该应用程序可以侦听的特定包,或在特定时间范围内获取事件、检索窗口内容等。在此方法中,我们必须通过在其中添加
XML
...
第 2 步:第二种是使用 onServiceConnected 方法中的 setServiceInfo(AccessibilityServiceInfo) 方法动态设置属性。
Java
@Override
public void onServiceConnected() {
// pass the typeof events you want your service to listen to
// other will not be handledby thi service
info.eventTypes = AccessibilityEvent.TYPE_VIEW_CLICKED |
AccessibilityEvent.TYPE_VIEW_FOCUSED;
// In case you want your service to work only with a particular application
//or when that application is in foreground, you should specify those applications package
//names here, otherwise the service would listen events from all the applications
info.packageNames = new String[]
{"com.example.android.myFirstApp", "com.example.android.mySecondApp"};
// Set the type of feedback your service will provide.
info.feedbackType = AccessibilityServiceInfo.FEEDBACK_SPOKEN;
// the notification timeout is the time interval after which the service would
// listen from the system. Anything happening between that interval won't be
// captured by the service
info.notificationTimeout = 100;
// finally set the serviceInfo
this.setServiceInfo(info);
}
现在,既然我们已经成功地实例化了 Accessibility 服务,让我们举一个例子来了解它的工作原理。
例子
在这个例子中,让我们创建一个服务来监听设备的按键事件,即当用户按下音量增大和减小键时,我们的服务将接收回调并执行任何特定任务。
第 1 步:创建一个新项目
要在 Android Studio 中创建新项目,请参阅如何在 Android Studio 中创建/启动新项目。请注意,选择Java作为编程语言。
第二步:创建accessibility_service_config.xml
创建一个新的布局资源文件并将该文件命名为accessibility_service_config。下面是accessibility_service_config.xml文件的代码。
XML
第 3 步:创建 MyService 类
在 Android Studio 中创建一个Java类,并将该类命名为MyService。下面是MyService的代码。 Java文件。
Java
import android.accessibilityservice.AccessibilityService;
import android.util.Log;
import android.view.KeyEvent;
import android.view.accessibility.AccessibilityEvent;
import android.widget.Toast;
public class MyService extends AccessibilityService {
@Override
public void onAccessibilityEvent(AccessibilityEvent accessibilityEvent) {
}
@Override
public void onInterrupt() {
}
@Override
protected boolean onKeyEvent(KeyEvent event) {
int action = event.getAction();
int keyCode = event.getKeyCode();
// the service listens for both pressing and releasing the key
// so the below code executes twice, i.e. you would encounter two Toasts
// in order to avoid this, we wrap the code inside an if statement
// which executes only when the key is released
if (action == KeyEvent.ACTION_UP) {
if (keyCode == KeyEvent.KEYCODE_VOLUME_UP) {
Log.d("Check", "KeyUp");
Toast.makeText(this, "KeyUp", Toast.LENGTH_SHORT).show();
} else if (keyCode == KeyEvent.KEYCODE_VOLUME_DOWN) {
Log.d("Check", "KeyDown");
Toast.makeText(this, "KeyDown", Toast.LENGTH_SHORT).show();
}
}
return super.onKeyEvent(event);
}
}
第 4 步:使用 AndroidManifest.xml 文件
下面是AndroidManifest.xml文件的代码。
XML
第 5 步:使用 MainActivity。 Java文件
转到主活动。 Java文件,参考如下代码。下面是MainActivity的代码。 Java文件。代码中添加了注释以更详细地理解代码。
Java
import androidx.appcompat.app.AppCompatActivity;
import android.content.Intent;
import android.os.Bundle;
import android.provider.Settings;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
if(!checkAccessibilityPermission()){
Toast.makeText(MainActivity.this, "Permission denied", Toast.LENGTH_SHORT).show();
}
}
// method to check is the user has permitted the accessibility permission
// if not then prompt user to the system's Settings activity
public boolean checkAccessibilityPermission () {
int accessEnabled = 0;
try {
accessEnabled = Settings.Secure.getInt(this.getContentResolver(), Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
if (accessEnabled == 0) {
// if not construct intent to request permission
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// request permission via start activity for result
startActivity(intent);
return false;
} else {
return true;
}
}
}