diff --git a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt index 55dbb6bd..95a1aaf4 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/ui/setup/InstallUpdatePage.kt @@ -1,5 +1,8 @@ package com.github.damontecres.wholphin.ui.setup +import android.Manifest +import androidx.activity.compose.rememberLauncherForActivityResult +import androidx.activity.result.contract.ActivityResultContracts import androidx.compose.foundation.background import androidx.compose.foundation.focusable import androidx.compose.foundation.gestures.scrollBy @@ -19,8 +22,10 @@ import androidx.compose.runtime.Composable import androidx.compose.runtime.LaunchedEffect import androidx.compose.runtime.getValue import androidx.compose.runtime.livedata.observeAsState +import androidx.compose.runtime.mutableStateOf import androidx.compose.runtime.remember import androidx.compose.runtime.rememberCoroutineScope +import androidx.compose.runtime.setValue import androidx.compose.ui.Alignment import androidx.compose.ui.Modifier import androidx.compose.ui.input.key.Key @@ -96,6 +101,17 @@ fun InstallUpdatePage( LaunchedEffect(Unit) { viewModel.init(preferences.appPreferences.updateUrl) } + var permissions by remember { mutableStateOf(viewModel.updater.hasPermissions()) } + val launcher = + rememberLauncherForActivityResult( + ActivityResultContracts.RequestPermission(), + ) { isGranted: Boolean -> + if (isGranted) { + permissions = true + } else { + // TODO + } + } when (val state = loading) { is LoadingState.Error -> ErrorMessage(state, modifier) LoadingState.Loading, @@ -109,7 +125,11 @@ fun InstallUpdatePage( currentVersion = viewModel.currentVersion, release = it, onInstallRelease = { - viewModel.installRelease(it) + if (!permissions) { + launcher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) + } else { + viewModel.installRelease(it) + } }, onCancel = { viewModel.navigationManager.goBack() @@ -197,8 +217,10 @@ fun InstallUpdatePageContent( Modifier .fillMaxWidth() .align(Alignment.CenterVertically) - .background(MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp), shape = RoundedCornerShape(16.dp)) - .padding(16.dp), + .background( + MaterialTheme.colorScheme.surfaceColorAtElevation(1.dp), + shape = RoundedCornerShape(16.dp), + ).padding(16.dp), ) { Text( text = "Update available", diff --git a/app/src/main/java/com/github/damontecres/wholphin/util/UpdateChecker.kt b/app/src/main/java/com/github/damontecres/wholphin/util/UpdateChecker.kt index 797f2d0e..d177e39d 100644 --- a/app/src/main/java/com/github/damontecres/wholphin/util/UpdateChecker.kt +++ b/app/src/main/java/com/github/damontecres/wholphin/util/UpdateChecker.kt @@ -10,14 +10,12 @@ import android.os.Build import android.os.Environment import android.provider.MediaStore import android.widget.Toast -import androidx.core.app.ActivityCompat import androidx.core.content.ContextCompat import androidx.core.content.FileProvider import androidx.core.content.edit import androidx.preference.PreferenceManager import com.github.damontecres.wholphin.R import com.github.damontecres.wholphin.hilt.StandardOkHttpClient -import com.github.damontecres.wholphin.ui.findActivity import com.github.damontecres.wholphin.ui.isNotNullOrBlank import com.github.damontecres.wholphin.ui.showToast import dagger.hilt.android.qualifiers.ApplicationContext @@ -173,7 +171,6 @@ class UpdateChecker } suspend fun installRelease(release: Release) { - val activity = context.findActivity()!! withContext(Dispatchers.IO) { cleanup() val request = @@ -209,59 +206,40 @@ class UpdateChecker } val intent = Intent(Intent.ACTION_INSTALL_PACKAGE) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) intent.data = uri context.startActivity(intent) } else { Timber.e("Resolver URI is null, trying fallback") // showToast(context, "Unable to download the apk") val targetFile = fallbackDownload(it) + val intent = Intent(Intent.ACTION_INSTALL_PACKAGE) + intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION or Intent.FLAG_ACTIVITY_NEW_TASK) + intent.data = + FileProvider.getUriForFile( + context, + context.packageName + ".provider", + targetFile, + ) + context.startActivity(intent) + } + } else { + val targetFile = fallbackDownload(it) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { val intent = Intent(Intent.ACTION_INSTALL_PACKAGE) intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) intent.data = FileProvider.getUriForFile( - activity, - activity.packageName + ".provider", + context, + context.packageName + ".provider", targetFile, ) - activity.startActivity(intent) - } - } else { - if (ContextCompat.checkSelfPermission( - context, - Manifest.permission.WRITE_EXTERNAL_STORAGE, - ) != PackageManager.PERMISSION_GRANTED || - ContextCompat.checkSelfPermission( - context, - Manifest.permission.READ_EXTERNAL_STORAGE, - ) != PackageManager.PERMISSION_GRANTED - ) { - ActivityCompat.requestPermissions( - activity, - arrayOf( - Manifest.permission.WRITE_EXTERNAL_STORAGE, - Manifest.permission.READ_EXTERNAL_STORAGE, - ), - PERMISSION_REQUEST_CODE, - ) + context.startActivity(intent) } else { - val targetFile = fallbackDownload(it) - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) { - val intent = Intent(Intent.ACTION_INSTALL_PACKAGE) - intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION) - intent.data = - FileProvider.getUriForFile( - activity, - activity.packageName + ".provider", - targetFile, - ) - activity.startActivity(intent) - } else { - val intent = Intent(Intent.ACTION_VIEW) - intent.setDataAndType(Uri.fromFile(targetFile), APK_MIME_TYPE) - intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - activity.startActivity(intent) - } + val intent = Intent(Intent.ACTION_VIEW) + intent.setDataAndType(Uri.fromFile(targetFile), APK_MIME_TYPE) + intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + context.startActivity(intent) } } } else { @@ -283,6 +261,17 @@ class UpdateChecker return targetFile } + fun hasPermissions(): Boolean = + Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q || + ContextCompat.checkSelfPermission( + context, + Manifest.permission.WRITE_EXTERNAL_STORAGE, + ) == PackageManager.PERMISSION_GRANTED && + ContextCompat.checkSelfPermission( + context, + Manifest.permission.READ_EXTERNAL_STORAGE, + ) == PackageManager.PERMISSION_GRANTED + /** * Delete previously downloaded APKs */