From 636c027298b6610602e70d33685825627d7c05f3 Mon Sep 17 00:00:00 2001 From: inorichi Date: Tue, 6 Feb 2018 11:42:38 +0100 Subject: [PATCH] Fix extensions installer on old Android versions. Fix deadlock on devices with 1-2 cores --- .../java/eu/kanade/tachiyomi/AppModule.kt | 19 ++++++---- .../extension/util/ExtensionInstaller.kt | 35 +++++++++++++++---- 2 files changed, 40 insertions(+), 14 deletions(-) diff --git a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt index 3b071fa2eb..114f231b6a 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/AppModule.kt @@ -11,7 +11,8 @@ import eu.kanade.tachiyomi.data.track.TrackManager import eu.kanade.tachiyomi.extension.ExtensionManager import eu.kanade.tachiyomi.network.NetworkHelper import eu.kanade.tachiyomi.source.SourceManager -import kotlinx.coroutines.experimental.async +import rx.Observable +import rx.schedulers.Schedulers import uy.kohesive.injekt.api.* class AppModule(val app: Application) : InjektModule { @@ -42,16 +43,20 @@ class AppModule(val app: Application) : InjektModule { // Asynchronously init expensive components for a faster cold start - async { get() } + rxAsync { get() } - async { get() } + rxAsync { get() } - async { get() } + rxAsync { get() } - async { get() } + rxAsync { get() } - async { get() } + rxAsync { get() } } -} \ No newline at end of file + private fun rxAsync(block: () -> Unit) { + Observable.fromCallable { block() }.subscribeOn(Schedulers.computation()).subscribe() + } + +} diff --git a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt index f445bbaf56..cf57e159ef 100644 --- a/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt +++ b/app/src/main/java/eu/kanade/tachiyomi/extension/util/ExtensionInstaller.kt @@ -1,17 +1,16 @@ package eu.kanade.tachiyomi.extension.util import android.app.DownloadManager -import android.content.BroadcastReceiver -import android.content.Context -import android.content.Intent -import android.content.IntentFilter +import android.content.* import android.net.Uri import com.jakewharton.rxrelay.PublishRelay import eu.kanade.tachiyomi.extension.model.Extension import eu.kanade.tachiyomi.extension.model.InstallStep +import eu.kanade.tachiyomi.util.getUriCompat import rx.Observable import rx.android.schedulers.AndroidSchedulers import timber.log.Timber +import java.io.File import java.util.concurrent.TimeUnit /** @@ -133,8 +132,10 @@ internal class ExtensionInstaller(private val context: Context) { */ fun uninstallApk(pkgName: String) { val packageUri = Uri.parse("package:$pkgName") - val uninstallIntent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri) - context.startActivity(uninstallIntent) + val intent = Intent(Intent.ACTION_UNINSTALL_PACKAGE, packageUri) + .setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + context.startActivity(intent) } /** @@ -204,12 +205,32 @@ internal class ExtensionInstaller(private val context: Context) { if (id !in activeDownloads.values) return val uri = downloadManager.getUriForDownloadedFile(id) + + // Set next installation step if (uri != null) { downloadsRelay.call(id to InstallStep.Installing) - installApk(uri) } else { Timber.e("Couldn't locate downloaded APK") downloadsRelay.call(id to InstallStep.Error) + return + } + + // Due to a bug in older Android versions (L and M at least), the installer can't open + // files that do not contain the apk extension, even if you specify the correct MIME. + // We workaround it by querying the actual file path and using the file provider when + // it fails. + try { + installApk(uri) + } catch (e: ActivityNotFoundException) { + val query = DownloadManager.Query() + query.setFilterById(id) + downloadManager.query(query).use { + if (it.moveToFirst()) { + val uriCompat = File(it.getString(it.getColumnIndex( + DownloadManager.COLUMN_LOCAL_FILENAME))).getUriCompat(context) + installApk(uriCompat) + } + } } } }