From a31f0cf788d98d041943d0c36c7209b25a1356df Mon Sep 17 00:00:00 2001 From: "Jason A. Donenfeld" Date: Fri, 2 Oct 2020 12:11:48 +0200 Subject: [PATCH] DownloadsFileSaver: initialize callback in constructor, not on the fly Signed-off-by: Jason A. Donenfeld --- .../android/activity/LogViewerActivity.kt | 4 +++- .../preference/ZipExporterPreference.kt | 4 +++- .../android/util/DownloadsFileSaver.kt | 23 +++++++++++++------ 3 files changed, 22 insertions(+), 9 deletions(-) diff --git a/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt b/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt index d343bd87..f928161e 100644 --- a/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt +++ b/ui/src/main/java/com/wireguard/android/activity/LogViewerActivity.kt @@ -147,12 +147,14 @@ class LogViewerActivity : AppCompatActivity() { } } + private val downloadsFileSaver = DownloadsFileSaver(this) + private suspend fun saveLog() { var exception: Throwable? = null var outputFile: DownloadsFileSaver.DownloadsFile? = null withContext(Dispatchers.IO) { try { - outputFile = DownloadsFileSaver.save(this@LogViewerActivity, "wireguard-log.txt", "text/plain", true) + outputFile = downloadsFileSaver.save("wireguard-log.txt", "text/plain", true) outputFile?.outputStream?.write(rawLogLines.toString().toByteArray(Charsets.UTF_8)) } catch (e: Throwable) { outputFile?.delete() diff --git a/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt b/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt index aaea7703..b8a1da75 100644 --- a/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt +++ b/ui/src/main/java/com/wireguard/android/preference/ZipExporterPreference.kt @@ -32,6 +32,8 @@ import java.util.zip.ZipOutputStream */ class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference(context, attrs) { private var exportedFilePath: String? = null + private val downloadsFileSaver = DownloadsFileSaver(activity) + private fun exportZip() { lifecycleScope.launch { val tunnels = Application.getTunnelManager().getTunnels() @@ -41,7 +43,7 @@ class ZipExporterPreference(context: Context, attrs: AttributeSet?) : Preference if (configs.isEmpty()) { throw IllegalArgumentException(context.getString(R.string.no_tunnels_error)) } - val outputFile = DownloadsFileSaver.save(activity, "wireguard-export.zip", "application/zip", true) + val outputFile = downloadsFileSaver.save("wireguard-export.zip", "application/zip", true) if (outputFile == null) { withContext(Dispatchers.Main.immediate) { isEnabled = true diff --git a/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.kt b/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.kt index c8f4aa8d..bcd4f25e 100644 --- a/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.kt +++ b/ui/src/main/java/com/wireguard/android/util/DownloadsFileSaver.kt @@ -14,6 +14,7 @@ import android.os.Environment import android.provider.MediaStore import android.provider.MediaStore.MediaColumns import androidx.activity.ComponentActivity +import androidx.activity.result.ActivityResultLauncher import androidx.activity.result.contract.ActivityResultContracts import androidx.core.content.ContextCompat import com.wireguard.android.R @@ -25,9 +26,18 @@ import java.io.FileOutputStream import java.io.IOException import java.io.OutputStream -object DownloadsFileSaver { - @Throws(Exception::class) - suspend fun save(context: ComponentActivity, name: String, mimeType: String?, overwriteExisting: Boolean) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { +class DownloadsFileSaver(private val context: ComponentActivity) { + private lateinit var activityResult: ActivityResultLauncher + private lateinit var futureGrant: CompletableDeferred + + init { + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q) { + futureGrant = CompletableDeferred() + activityResult = context.registerForActivityResult(ActivityResultContracts.RequestPermission()) { ret -> futureGrant.complete(ret) } + } + } + + suspend fun save(name: String, mimeType: String?, overwriteExisting: Boolean) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { withContext(Dispatchers.IO) { val contentResolver = context.contentResolver if (overwriteExisting) @@ -66,13 +76,12 @@ object DownloadsFileSaver { } else { withContext(Dispatchers.Main.immediate) { if (ContextCompat.checkSelfPermission(context, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) { - val futureGrant = CompletableDeferred() - val activityResult = context.registerForActivityResult(ActivityResultContracts.RequestPermission(), futureGrant::complete) activityResult.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE) val granted = futureGrant.await() - activityResult.unregister() - if (!granted) + if (!granted) { + futureGrant = CompletableDeferred() return@withContext null + } } @Suppress("DEPRECATION") val path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS) withContext(Dispatchers.IO) {