From 34e5eebbc2dfdd9e71ba200c044f3637ba89aaa2 Mon Sep 17 00:00:00 2001 From: Allan Wang Date: Sat, 29 Feb 2020 23:34:35 -0800 Subject: Prepare for android q image download support --- .../pitchedapps/frost/activities/ImageActivity.kt | 63 +++++++++++++++++----- .../com/pitchedapps/frost/utils/Downloader.kt | 5 +- 2 files changed, 53 insertions(+), 15 deletions(-) diff --git a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt index 6ae7622d..629d5c9b 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/activities/ImageActivity.kt @@ -16,13 +16,18 @@ */ package com.pitchedapps.frost.activities +import android.content.ContentValues import android.content.Context import android.content.Intent import android.content.res.ColorStateList import android.graphics.Color +import android.net.Uri +import android.os.Build import android.os.Bundle import android.os.Environment +import android.provider.MediaStore import android.view.View +import androidx.core.net.toFile import androidx.customview.widget.ViewDragHelper import ca.allanwang.kau.internal.KauBaseActivity import ca.allanwang.kau.logging.KauLoggerExtension @@ -49,6 +54,7 @@ import com.google.android.material.bottomsheet.BottomSheetBehavior import com.google.android.material.floatingactionbutton.FloatingActionButton import com.mikepenz.iconics.typeface.IIcon import com.mikepenz.iconics.typeface.library.googlematerial.GoogleMaterial +import com.pitchedapps.frost.BuildConfig import com.pitchedapps.frost.R import com.pitchedapps.frost.databinding.ActivityImageBinding import com.pitchedapps.frost.facebook.FB_IMAGE_ID_MATCHER @@ -67,6 +73,13 @@ import com.pitchedapps.frost.utils.isIndirectImageUrl import com.pitchedapps.frost.utils.logFrostEvent import com.pitchedapps.frost.utils.sendFrostEmail import com.pitchedapps.frost.utils.setFrostColors +import kotlinx.coroutines.CoroutineExceptionHandler +import kotlinx.coroutines.Deferred +import kotlinx.coroutines.Dispatchers +import kotlinx.coroutines.async +import kotlinx.coroutines.launch +import kotlinx.coroutines.withContext +import org.koin.android.ext.android.inject import java.io.File import java.io.FileNotFoundException import java.io.IOException @@ -75,14 +88,6 @@ import java.util.Date import java.util.Locale import kotlin.math.abs import kotlin.math.max -import kotlinx.coroutines.CoroutineExceptionHandler -import kotlinx.coroutines.Deferred -import kotlinx.coroutines.Dispatchers -import kotlinx.coroutines.async -import kotlinx.coroutines.launch -import kotlinx.coroutines.withContext -import org.koin.android.ext.android.inject -import org.koin.core.inject /** * Created by Allan Wang on 2017-07-15. @@ -103,6 +108,8 @@ class ImageActivity : KauBaseActivity() { * Nonnull once the image is downloaded by the user */ internal var savedFile: File? = null + + internal var savedUri: Uri? = null /** * Indicator for fab's click result */ @@ -159,6 +166,7 @@ class ImageActivity : KauBaseActivity() { } errorRef = e e.logFrostEvent("Image load error") + L.e(e) { "ASDF" } with(binding) { if (imageProgress.isVisible) imageProgress.fadeOut() @@ -305,13 +313,43 @@ class ImageActivity : KauBaseActivity() { return null } return when (type.substring(6)) { - "jpeg" -> ".jpg" - "png" -> ".png" - "gif" -> ".gif" + "jpeg" -> "jpg" + "png" -> "png" + "gif" -> "gif" else -> null } } + private fun newImageUri(mimeType: String): Uri? { + val imageExtension = getImageExtension(mimeType) + val timeStamp = SimpleDateFormat(TIME_FORMAT, Locale.getDefault()).format(Date()) + val imageFileName = "${IMG_TAG}_${timeStamp}" + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) { + val contentValues = ContentValues().apply { + put(MediaStore.MediaColumns.DISPLAY_NAME, imageFileName) + put(MediaStore.MediaColumns.MIME_TYPE, mimeType) + put(MediaStore.MediaColumns.RELATIVE_PATH, IMG_TAG) + } + return contentResolver.insert( + MediaStore.Images.Media.EXTERNAL_CONTENT_URI, + contentValues + ) + } + val storageDir = + Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES) + val frostDir = File(storageDir, IMG_TAG) + if (!frostDir.exists()) frostDir.mkdirs() + val imageFile = File(frostDir, "$imageFileName.$imageExtension") + return try { + frostUriFromFile(imageFile) + } catch (e: IllegalArgumentException) { + if (BuildConfig.DEBUG) { + L.e(e) { "Could not get uri for ${imageFile.absolutePath}" } + } + null + } + } + @Throws(IOException::class) private fun createPublicMediaFile(): File { val timeStamp = SimpleDateFormat(TIME_FORMAT, Locale.getDefault()).format(Date()) @@ -343,7 +381,6 @@ class ImageActivity : KauBaseActivity() { } else { file.setLastModified(System.currentTimeMillis()) } - // Forbid overwrites if (file.isFile && file.length() > 0) { L.i { "Forbid image overwrite" } @@ -370,7 +407,7 @@ class ImageActivity : KauBaseActivity() { throw IOException("Unsuccessful response for image: ${response.peekBody(128).string()}") } - imgExtension = getImageExtension(response.header("Content-Type")) ?: ".jpg" + imgExtension = getImageExtension(response.header("Content-Type")) ?: "jpg" val body = response.body ?: throw IOException("Failed to retrieve image body") diff --git a/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt b/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt index 5e909b03..3c713ec9 100644 --- a/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt +++ b/app/src/main/kotlin/com/pitchedapps/frost/utils/Downloader.kt @@ -22,6 +22,7 @@ import android.content.Context.DOWNLOAD_SERVICE import android.net.Uri import android.os.Environment import android.webkit.URLUtil +import androidx.core.content.getSystemService import ca.allanwang.kau.permissions.PERMISSION_WRITE_EXTERNAL_STORAGE import ca.allanwang.kau.permissions.kauRequestPermissions import ca.allanwang.kau.utils.isAppEnabled @@ -64,7 +65,8 @@ fun Context.frostDownload( toast(R.string.error_invalid_download) return L.e { "Invalid download $uri" } } - if (!isAppEnabled(DOWNLOAD_MANAGER_PACKAGE)) { + val dm = getSystemService() + if (dm == null || !isAppEnabled(DOWNLOAD_MANAGER_PACKAGE)) { materialDialog { title(R.string.no_download_manager) message(R.string.no_download_manager_desc) @@ -87,7 +89,6 @@ fun Context.frostDownload( request.allowScanningByMediaScanner() request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED) request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "Frost/$title") - val dm = getSystemService(DOWNLOAD_SERVICE) as DownloadManager try { dm.enqueue(request) } catch (e: Exception) { -- cgit v1.2.3