Refactor(FileUtils): Optimize code

This commit is contained in:
2024-10-12 15:59:07 +08:00
parent 326e777b7f
commit f7dd806885
3 changed files with 102 additions and 74 deletions

View File

@@ -225,7 +225,7 @@ private fun initWebView(
webview.settings.javaScriptEnabled = true
webview.settings.domStorageEnabled = true
webview.addJavascriptInterface(
NativeWebApi(context = context, webView = webview, permissionLauncher),
NativeWebApi(context = context, permissionLauncher = permissionLauncher),
"NativeApi"
)
webview.setDownloadListener { url, userAgent, _, mimetype, _ ->

View File

@@ -0,0 +1,95 @@
package top.fatweb.oxygen.toolbox.util
import android.content.ContentValues
import android.content.Context
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.annotation.RequiresApi
import kotlinx.coroutines.runBlocking
import timber.log.Timber
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import kotlin.let
fun saveToDownloads(
context: Context,
permissionLauncher: ManagedActivityResultLauncher<String, Boolean>,
data: ByteArray,
fileName: String
) = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
saveFileToDownloads(context = context, data = data, fileName = fileName)
} else {
saveFileToDownloads(
context = context,
permissionLauncher = permissionLauncher,
data = data,
fileName = fileName
)
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun saveFileToDownloads(
context: Context,
data: ByteArray,
fileName: String
): Boolean {
val resolver = context.contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, fileName)
put(MediaStore.Downloads.MIME_TYPE, "application/octet-stream")
put(MediaStore.Downloads.IS_PENDING, 1)
}
val collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val fileUri = resolver.insert(collection, contentValues)
return fileUri?.let { uri ->
resolver.openOutputStream(uri)?.use { outputStream ->
outputStream.write(data)
outputStream.flush()
}
contentValues.clear()
contentValues.put(MediaStore.Downloads.IS_PENDING, 0)
resolver.update(uri, contentValues, null, null)
true
} ?: run {
Timber.e("Could not save file $fileName to Downloads")
false
}
}
private fun saveFileToDownloads(
context: Context,
permissionLauncher: ManagedActivityResultLauncher<String, Boolean>,
data: ByteArray,
fileName: String
): Boolean {
if (!runBlocking {
Permissions.requestWriteExternalStoragePermission(
context,
permissionLauncher
)
}) {
return false
}
val downloadsDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File(downloadsDir, fileName)
return try {
FileOutputStream(file).apply {
write(data)
close()
}
true
} catch (e: IOException) {
Timber.e(e, "Could not save file $fileName to ${file.absolutePath}")
false
}
}

View File

@@ -2,26 +2,14 @@ package top.fatweb.oxygen.toolbox.util
import android.content.ClipData
import android.content.ClipboardManager
import android.content.ContentValues
import android.content.Context
import android.content.Context.CLIPBOARD_SERVICE
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.util.Base64
import android.webkit.JavascriptInterface
import android.webkit.WebView
import androidx.activity.compose.ManagedActivityResultLauncher
import androidx.annotation.RequiresApi
import kotlinx.coroutines.runBlocking
import timber.log.Timber
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
class NativeWebApi(
private val context: Context,
private val webView: WebView,
private val permissionLauncher: ManagedActivityResultLauncher<String, Boolean>
) {
@JavascriptInterface
@@ -43,66 +31,11 @@ class NativeWebApi(
fun saveToDownloads(dataBase64: String, fileName: String): Boolean {
val data = Base64.decode(dataBase64, Base64.DEFAULT)
return if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
saveFileToDownloads(data = data, fileName = fileName)
} else {
saveFileToExternalDownloads(data = data, fileName = fileName)
}
}
@RequiresApi(Build.VERSION_CODES.Q)
private fun saveFileToDownloads(data: ByteArray, fileName: String): Boolean {
val resolver = context.contentResolver
val contentValues = ContentValues().apply {
put(MediaStore.Downloads.DISPLAY_NAME, fileName)
put(MediaStore.Downloads.MIME_TYPE, "application/octet-stream")
put(MediaStore.Downloads.IS_PENDING, 1)
}
val collection = MediaStore.Downloads.getContentUri(MediaStore.VOLUME_EXTERNAL_PRIMARY)
val fileUri = resolver.insert(collection, contentValues)
return fileUri?.let { uri ->
resolver.openOutputStream(uri)?.use { outputStream ->
outputStream.write(data)
outputStream.flush()
}
contentValues.clear()
contentValues.put(MediaStore.Downloads.IS_PENDING, 0)
resolver.update(uri, contentValues, null, null)
true
} ?: let {
Timber.e("Could not save file $fileName to Downloads")
false
}
}
private fun saveFileToExternalDownloads(data: ByteArray, fileName: String): Boolean {
if (!runBlocking { Permissions.requestWriteExternalStoragePermission(context, permissionLauncher) }) {
return false
}
val downloadsDir =
Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS)
val file = File(downloadsDir, fileName)
return try {
FileOutputStream(file).apply {
write(data)
close()
}
true
} catch (e: IOException) {
Timber.e(e, "Could not save file $fileName to ${file.absolutePath}")
false
}
}
private fun callback(callback: String, vararg args: Any) {
val jsCode =
"$callback(${args.map { if (it is String) "'$it'" else it }.joinToString(", ")})"
webView.evaluateJavascript(jsCode, null)
return saveToDownloads(
context = context,
permissionLauncher = permissionLauncher,
data = data,
fileName = fileName
)
}
}