156 lines
5.0 KiB
Kotlin
156 lines
5.0 KiB
Kotlin
package com.sw.dualscreen.utils
|
|
|
|
import android.content.ContentUris
|
|
import android.content.Context
|
|
import android.net.Uri
|
|
import android.os.Build
|
|
import android.provider.MediaStore
|
|
import androidx.annotation.RequiresApi
|
|
import okhttp3.MediaType.Companion.toMediaTypeOrNull
|
|
import okhttp3.MultipartBody
|
|
import okhttp3.RequestBody.Companion.asRequestBody
|
|
import timber.log.Timber
|
|
import java.io.File
|
|
|
|
object FileUtils {
|
|
/**
|
|
* 从Uri获取File
|
|
* example: file:///data/user/0/com.sw.inbound/cache/IMG_17515262353556856678814444882273.jpg
|
|
*/
|
|
private fun getFileFromUri(context: Context, uri: Uri): File? {
|
|
Timber.d("getFileFromUri uri = ${uri.scheme}")
|
|
return when (uri.scheme) {
|
|
"file" -> File(uri.path ?: return null)
|
|
"content" -> {
|
|
try {
|
|
val inputStream = context.contentResolver.openInputStream(uri) ?: return null
|
|
val cacheDir = context.cacheDir
|
|
val file = File.createTempFile(
|
|
"upload_${System.currentTimeMillis()}",
|
|
".jpg",
|
|
cacheDir
|
|
)
|
|
file.outputStream().use { output ->
|
|
inputStream.copyTo(output)
|
|
}
|
|
file
|
|
} catch (e: Exception) {
|
|
Timber.e(e)
|
|
null
|
|
}
|
|
}
|
|
|
|
else -> null
|
|
}
|
|
}
|
|
|
|
/**
|
|
* 通过uri生成http请求体
|
|
*/
|
|
fun genRequestPart(context: Context, imageUri: Uri): MultipartBody.Part? {
|
|
Timber.d("genRequestPart imageUri = $imageUri")
|
|
// 1. 从Uri获取文件
|
|
val file = getFileFromUri(context, imageUri)
|
|
if (file == null) {
|
|
Timber.e("getFileFromUri file is null")
|
|
return null
|
|
}
|
|
// 2. 创建请求体
|
|
val requestFile = file
|
|
.asRequestBody("application/octet-stream".toMediaTypeOrNull())
|
|
val imagePart = MultipartBody.Part.createFormData(
|
|
"file",
|
|
file.name,
|
|
requestFile
|
|
)
|
|
return imagePart
|
|
}
|
|
|
|
/**
|
|
* 通过Uri删除文件
|
|
* @param context 上下文
|
|
* @param uri 文件Uri
|
|
* @return Boolean 是否删除成功
|
|
*/
|
|
fun deleteFileWithUri(context: Context, uri: Uri): Boolean {
|
|
Timber.d("deleteFileWithUri uri = ${uri.scheme}")
|
|
return when {
|
|
// 1. 处理 content:// 类型的Uri (MediaStore)
|
|
uri.scheme.equals("content", ignoreCase = true) -> {
|
|
deleteContentUriFile(context, uri)
|
|
}
|
|
// 2. 处理 file:// 类型的Uri
|
|
uri.scheme.equals("file", ignoreCase = true) -> {
|
|
deleteFileUriFile(uri)
|
|
}
|
|
// 3. 其他情况尝试直接解析路径
|
|
else -> {
|
|
deleteFileFromPath(uri.path ?: return false)
|
|
}
|
|
}
|
|
}
|
|
|
|
// 删除Content Uri文件
|
|
private fun deleteContentUriFile(context: Context, uri: Uri): Boolean {
|
|
Timber.d("deleteContentUriFile uri = ${uri.scheme}")
|
|
return try {
|
|
context.contentResolver.delete(uri, null, null) > 0
|
|
} catch (e: SecurityException) {
|
|
// Android 10+需要特殊处理
|
|
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
|
|
deleteMediaStoreFile(context, uri)
|
|
} else {
|
|
false
|
|
}
|
|
} catch (e: Exception) {
|
|
Timber.e(e)
|
|
false
|
|
}
|
|
}
|
|
|
|
// Android 10+删除MediaStore文件
|
|
@RequiresApi(Build.VERSION_CODES.Q)
|
|
private fun deleteMediaStoreFile(context: Context, uri: Uri): Boolean {
|
|
Timber.d("deleteMediaStoreFile uri = ${uri.scheme}")
|
|
val contentResolver = context.contentResolver
|
|
val projection = arrayOf(MediaStore.MediaColumns._ID)
|
|
|
|
return try {
|
|
contentResolver.query(uri, projection, null, null, null)?.use { cursor ->
|
|
if (cursor.moveToFirst()) {
|
|
val id =
|
|
cursor.getLong(cursor.getColumnIndexOrThrow(MediaStore.MediaColumns._ID))
|
|
val contentUri = ContentUris.withAppendedId(uri, id)
|
|
contentResolver.delete(contentUri, null, null) > 0
|
|
} else {
|
|
false
|
|
}
|
|
} ?: false
|
|
} catch (e: Exception) {
|
|
Timber.e(e)
|
|
false
|
|
}
|
|
}
|
|
|
|
// 删除File Uri文件
|
|
private fun deleteFileUriFile(uri: Uri): Boolean {
|
|
Timber.d("deleteFileUriFile uri = $uri")
|
|
return try {
|
|
File(uri.path ?: return false).delete()
|
|
} catch (e: Exception) {
|
|
Timber.e(e)
|
|
false
|
|
}
|
|
}
|
|
|
|
// 直接通过路径删除文件
|
|
private fun deleteFileFromPath(path: String): Boolean {
|
|
Timber.d("deleteFileFromPath path = $path")
|
|
return try {
|
|
File(path).delete()
|
|
} catch (e: Exception) {
|
|
Timber.e(e)
|
|
false
|
|
}
|
|
}
|
|
} |