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

Android Studio中Kotlin悬浮窗应用实现背景应用暂停与恢复的方案咨询

Android Studio中Kotlin悬浮窗应用实现背景应用暂停与恢复的方案咨询

嘿,刚接触Kotlin就能搞定悬浮窗已经很厉害啦!你的需求我完全get到了,但得先给你划个重点:Android出于系统安全和用户体验的考虑,不允许第三方应用直接“冻结”其他应用的运行,不过针对你提到的YouTube、TikTok这类视频播放类应用,我们可以通过控制媒体播放的暂停与恢复来实现你想要的效果,下面给你几个切实可行的方案:

方案一:利用音频焦点自动控制媒体播放

这是最省心的方案,因为Android系统本身就有一套音频焦点管理机制——当你的应用请求音频焦点时,正在播放的媒体应用会自动暂停;当你释放焦点时,大部分主流应用都会自动恢复播放,完全不需要你挨个处理每个应用。

实现步骤:

  1. 先在你的悬浮窗Service或者Activity中初始化AudioManager:
private lateinit var audioManager: AudioManager

override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    audioManager = getSystemService(Context.AUDIO_SERVICE) as AudioManager
}
  1. 当悬浮窗弹出时,请求音频焦点:
// 定义音频焦点变化的监听器,可选:用来处理焦点被抢占的情况
private val audioFocusChangeListener = AudioManager.OnAudioFocusChangeListener { focusChange ->
    when(focusChange) {
        AudioManager.AUDIOFOCUS_LOSS -> {
            // 永久失去焦点时的逻辑,比如隐藏悬浮窗
        }
    }
}

// 悬浮窗显示时调用此方法
fun requestAudioFocus() {
    val result = audioManager.requestAudioFocus(
        audioFocusChangeListener,
        AudioManager.STREAM_MUSIC, // 针对媒体播放的音频流
        AudioManager.AUDIOFOCUS_GAIN_TRANSIENT_EXCLUSIVE // 临时独占焦点,正好匹配你的场景
    )
    if (result == AudioManager.AUDIOFOCUS_REQUEST_GRANTED) {
        // 焦点请求成功,此时正在播放的媒体应该已经自动暂停了
    }
}
  1. 当用户完成问题、悬浮窗关闭时,释放音频焦点:
// 悬浮窗消失时调用此方法
fun abandonAudioFocus() {
    audioManager.abandonAudioFocus(audioFocusChangeListener)
    // 释放焦点后,大部分主流媒体应用会自动恢复播放
}

方案二:主动控制活跃媒体会话(Android 8.0+)

如果遇到个别不响应音频焦点的顽固应用,你可以主动找到当前活跃的媒体会话,直接发送暂停/播放指令。不过要注意:这个方案对权限要求较高,普通第三方应用可能会受限。

实现步骤:

  1. 先在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.MEDIA_CONTROL" />

注意:MEDIA_CONTROL是系统级权限,Android 11+之后普通第三方应用很难直接获取,如果你做的是面向普通用户的应用,优先选方案一。

  1. 悬浮窗弹出时,发送暂停指令:
fun pauseActiveMedia() {
    val mediaSessionManager = getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager
    // 获取当前所有活跃的媒体会话
    val activeSessions = mediaSessionManager.activeSessions
    for (session in activeSessions) {
        // 给每个活跃会话发送暂停指令
        session.controller.transportControls.pause()
    }
}
  1. 悬浮窗关闭时,发送恢复指令:
fun resumeActiveMedia() {
    val mediaSessionManager = getSystemService(Context.MEDIA_SESSION_SERVICE) as MediaSessionManager
    val activeSessions = mediaSessionManager.activeSessions
    for (session in activeSessions) {
        // 给每个活跃会话发送播放指令
        session.controller.transportControls.play()
    }
}

方案三:针对特定应用精准控制

如果你只想暂停YouTube、TikTok这类指定应用,其他后台应用不受影响,可以用这个方案:先检测当前前台应用,再给目标应用发送模拟媒体按键事件。

实现步骤:

  1. 先在AndroidManifest.xml中添加权限:
<uses-permission android:name="android.permission.PACKAGE_USAGE_STATS"
    tools:ignore="ProtectedPermissions" />

这个权限无法通过动态申请获取,需要引导用户在设置>隐私>权限管理>使用情况访问权限中手动开启你的应用权限。

  1. 编写工具函数获取当前前台应用的包名:
fun getForegroundAppPackage(): String? {
    val usageStatsManager = getSystemService(Context.USAGE_STATS_SERVICE) as UsageStatsManager
    val now = System.currentTimeMillis()
    // 查询最近10秒内的应用使用记录
    val stats = usageStatsManager.queryUsageStats(
        UsageStatsManager.INTERVAL_DAILY,
        now - 10000,
        now
    )
    if (stats != null && stats.isNotEmpty()) {
        var recentStats: UsageStats? = null
        for (usageStat in stats) {
            if (recentStats == null || usageStat.lastTimeUsed > recentStats.lastTimeUsed) {
                recentStats = usageStat
            }
        }
        return recentStats?.packageName
    }
    return null
}
  1. 悬浮窗弹出时,判断并暂停目标应用:
fun pauseTargetApps() {
    val foregroundPackage = getForegroundAppPackage()
    // 这里填你要控制的应用包名,比如YouTube和TikTok
    val targetPackages = listOf("com.google.android.youtube", "com.zhiliaoapp.musically")
    if (targetPackages.contains(foregroundPackage)) {
        // 模拟媒体暂停按键的按下与抬起事件
        val pauseIntent = Intent(Intent.ACTION_MEDIA_BUTTON).apply {
            putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PAUSE))
        }
        sendBroadcast(pauseIntent)
        pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PAUSE))
        sendBroadcast(pauseIntent)
    }
}
  1. 悬浮窗关闭时,恢复目标应用播放:
fun resumeTargetApps() {
    val foregroundPackage = getForegroundAppPackage()
    val targetPackages = listOf("com.google.android.youtube", "com.zhiliaoapp.musically")
    if (targetPackages.contains(foregroundPackage)) {
        // 模拟媒体播放按键事件
        val playIntent = Intent(Intent.ACTION_MEDIA_BUTTON).apply {
            putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(KeyEvent.ACTION_DOWN, KeyEvent.KEYCODE_MEDIA_PLAY))
        }
        sendBroadcast(playIntent)
        playIntent.putExtra(Intent.EXTRA_KEY_EVENT, KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY))
        sendBroadcast(playIntent)
    }
}

给新手你的小提醒

  • 不同Android版本的权限规则差异很大,比如Android 12+对悬浮窗的权限要求更严格,一定要确保你已经申请了SYSTEM_ALERT_WINDOW权限
  • 不是所有应用都严格遵循媒体控制规范,小众应用可能无法自动恢复,你可以在测试中针对性调整
  • 作为Kotlin新手,建议先从方案一开始尝试,代码最少、适配性最好,等熟悉之后再尝试其他方案

内容来源于stack exchange

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.04.07 13:19:32