Android监测顶层包名+类名
Android 监测顶层包名+类名
本文主要介绍下通过辅助功能来实现android 中实时监测顶层包名类名.
1: 检测应用是否开启辅助功能
通过读取系统设置中的 ACCESSIBILITY_ENABLED 和 ENABLED_ACCESSIBILITY_SERVICES 来判断当前服务是否已启用.
/**
* 检查辅助功能是否已启用
*/
private boolean isAccessibilityServiceEnabled(Context context) {
int accessibilityEnabled = 0;
try {
accessibilityEnabled = Settings.Secure.getInt(
context.getContentResolver(),
android.provider.Settings.Secure.ACCESSIBILITY_ENABLED);
} catch (Settings.SettingNotFoundException e) {
Log.e(TAG, "Error finding accessibility setting: " + e.getMessage());
}
if (accessibilityEnabled == 1) {
String services = Settings.Secure.getString(
context.getContentResolver(),
Settings.Secure.ENABLED_ACCESSIBILITY_SERVICES);
if (services != null) {
Log.d(TAG, "Enabled services: " + services);
return services.contains(context.getPackageName() + "/" + MyAccessibilityService.class.getName());
}
}
return false;
}
2: 跳转到辅助功能设置页面
使用 Intent 跳转到系统辅助功能设置页面, 添加 FLAG_ACTIVITY_NEW_TASK 标志以确保可以从服务中启动 Activity.
注意权限声明:确保在 AndroidManifest.xml 中已声明 BIND_ACCESSIBILITY_SERVICE 权限
/**
* 跳转到辅助功能设置页面
*/
private void openAccessibilitySettings() {
Intent intent = new Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startActivity(intent);
}
3: 实现MyAccessibilityService类
package com.example.topclass;
import android.accessibilityservice.AccessibilityService;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.os.Build;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.accessibility.AccessibilityEvent;
import androidx.annotation.RequiresApi;
/**
* @Author: zh
* @Time: 24-12-12.
* @Describe: 辅助功能监测顶层包名
*/
public class MyAccessibilityService extends AccessibilityService {
private static final String TAG = "MyAccessibilityService";
private static final String CHANNEL_ID = "AccessibilityServiceChannel";
private Handler handler = new Handler(Looper.getMainLooper());
private Runnable heartbeatRunnable;
@Override
public void onAccessibilityEvent(AccessibilityEvent event) {
// 检查事件类型是否为窗口状态变化
if (event.getEventType() == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
// 获取当前顶层页面的包名
String packageName = event.getPackageName().toString();
// 获取当前顶层页面的类名
String className = event.getClassName().toString();
// 打印包名和类名
Log.d(TAG, "Top Activity: PackageName=" + packageName + ", ClassName=" + className);
}
}
@Override
public void onInterrupt() {
// 当服务被中断时调用
Log.d(TAG, "Accessibility service interrupted");
}
@Override
protected void onServiceConnected() {
super.onServiceConnected();
// 提升服务优先级,绑定前台服务
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
startForegroundService();
// 启动心跳机制,每1s发送一次通知
heartbeatRunnable = new Runnable() {
@Override
public void run() {
// 增强日志记录,确保服务状态可见
Log.d(TAG, "Heartbeat: Service is active. Thread ID: " + Thread.currentThread().getId());
handler.postDelayed(this, 1000); // 每1s执行一次
}
};
handler.post(heartbeatRunnable);
}
}
@Override
public void onDestroy() {
super.onDestroy();
// 停止心跳机制
if (heartbeatRunnable != null) {
handler.removeCallbacks(heartbeatRunnable);
}
// 增加详细日志记录,确保资源释放过程被记录
Log.d(TAG, "Service destroyed. Resources cleaned up. Thread ID: " + Thread.currentThread().getId());
}
/**
* 绑定前台服务,提升优先级
*/
@RequiresApi(api = Build.VERSION_CODES.O)
private void startForegroundService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
NotificationChannel channel = new NotificationChannel(
CHANNEL_ID,
"Accessibility Service",
NotificationManager.IMPORTANCE_HIGH
);
NotificationManager manager = getSystemService(NotificationManager.class);
manager.createNotificationChannel(channel);
}
Notification notification = new Notification.Builder(this, CHANNEL_ID)
.setContentTitle("Accessibility Service Running")
.setContentText("Listening for page changes...")
.setSmallIcon(R.drawable.ic_launcher_background)
.setPriority(Notification.PRIORITY_HIGH)
.build();
startForeground(999, notification);
}
}
- 实现了 AccessibilityService,并在 onAccessibilityEvent 方法中监听 TYPE_WINDOW_STATE_CHANGED 事件。
提取事件中的包名和类名,并通过 Log.d 打印到日志中 - 在 onServiceConnected 方法中调用 startForegroundService,将服务绑定为前台服务。使用 Notification 提示用户服务正在运行,避免被系统回收。
- 增加 android.permission.FOREGROUND_SERVICE权限, 避免启动前台服务时抛出 java.lang.SecurityException 异常.
4: 声明 AccessibilityService
AndroidManifest.xml文件中声明AccessibilityService.并配置了必要的权限和元数据.
<!-- 声明 AccessibilityService -->
<service
android:name=".MyAccessibilityService"
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE"
android:exported="false">
<intent-filter>
<action android:name="android.accessibilityservice.AccessibilityService" />
</intent-filter>
<meta-data
android:name="android.accessibilityservice"
android:resource="@xml/accessibility_service_config" />
</service>
5: 编写accessibility_service_config
编写accessibility_service_config, 配置服务的事件类型和反馈类型,确保能够监听窗口状态变化.
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
android:accessibilityEventTypes="typeWindowStateChanged"
android:accessibilityFeedbackType="feedbackGeneric"
android:canRetrieveWindowContent="true"
android:description="@string/accessibility_service_description"
android:notificationTimeout="100" />
6: 添加字符串资源
<string name="accessibility_service_description">This service listens to page changes and logs the top activity.</string>
7: 输出如下
2024-12-12 15:41:37.190 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:39.135 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:39.136 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.android.contacts, ClassName=android.widget.FrameLayout
2024-12-12 15:41:39.136 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.android.contacts, ClassName=com.android.dialer.BBKTwelveKeyDialer
2024-12-12 15:41:39.171 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.android.contacts, ClassName=com.android.dialer.BBKTwelveKeyDialer
2024-12-12 15:41:39.274 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.bbk.launcher2, ClassName=com.bbk.launcher2.Launcher
2024-12-12 15:41:40.153 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:40.247 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.bbk.launcher2, ClassName=com.bbk.launcher2.Launcher
2024-12-12 15:41:41.163 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:42.171 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:43.965 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:44.019 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.android.mms, ClassName=android.widget.FrameLayout
2024-12-12 15:41:44.019 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.android.mms, ClassName=com.android.mms.ui.ConversationList
2024-12-12 15:41:44.023 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.android.mms, ClassName=com.android.mms.ui.ConversationList
2024-12-12 15:41:44.125 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.bbk.launcher2, ClassName=com.bbk.launcher2.Launcher
2024-12-12 15:41:44.970 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:45.023 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.bbk.launcher2, ClassName=com.bbk.launcher2.Launcher
2024-12-12 15:41:46.562 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:46.596 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.tencent.mm, ClassName=com.tencent.mm.ui.LauncherUI
2024-12-12 15:41:46.596 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.tencent.mm, ClassName=com.tencent.mm.plugin.account.ui.LoginPasswordUI
2024-12-12 15:41:46.730 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.bbk.launcher2, ClassName=com.bbk.launcher2.Launcher
2024-12-12 15:41:47.569 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:47.806 7064-7064/com.example.topclass D/MyAccessibilityService: Top Activity: PackageName=com.bbk.launcher2, ClassName=com.bbk.launcher2.Launcher
2024-12-12 15:41:48.578 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2
2024-12-12 15:41:49.586 7064-7064/com.example.topclass D/MyAccessibilityService: Heartbeat: Service is active. Thread ID: 2