Refine storage permission request

This commit is contained in:
FooIbar committed 2023-11-01 15:42:55 +08:00
1 parent 3ee4b4a61e
commit 498129314a
4 files changed
+84 -114

No files matched your search

@@ -21,10 +21,8 @@ import android.app.Activity
import android.app.Dialog
import android.app.DownloadManager
import android.content.DialogInterface
import android.content.pm.PackageManager
import android.graphics.Color
import android.net.Uri
import android.os.Build
import android.os.Bundle
import android.os.Environment
import android.view.LayoutInflater
@@ -32,7 +30,6 @@ import android.view.View
import android.view.ViewGroup
import android.widget.AdapterView
import android.widget.ArrayAdapter
import androidx.activity.result.contract.ActivityResultContracts
import androidx.annotation.StringRes
import androidx.compose.foundation.clickable
import androidx.compose.foundation.horizontalScroll
@@ -96,7 +93,6 @@ import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.viewinterop.AndroidViewBinding
import androidx.core.content.ContextCompat
import androidx.core.text.parseAsHtml
import androidx.lifecycle.lifecycleScope
import androidx.navigation.fragment.findNavController
@@ -170,7 +166,10 @@ import com.hippo.ehviewer.util.IntList
import com.hippo.ehviewer.util.ReadableTime
import com.hippo.ehviewer.util.addTextToClipboard
import com.hippo.ehviewer.util.getParcelableCompat
import com.hippo.ehviewer.util.isAtLeastQ
import com.hippo.ehviewer.util.requestPermission
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext
import kotlin.math.roundToInt
import kotlinx.coroutines.CancellationException
@@ -197,20 +196,6 @@ class GalleryDetailScene : BaseScene() {
private var getDetailError by mutableStateOf("")
private var mTorrentList: TorrentResult? = null
private var requestStoragePermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
) { result: Boolean ->
if (result && composeBindingGD != null) {
val helper = TorrentListDialogHelper()
val binding = DialogTorrentListBinding.inflate(layoutInflater)
val dialog: Dialog = BaseDialogBuilder(requireActivity())
.setTitle(R.string.torrents)
.setView(binding.root)
.setOnDismissListener(helper)
.show()
helper.setDialog(dialog, binding, composeBindingGD!!.torrentUrl)
}
}
private var mArchiveFormParamOr: String? = null
private var mArchiveList: List<ArchiveParser.Archive>? = null
private var mCurrentFunds: HomeParser.Funds? = null
@@ -1113,21 +1098,20 @@ class GalleryDetailScene : BaseScene() {
private fun showTorrentDialog() {
val galleryDetail = composeBindingGD ?: return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(
requireActivity(),
Manifest.permission.WRITE_EXTERNAL_STORAGE,
) != PackageManager.PERMISSION_GRANTED
) {
requestStoragePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
} else {
val helper = TorrentListDialogHelper()
val binding = DialogTorrentListBinding.inflate(layoutInflater)
val dialog: Dialog = BaseDialogBuilder(requireContext())
.setTitle(R.string.torrents)
.setView(binding.root)
.setOnDismissListener(helper)
.show()
helper.setDialog(dialog, binding, galleryDetail.torrentUrl)
viewLifecycleOwner.lifecycleScope.launchUI {
val granted = isAtLeastQ || requireContext().requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (granted) {
val helper = TorrentListDialogHelper()
val binding = DialogTorrentListBinding.inflate(layoutInflater)
val dialog: Dialog = BaseDialogBuilder(requireContext())
.setTitle(R.string.torrents)
.setView(binding.root)
.setOnDismissListener(helper)
.show()
helper.setDialog(dialog, binding, galleryDetail.torrentUrl)
} else {
showTip(getString(R.string.permission_denied), LENGTH_SHORT)
}
}
}
@@ -23,7 +23,6 @@ import android.content.ClipData
import android.content.ContentValues
import android.content.Intent
import android.content.pm.ActivityInfo
import android.content.pm.PackageManager
import android.graphics.Color
import android.graphics.ColorMatrix
import android.graphics.ColorMatrixColorFilter
@@ -43,7 +42,6 @@ import android.view.animation.Animation
import android.view.animation.AnimationUtils
import android.webkit.MimeTypeMap
import android.widget.Toast
import androidx.activity.result.contract.ActivityResultContracts
import androidx.activity.result.contract.ActivityResultContracts.CreateDocument
import androidx.activity.viewModels
import androidx.annotation.ChecksSdkIntAtLeast
@@ -52,7 +50,6 @@ import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.setValue
import androidx.core.content.ContextCompat
import androidx.core.content.FileProvider
import androidx.core.graphics.ColorUtils
import androidx.core.view.WindowCompat
@@ -82,7 +79,9 @@ import com.hippo.ehviewer.util.getParcelableExtraCompat
import com.hippo.ehviewer.util.getValue
import com.hippo.ehviewer.util.isAtLeastO
import com.hippo.ehviewer.util.isAtLeastP
import com.hippo.ehviewer.util.isAtLeastQ
import com.hippo.ehviewer.util.lazyMut
import com.hippo.ehviewer.util.requestPermission
import com.hippo.ehviewer.util.sendTo
import com.hippo.ehviewer.util.setValue
import com.hippo.unifile.UniFile
@@ -95,6 +94,7 @@ import eu.kanade.tachiyomi.ui.reader.setting.ReadingModeType
import eu.kanade.tachiyomi.ui.reader.viewer.BaseViewer
import eu.kanade.tachiyomi.ui.reader.viewer.pager.R2LPagerViewer
import eu.kanade.tachiyomi.util.lang.launchIO
import eu.kanade.tachiyomi.util.lang.launchUI
import eu.kanade.tachiyomi.util.lang.withUIContext
import eu.kanade.tachiyomi.util.system.applySystemAnimatorScale
import eu.kanade.tachiyomi.util.system.isNightMode
@@ -170,17 +170,6 @@ class ReaderActivity : EhActivity() {
}
var mGalleryProvider by lazyMut { vm::galleryProvider }
private var mCurrentIndex: Int = 0
private var mSavingPage = -1
private var requestStoragePermissionLauncher = registerForActivityResult(
ActivityResultContracts.RequestPermission(),
) { result ->
if (result!! && mSavingPage != -1) {
saveImage(mSavingPage)
} else {
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show()
}
mSavingPage = -1
}
private val galleryDetailUrl: String?
get() {
@@ -455,78 +444,73 @@ class ReaderActivity : EhActivity() {
}
fun saveImage(page: Int) {
if (null == mGalleryProvider) {
return
}
mGalleryProvider ?: return
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.Q && ContextCompat.checkSelfPermission(
this,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
) != PackageManager.PERMISSION_GRANTED
) {
mSavingPage = page
requestStoragePermissionLauncher.launch(Manifest.permission.WRITE_EXTERNAL_STORAGE)
return
}
lifecycleScope.launchUI {
val granted = isAtLeastQ || requestPermission(Manifest.permission.WRITE_EXTERNAL_STORAGE)
if (granted) {
val filename = mGalleryProvider!!.getImageFilenameWithExtension(page)
var mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
MimeTypeMap.getFileExtensionFromUrl(filename),
)
if (mimeType.isNullOrEmpty()) {
mimeType = "image/jpeg"
}
val filename = mGalleryProvider!!.getImageFilenameWithExtension(page)
var mimeType = MimeTypeMap.getSingleton().getMimeTypeFromExtension(
MimeTypeMap.getFileExtensionFromUrl(filename),
)
if (mimeType.isNullOrEmpty()) {
mimeType = "image/jpeg"
}
val realPath: String
val resolver = contentResolver
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
if (isAtLeastQ) {
values.put(
MediaStore.MediaColumns.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES + File.separator + AppConfig.APP_DIRNAME,
)
values.put(MediaStore.MediaColumns.IS_PENDING, 1)
realPath = Environment.DIRECTORY_PICTURES + File.separator + AppConfig.APP_DIRNAME
} else {
val path = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
AppConfig.APP_DIRNAME,
)
realPath = path.toString()
if (!FileUtils.ensureDirectory(path)) {
Toast.makeText(this@ReaderActivity, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show()
return@launchUI
}
values.put(MediaStore.MediaColumns.DATA, path.toString() + File.separator + filename)
}
val imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
if (imageUri == null) {
Toast.makeText(this@ReaderActivity, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show()
return@launchUI
}
if (!mGalleryProvider!!.save(page, UniFile.fromMediaUri(this@ReaderActivity, imageUri))) {
try {
resolver.delete(imageUri, null, null)
} catch (e: Exception) {
e.printStackTrace()
}
val realPath: String
val resolver = contentResolver
val values = ContentValues()
values.put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
values.put(MediaStore.Images.Media.DATE_ADDED, System.currentTimeMillis())
values.put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
values.put(
MediaStore.MediaColumns.RELATIVE_PATH,
Environment.DIRECTORY_PICTURES + File.separator + AppConfig.APP_DIRNAME,
)
values.put(MediaStore.MediaColumns.IS_PENDING, 1)
realPath = Environment.DIRECTORY_PICTURES + File.separator + AppConfig.APP_DIRNAME
} else {
val path = File(
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),
AppConfig.APP_DIRNAME,
)
realPath = path.toString()
if (!FileUtils.ensureDirectory(path)) {
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show()
return
Toast.makeText(this@ReaderActivity, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show()
return@launchUI
} else if (isAtLeastQ) {
val contentValues = ContentValues()
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
resolver.update(imageUri, contentValues, null, null)
}
Toast.makeText(
this@ReaderActivity,
getString(R.string.image_saved, realPath + File.separator + filename),
Toast.LENGTH_SHORT,
).show()
} else {
Toast.makeText(this@ReaderActivity, R.string.permission_denied, Toast.LENGTH_SHORT).show()
}
values.put(MediaStore.MediaColumns.DATA, path.toString() + File.separator + filename)
}
val imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values)
if (imageUri == null) {
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show()
return
}
if (!mGalleryProvider!!.save(page, UniFile.fromMediaUri(this, imageUri))) {
try {
resolver.delete(imageUri, null, null)
} catch (e: Exception) {
e.printStackTrace()
}
Toast.makeText(this, R.string.error_cant_save_image, Toast.LENGTH_SHORT).show()
return
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val contentValues = ContentValues()
contentValues.put(MediaStore.MediaColumns.IS_PENDING, 0)
resolver.update(imageUri, contentValues, null, null)
}
Toast.makeText(
this,
getString(R.string.image_saved, realPath + File.separator + filename),
Toast.LENGTH_SHORT,
).show()
}
fun saveImageTo(page: Int) {
@@ -533,6 +533,7 @@
<string name="update_frequency_monthly">每月</string>
<string name="new_version_available">有新版本!</string>
<string name="already_latest_version">已是最新版本</string>
<string name="permission_denied">权限被拒</string>
<!-- Tachiyomi Reader Start-->
<string name="action_settings">设置</string>
<string name="action_retry">重试</string>
+1
View File
@@ -597,6 +597,7 @@
<string name="update_frequency_monthly">Monthly</string>
<string name="new_version_available">New version available!</string>
<string name="already_latest_version">Already the latest version</string>
<string name="permission_denied">Permission denied</string>
<!-- Tachiyomi Reader Start-->
<string name="action_settings">Settings</string>
<string name="pref_rotation_type">Default rotation type</string>