diff --git a/android/app/build.gradle b/android/app/build.gradle index fb171d5cd..fe3ff4de2 100644 --- a/android/app/build.gradle +++ b/android/app/build.gradle @@ -97,8 +97,9 @@ repositories { dependencies { implementation "org.jetbrains.kotlin:kotlin-stdlib-jdk7:$kotlin_version" + implementation 'org.jetbrains.kotlinx:kotlinx-coroutines-android:1.3.9' implementation 'androidx.core:core-ktx:1.5.0-alpha04' // v1.5.0-alpha02+ for ShortcutManagerCompat.setDynamicShortcuts - implementation "androidx.exifinterface:exifinterface:1.3.1" + implementation 'androidx.exifinterface:exifinterface:1.3.1' implementation 'com.commonsware.cwac:document:0.4.1' implementation 'com.drewnoakes:metadata-extractor:2.15.0' implementation 'com.github.bumptech.glide:glide:4.11.0' diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt index d8dcc7243..fd747194e 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppAdapterHandler.kt @@ -17,6 +17,8 @@ import deckers.thibault.aves.utils.LogUtils.createTag import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import java.io.ByteArrayOutputStream import java.io.File import java.util.* @@ -26,8 +28,8 @@ import kotlin.math.roundToInt class AppAdapterHandler(private val context: Context) : MethodCallHandler { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { when (call.method) { - "getAppIcon" -> Thread { getAppIcon(call, MethodResultWrapper(result)) }.start() - "getAppNames" -> Thread { getAppNames(MethodResultWrapper(result)) }.start() + "getAppIcon" -> GlobalScope.launch { getAppIcon(call, Coresult(result)) } + "getAppNames" -> GlobalScope.launch { getAppNames(Coresult(result)) } "getEnv" -> result.success(System.getenv()) "edit" -> { val title = call.argument("title") diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppShortcutHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppShortcutHandler.kt index 5766f7579..434528333 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppShortcutHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/AppShortcutHandler.kt @@ -3,7 +3,6 @@ package deckers.thibault.aves.channel.calls import android.content.Context import android.content.Intent import android.graphics.BitmapFactory -import android.text.TextUtils import androidx.core.content.pm.ShortcutInfoCompat import androidx.core.content.pm.ShortcutManagerCompat import androidx.core.graphics.drawable.IconCompat @@ -13,13 +12,15 @@ import deckers.thibault.aves.utils.BitmapUtils.centerSquareCrop import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch class AppShortcutHandler(private val context: Context) : MethodCallHandler { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { when (call.method) { "canPin" -> result.success(canPin()) "pin" -> { - Thread { pin(call) }.start() + GlobalScope.launch { pin(call) } result.success(null) } else -> result.notImplemented() diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt index 8f158f27e..7785fbd61 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MetadataHandler.kt @@ -55,6 +55,8 @@ import deckers.thibault.aves.utils.StorageUtils import io.flutter.plugin.common.MethodCall import io.flutter.plugin.common.MethodChannel import io.flutter.plugin.common.MethodChannel.MethodCallHandler +import kotlinx.coroutines.GlobalScope +import kotlinx.coroutines.launch import java.io.ByteArrayOutputStream import java.io.IOException import java.util.* @@ -63,15 +65,15 @@ import kotlin.math.roundToLong class MetadataHandler(private val context: Context) : MethodCallHandler { override fun onMethodCall(call: MethodCall, result: MethodChannel.Result) { when (call.method) { - "getAllMetadata" -> Thread { getAllMetadata(call, MethodResultWrapper(result)) }.start() - "getCatalogMetadata" -> Thread { getCatalogMetadata(call, MethodResultWrapper(result)) }.start() - "getOverlayMetadata" -> Thread { getOverlayMetadata(call, MethodResultWrapper(result)) }.start() - "getContentResolverMetadata" -> Thread { getContentResolverMetadata(call, MethodResultWrapper(result)) }.start() - "getExifInterfaceMetadata" -> Thread { getExifInterfaceMetadata(call, MethodResultWrapper(result)) }.start() - "getMediaMetadataRetrieverMetadata" -> Thread { getMediaMetadataRetrieverMetadata(call, MethodResultWrapper(result)) }.start() - "getEmbeddedPictures" -> Thread { getEmbeddedPictures(call, MethodResultWrapper(result)) }.start() - "getExifThumbnails" -> Thread { getExifThumbnails(call, MethodResultWrapper(result)) }.start() - "getXmpThumbnails" -> Thread { getXmpThumbnails(call, MethodResultWrapper(result)) }.start() + "getAllMetadata" -> GlobalScope.launch { getAllMetadata(call, Coresult(result)) } + "getCatalogMetadata" -> GlobalScope.launch { getCatalogMetadata(call, Coresult(result)) } + "getOverlayMetadata" -> GlobalScope.launch { getOverlayMetadata(call, Coresult(result)) } + "getContentResolverMetadata" -> GlobalScope.launch { getContentResolverMetadata(call, Coresult(result)) } + "getExifInterfaceMetadata" -> GlobalScope.launch { getExifInterfaceMetadata(call, Coresult(result)) } + "getMediaMetadataRetrieverMetadata" -> GlobalScope.launch { getMediaMetadataRetrieverMetadata(call, Coresult(result)) } + "getEmbeddedPictures" -> GlobalScope.launch { getEmbeddedPictures(call, Coresult(result)) } + "getExifThumbnails" -> GlobalScope.launch { getExifThumbnails(call, Coresult(result)) } + "getXmpThumbnails" -> GlobalScope.launch { getXmpThumbnails(call, Coresult(result)) } else -> result.notImplemented() } } diff --git a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MethodResultWrapper.kt b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MethodResultWrapper.kt index 19eb6854b..2603c9cfa 100644 --- a/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MethodResultWrapper.kt +++ b/android/app/src/main/kotlin/deckers/thibault/aves/channel/calls/MethodResultWrapper.kt @@ -3,6 +3,9 @@ package deckers.thibault.aves.channel.calls import android.os.Handler import android.os.Looper import io.flutter.plugin.common.MethodChannel +import kotlinx.coroutines.CoroutineScope +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.launch // ensure `result` methods are called on the main looper thread class MethodResultWrapper internal constructor(private val methodResult: MethodChannel.Result) : MethodChannel.Result { @@ -19,4 +22,21 @@ class MethodResultWrapper internal constructor(private val methodResult: MethodC override fun notImplemented() { handler.post { methodResult.notImplemented() } } -} \ No newline at end of file +} + +// ensure `result` methods are called on the main looper thread +class Coresult internal constructor(private val methodResult: MethodChannel.Result) : MethodChannel.Result { + private val mainScope = CoroutineScope(Dispatchers.Main) + + override fun success(result: Any?) { + mainScope.launch { methodResult.success(result) } + } + + override fun error(errorCode: String, errorMessage: String?, errorDetails: Any?) { + mainScope.launch { methodResult.error(errorCode, errorMessage, errorDetails) } + } + + override fun notImplemented() { + mainScope.launch { methodResult.notImplemented() } + } +}