Android 打开系统文件管理器兼容android8,9,10和读取第三方文件管理的文件(微信文件管理)
程序员文章站
2022-03-15 10:33:34
打开系统文件管理器兼容android8,9,10和读取第三方文件管理的文件(微信文件管理),缺点:单选 val intent = Intent(Intent.ACTION_GET_CONTENT) intent.type = "*/*" intent.addCategory(Intent.CATEGORY_OPENABLE) (parent.cont...
打开系统文件管理器兼容android8,9,10和读取第三方文件管理的文件(微信文件管理),缺点:单选
val intent = Intent(Intent.ACTION_GET_CONTENT)
intent.type = "*/*"
intent.addCategory(Intent.CATEGORY_OPENABLE)
(parent.context as Activity).startActivityForResult(intent, myRequestCode)
根据onActivityResult回调的uri获得文件路径,android8,9,10实测通过,也可以获取第三方文件管理器(微信文件管理)的路径
package com.xxxx.app.common_work.utils
import android.content.ContentResolver
import android.content.ContentUris
import android.content.Context
import android.database.Cursor
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.DocumentsContract
import android.provider.MediaStore
import android.provider.OpenableColumns
import android.support.annotation.RequiresApi
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.io.InputStream
object HtFileUtils {
/**
* 根据Uri获取文件绝对路径,解决Android4.4以上版本Uri转换 兼容Android 10
*
* @param context
* @param imageUri
*/
fun getFileAbsolutePath(context: Context, imageUri: Uri): String? {
if (context == null || imageUri == null) {
return null
}
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
return getRealFilePath(context, imageUri)
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT && Build.VERSION.SDK_INT < 29 && DocumentsContract.isDocumentUri(context, imageUri)) {
if (isExternalStorageDocument(imageUri)) {
val docId = DocumentsContract.getDocumentId(imageUri)
val split = docId.split(":".toRegex()).toTypedArray()
val type = split[0]
if ("primary".equals(type, ignoreCase = true)) {
return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
}
} else if (isDownloadsDocument(imageUri)) {
val id = DocumentsContract.getDocumentId(imageUri)
val contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id))
return getDataColumn(context, contentUri, null, null)
} else if (isMediaDocument(imageUri)) {
val docId = DocumentsContract.getDocumentId(imageUri)
val split = docId.split(":".toRegex()).toTypedArray()
val type = split[0]
var contentUri: Uri? = null
if ("image" == type) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
} else if ("video" == type) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
} else if ("audio" == type) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
val selection = MediaStore.Images.Media._ID + "=?"
val selectionArgs = arrayOf(split[1])
return getDataColumn(context, contentUri, selection, selectionArgs)
}
} // MediaStore (and general)
if (Build.VERSION.SDK_INT >= 29) {
return uriToFileApiQ(context, imageUri)
} else if ("content".equals(imageUri.scheme, ignoreCase = true)) {
// Return the remote address
return if (isGooglePhotosUri(imageUri)) {
imageUri.lastPathSegment
} else {
val paths: String? = getDataColumn(context, imageUri, null, null)
if (paths == null) {
uriToFileApiQ(context, imageUri)
} else {
paths
}
}
} else if ("file".equals(imageUri.scheme, ignoreCase = true)) {
return imageUri.path
}
return null
}
//此方法 只能用于4.4以下的版本
private fun getRealFilePath(context: Context, uri: Uri?): String? {
if (null == uri) {
return null
}
val scheme = uri.scheme
var data: String? = null
if (scheme == null) {
data = uri.path
} else if (ContentResolver.SCHEME_FILE == scheme) {
data = uri.path
} else if (ContentResolver.SCHEME_CONTENT == scheme) {
val projection = arrayOf(MediaStore.Images.ImageColumns.DATA)
val cursor = context.contentResolver.query(uri, projection, null, null, null)
// Cursor cursor = context.getContentResolver().query(uri, new String[]{MediaStore.Images.ImageColumns.DATA}, null, null, null);
if (null != cursor) {
if (cursor.moveToFirst()) {
val index: Int = cursor.getColumnIndex(MediaStore.Images.ImageColumns.DATA)
if (index > -1) {
data = cursor.getString(index)
}
}
cursor.close()
}
}
return data
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is ExternalStorageProvider.
*/
private fun isExternalStorageDocument(uri: Uri): Boolean {
return "com.android.externalstorage.documents" == uri.authority
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is DownloadsProvider.
*/
private fun isDownloadsDocument(uri: Uri): Boolean {
return "com.android.providers.downloads.documents" == uri.authority
}
private fun getDataColumn(context: Context, uri: Uri?, selection: String?, selectionArgs: Array<String>?): String? {
var cursor: Cursor? = null
val column = MediaStore.Images.Media.DATA
val projection = arrayOf(column)
try {
cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
if (cursor != null && cursor.moveToFirst()) {
val index: Int = cursor.getColumnIndexOrThrow(column)
return cursor.getString(index)
}
} finally {
if (cursor != null) {
cursor.close()
}
}
return null
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is MediaProvider.
*/
private fun isMediaDocument(uri: Uri): Boolean {
return "com.android.providers.media.documents" == uri.authority
}
/**
* @param uri The Uri to check.
* @return Whether the Uri authority is Google Photos.
*/
private fun isGooglePhotosUri(uri: Uri): Boolean {
return "com.google.android.apps.photos.content" == uri.authority
}
/**
* Android 10 以上适配 另一种写法
* @param context
* @param uri
* @return
*/
private fun getFileFromContentUri(context: Context, uri: Uri?): String? {
if (uri == null) {
return null
}
val filePath: String
val filePathColumn = arrayOf(MediaStore.MediaColumns.DATA, MediaStore.MediaColumns.DISPLAY_NAME)
val contentResolver = context.contentResolver
val cursor: Cursor? = contentResolver.query(uri, filePathColumn, null,
null, null)
if (cursor != null) {
cursor.moveToFirst()
try {
filePath = cursor.getString(cursor.getColumnIndex(filePathColumn[0]))
return filePath
} catch (e: Exception) {
} finally {
cursor.close()
}
}
return ""
}
/**
* Android 10 以上适配,以及读一些第三方文件管理器
* @param context
* @param uri
* @return
*/
//@RequiresApi(api = [29, 28])
private fun uriToFileApiQ(context: Context, uri: Uri): String? {
var file: File? = null
//android10以上转换
if (uri.scheme == ContentResolver.SCHEME_FILE) {
file = File(uri.path)
} else if (uri.scheme == ContentResolver.SCHEME_CONTENT) {
//把文件复制到沙盒目录
val contentResolver = context.contentResolver
val cursor: Cursor? = contentResolver.query(uri, null, null, null, null)
if (cursor?.moveToFirst() == true) {
val displayName = cursor?.getString(cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME))
try {
val inputStream = contentResolver.openInputStream(uri)
val cache = File(context.externalCacheDir!!.absolutePath, /*Math.round((Math.random() + 1) * 1000).toString() + */displayName)
val fos = FileOutputStream(cache)
copy(inputStream!!, fos)
file = cache
fos.close()
inputStream.close()
} catch (e: IOException) {
e.printStackTrace()
}
}
}
return file!!.absolutePath
}
private fun copy(inputStream: InputStream, fos: FileOutputStream) {
try {
val buffer = ByteArray(1024)
var len: Int
while (inputStream.read(buffer).also { len = it } > 0) {
fos.write(buffer, 0, len)
}
} catch (e: java.lang.Exception) {
} finally {
fos.flush()
inputStream.close()
fos.close()
}
}
}
本文地址:https://blog.csdn.net/Coder_Hcy/article/details/108875998