You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何通过BroadcastReceiver监听应用启动的Broadcast Intent?

解决Android检测应用启动的问题

你当前的配置完全错误,android.intent.category.LAUNCHER是用于标记应用入口Activity的,和广播接收无关。而且Android早已废弃了通过静态注册广播监听应用启动的方式,API 21及以上系统不再支持这类广播的静态接收,即使动态注册也会因为后台限制导致不可靠。

下面是两种目前可行的实现方案:

方案一:使用UsageStatsManager(需用户授权)

该方案通过系统提供的应用使用统计服务,查询最近活跃的应用,需要用户授予"查看应用使用情况"权限。

1. 配置权限

在AndroidManifest.xml中添加权限:

<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS" 
    tools:ignore="ProtectedPermissions" />

2. 检查并引导开启权限

// 检查是否已获取权限
fun checkUsageStatsPermission(context: Context): Boolean {
    val appOps = context.getSystemService(Context.APP_OPS_SERVICE) as AppOpsManager
    val mode = appOps.checkOpNoThrow(AppOpsManager.OPSTR_GET_USAGE_STATS,
        android.os.Process.myUid(), context.packageName)
    return mode == AppOpsManager.MODE_ALLOWED
}

// 跳转到权限设置页面
fun openUsageStatsSettings(context: Context) {
    val intent = Intent(Settings.ACTION_USAGE_ACCESS_SETTINGS)
    context.startActivity(intent)
}

3. 查询当前活跃应用并监听

通过定时轮询获取当前最活跃的应用包名,判断是否是目标应用:

// 获取当前前台应用包名
fun getTopAppPackageName(context: Context): String? {
    val usageStatsManager = context.getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
    val endTime = System.currentTimeMillis()
    val startTime = endTime - 1000 * 60 * 10 // 查询最近10分钟的使用记录
    val usageStatsList = usageStatsManager.queryUsageStats(
        UsageStatsManager.INTERVAL_BEST, startTime, endTime
    )
    if (usageStatsList.isEmpty()) return null

    return usageStatsList.maxByOrNull { it.lastTimeUsed }?.packageName
}

// 启动轮询检测
private val handler = Handler(Looper.getMainLooper())
private val checkRunnable = object : Runnable {
    override fun run() {
        val topPackage = getTopAppPackageName(applicationContext)
        if ("com.example.targetapp" == topPackage) {
            // 触发提醒逻辑,比如显示通知
            showNotification(applicationContext)
        }
        handler.postDelayed(this, 2000) // 每2秒检查一次
    }
}

// 开始检测
handler.post(checkRunnable)
// 停止检测
// handler.removeCallbacks(checkRunnable)

方案二:使用AccessibilityService(无障碍服务,需用户授权)

该方案通过无障碍服务监听窗口状态变化,当目标应用启动时会触发事件,可靠性更高,但需要用户开启无障碍权限。

1. 创建无障碍服务类

class AppLaunchDetectionService : AccessibilityService() {
    override fun onAccessibilityEvent(event: AccessibilityEvent?) {
        // 监听窗口状态变化事件
        if (event?.eventType == AccessibilityEvent.TYPE_WINDOW_STATE_CHANGED) {
            val targetPackage = "com.example.targetapp"
            val currentPackage = event.packageName?.toString()
            if (targetPackage == currentPackage) {
                // 触发提醒逻辑
                showNotification(this)
            }
        }
    }

    override fun onInterrupt() {
        // 服务中断时的处理
    }
}

2. 在Manifest中配置服务

<service
    android:name=".AppLaunchDetectionService"
    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/accessibility_config" />
</service>

3. 创建无障碍服务配置文件

在res/xml目录下创建accessibility_config.xml:

<?xml version="1.0" encoding="utf-8"?>
<accessibility-service xmlns:android="http://schemas.android.com/apk/res/android"
    android:accessibilityEventTypes="typeWindowStateChanged"
    android:accessibilityFeedbackType="feedbackGeneric"
    android:accessibilityFlags="flagDefault"
    android:canRetrieveWindowContent="true"
    android:description="@string/accessibility_service_desc" />

在strings.xml中添加服务描述:

<string name="accessibility_service_desc">检测目标应用启动,为您提供提醒服务</string>

4. 检查并引导开启无障碍权限

// 检查无障碍权限是否开启
fun checkAccessibilityPermission(context: Context): Boolean {
    val accessibilityManager = context.getSystemService(Context.ACCESSIBILITY_SERVICE) as AccessibilityManager
    val enabledServices = accessibilityManager.getEnabledAccessibilityServiceList(AccessibilityServiceInfo.FEEDBACK_GENERIC)
    return enabledServices.any { it.id.contains(context.packageName) }
}

// 跳转到无障碍设置页面
fun openAccessibilitySettings(context: Context) {
    val intent = Intent(Settings.ACTION_ACCESSIBILITY_SETTINGS)
    context.startActivity(intent)
}

注意事项

  • 两种方案都需要用户手动授权,无法自动获取
  • UsageStatsManager的轮询间隔可以根据需求调整,过短会增加功耗
  • 无障碍服务会被系统视为敏感权限,应用上架时需要说明用途

内容的提问来源于stack exchange,提问作者Owlon

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.25 05:20:35