1
0
mirror of https://github.com/godotengine/godot.git synced 2025-11-04 12:00:25 +00:00

Android: Run clipboard tasks on UI thread

Fixes crashes on older Android versions (API level <= 27) by ensuring
that all clipboard operations are executed on the UI thread.
This commit is contained in:
Anish Mishra
2025-07-20 18:52:18 +05:30
parent 71a9948157
commit 67b45299c7

View File

@@ -38,7 +38,6 @@ import android.content.pm.PackageManager
import android.content.res.Configuration import android.content.res.Configuration
import android.content.res.Resources import android.content.res.Resources
import android.graphics.Color import android.graphics.Color
import android.graphics.Rect
import android.hardware.Sensor import android.hardware.Sensor
import android.hardware.SensorManager import android.hardware.SensorManager
import android.os.* import android.os.*
@@ -79,6 +78,8 @@ import java.io.FileInputStream
import java.io.InputStream import java.io.InputStream
import java.security.MessageDigest import java.security.MessageDigest
import java.util.* import java.util.*
import java.util.concurrent.Callable
import java.util.concurrent.FutureTask
import java.util.concurrent.atomic.AtomicBoolean import java.util.concurrent.atomic.AtomicBoolean
import java.util.concurrent.atomic.AtomicReference import java.util.concurrent.atomic.AtomicReference
@@ -136,6 +137,16 @@ class Godot private constructor(val context: Context) {
val netUtils = GodotNetUtils(context) val netUtils = GodotNetUtils(context)
private val godotInputHandler = GodotInputHandler(context, this) private val godotInputHandler = GodotInputHandler(context, this)
private val hasClipboardCallable = Callable {
mClipboard?.hasPrimaryClip() == true
}
private val getClipboardCallable = Callable {
val clipData = mClipboard?.primaryClip
val text = clipData?.getItemAt(0)?.text
text?.toString() ?: ""
}
/** /**
* Task to run when the engine terminates. * Task to run when the engine terminates.
*/ */
@@ -934,19 +945,31 @@ class Godot private constructor(val context: Context) {
@Keep @Keep
fun hasClipboard(): Boolean { fun hasClipboard(): Boolean {
return mClipboard?.hasPrimaryClip() == true return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P || Looper.getMainLooper().thread == Thread.currentThread()) {
hasClipboardCallable.call()
} else {
val task = FutureTask(hasClipboardCallable)
runOnHostThread(task)
task.get()
}
} }
@Keep @Keep
fun getClipboard(): String { fun getClipboard(): String {
val clipData = mClipboard?.primaryClip ?: return "" return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.P || Looper.getMainLooper().thread == Thread.currentThread()) {
val text = clipData.getItemAt(0).text ?: return "" getClipboardCallable.call()
return text.toString() } else {
val task = FutureTask(getClipboardCallable)
runOnHostThread(task)
task.get()
}
} }
@Keep @Keep
fun setClipboard(text: String?) { fun setClipboard(text: String?) {
mClipboard?.setPrimaryClip(ClipData.newPlainText("myLabel", text)) runOnHostThread {
mClipboard?.setPrimaryClip(ClipData.newPlainText("myLabel", text))
}
} }
@Keep @Keep