fix: async MPV commands to prevent ANR

This commit is contained in:
edde746
2026-01-20 01:14:45 +01:00
parent e18a9457dd
commit 9721e6bf3f
12 changed files with 397 additions and 10 deletions
@@ -22,8 +22,10 @@ import android.view.TextureView
import android.view.WindowManager
import androidx.annotation.RequiresApi
import dev.jdtech.mpv.MPVLib
import io.flutter.plugin.common.MethodChannel
import java.math.BigDecimal
import java.math.RoundingMode
import java.util.concurrent.Executors
interface MpvPlayerDelegate {
fun onPropertyChange(name: String, value: Any?)
@@ -48,6 +50,9 @@ class MpvPlayerCore(private val activity: Activity) :
var isInitialized: Boolean = false
private set
// Executor for running MPV commands off the UI thread to prevent ANR
private val commandExecutor = Executors.newSingleThreadExecutor()
// Frame rate matching
private var currentVideoFps: Float = 0f
private var displayListener: DisplayManager.DisplayListener? = null
@@ -451,6 +456,32 @@ class MpvPlayerCore(private val activity: Activity) :
MPVLib.command(args)
}
/**
* Execute an MPV command asynchronously off the UI thread.
* This prevents ANR when commands like loadfile block waiting for network I/O.
* The result is called back on the UI thread when the command completes.
*/
fun commandAsync(args: Array<String>, result: MethodChannel.Result) {
if (!isInitialized || args.isEmpty()) {
result.success(null)
return
}
commandExecutor.execute {
try {
MPVLib.command(args)
activity.runOnUiThread {
result.success(null)
}
} catch (e: Exception) {
Log.e(TAG, "Async command failed: ${e.message}", e)
activity.runOnUiThread {
result.error("COMMAND_FAILED", e.message, null)
}
}
}
}
fun setVisible(visible: Boolean) {
activity.runOnUiThread {
surfaceView?.visibility = if (visible) View.VISIBLE else View.INVISIBLE
@@ -652,6 +683,9 @@ class MpvPlayerCore(private val activity: Activity) :
fun dispose() {
Log.d(TAG, "Disposing")
// Shutdown command executor
commandExecutor.shutdown()
// Clean up frame rate listener
clearVideoFrameRate()
@@ -190,8 +190,10 @@ class MpvPlayerPlugin : FlutterPlugin, MethodChannel.MethodCallHandler,
return
}
playerCore?.command(args.toTypedArray())
result.success(null)
// Use async command to prevent ANR - command executes off UI thread
// and result is called back when complete
playerCore?.commandAsync(args.toTypedArray(), result)
?: result.success(null)
}
private fun handleSetVisible(call: MethodCall, result: MethodChannel.Result) {