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);
    }

}
  1. 实现了 AccessibilityService,并在 onAccessibilityEvent 方法中监听 TYPE_WINDOW_STATE_CHANGED 事件。
    提取事件中的包名和类名,并通过 Log.d 打印到日志中
  2. 在 onServiceConnected 方法中调用 startForegroundService,将服务绑定为前台服务。使用 Notification 提示用户服务正在运行,避免被系统回收。
  3. 增加 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

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值