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

Android Visualizer类引发FORTIFY互斥锁崩溃问题求助

问题分析与解决方案

从崩溃栈可以明确,这是Visualizer内部捕获线程尝试对已销毁的互斥量执行锁操作导致的SIGABRT崩溃,通常出现在Visualizer实例资源未正确释放、生命周期管理混乱的场景下,尤其在Android 9(SDK28)的部分设备上更容易触发。

核心解决方案

1. 严格遵循Visualizer的生命周期管理

必须在组件(如Activity/Fragment)的销毁阶段,按顺序释放Visualizer资源,避免内部线程残留:

  • 先移除数据捕获监听器
  • 禁用Visualizer
  • 最后调用release()释放底层资源

2. 避免强制非空操作,改用安全调用

原代码中的!!会掩盖空指针风险,同时可能导致资源未被正确清理,改用?.安全调用更稳妥。

3. 确保UI操作在主线程执行

Visualizer的回调方法运行在子线程,直接更新UI可能引发线程安全问题,需通过view.post或runOnUiThread切换到主线程。

修改后的代码示例

// 声明为类成员变量
private var visualizer: Visualizer? = null

// 初始化Visualizer的方法
fun initVisualizer(audioSessionId: Int) {
    visualizer = Visualizer(audioSessionId).apply {
        enabled = false
        captureSize = Visualizer.getCaptureSizeRange()[1]
        setDataCaptureListener(object : Visualizer.OnDataCaptureListener {
            override fun onWaveFormDataCapture(
                visualizer: Visualizer, bytes: ByteArray,
                samplingRate: Int
            ) {
                val number = 128 - (if (bytes[0] < 0) -bytes[0] else bytes[0]).toInt()
                val result = (number.toFloat() / 128) * 100
                val progress = 100f - result

                // 切换到主线程更新UI
                volumeBoosterFragment?.view?.post {
                    volumeBoosterFragment?.binding?.animSeekbar?.setProgress(progress)
                    volumeBoosterFragment?.binding?.animSeekbar2?.setProgress(progress)
                }
                equalizerFragment?.view?.post {
                    equalizerFragment?.binding?.animSeekbar?.setProgress(progress)
                    equalizerFragment?.binding?.animSeekbar2?.setProgress(progress)
                }
            }

            override fun onFftDataCapture(
                visualizer: Visualizer, bytes: ByteArray,
                samplingRate: Int
            ) {
            }
        }, Visualizer.getMaxCaptureRate() / 2, true, false)
        enabled = true // 最后启用,确保监听器已设置完成
    }
}

// 在组件销毁时调用的清理方法
fun releaseVisualizer() {
    visualizer?.let {
        it.setDataCaptureListener(null, 0, false, false) // 移除监听器
        it.enabled = false
        it.release() // 释放底层资源
    }
    visualizer = null // 置空避免后续误操作
}

额外注意事项

  • 在Fragment的onDestroyView或Activity的onDestroy中调用releaseVisualizer()
  • 若应用在后台仍需运行,需确保Visualizer在后台时被正确禁用,避免资源泄漏
  • 针对Android 9设备,可额外添加try-catch包裹Visualizer的初始化与释放逻辑,防止系统底层异常扩散

内容的提问来源于stack exchange,提问作者Abubakar Saddique Butt Hazel

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.18 03:52:41