如何在 Android 10 上从图库中获取所选视频的路径

huangapple go评论150阅读模式
英文:

How to get the path of a video which is selected from gallery on android 10

问题

我尝试了很多代码片段以下是我现在正在使用的代码我知道 MediaStore.Video.Media.DATA 已被弃用但不知何故这种方法在 Android 10 上也能工作但有时会抛出

> android.database.CursorIndexOutOfBoundsException: 请求索引 0尺寸为 0

public static String getvideoPath(Context context, Uri uri) {
    try {
        Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
        cursor.moveToFirst();
        String document_id = cursor.getString(0);
        LogMessage.v("文档 ID: "+document_id);
        if (document_id != null) {
            document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
            cursor.close();
            cursor = context.getContentResolver().query(
                    MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
                    null, MediaStore.Video.Media._ID + " = ? ", new String[]{document_id}, null);
            cursor.moveToFirst();
            String path = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
            cursor.close();
            return path;
        } else
            return getPath(context, uri);
    } catch (Exception e) {
        e.printStackTrace();
        return getPath(context, uri);
    }
}

private static String getPath(Context context, Uri uri) {
    try {
        String[] proj = { MediaStore.Video.Media.DATA };
        Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
        cursor.moveToFirst();
        String document_id = cursor.getString(0);
        return document_id;
    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
英文:

I tried lot of snippets. This is what I'm using now. I know that MediaStore.Video.Media.DATA is deprecated.somehow this method is working on android 10 as well but sometimes it throws

> android.database.CursorIndexOutOfBoundsException: Index 0 requested, with a size of 0

public static String getvideoPath(Context context, Uri uri) {
try {
Cursor cursor = context.getContentResolver().query(uri, null, null, null, null);
cursor.moveToFirst();
String document_id = cursor.getString(0);
LogMessage.v("Document Id:: "+document_id);
if(document_id!=null){
document_id = document_id.substring(document_id.lastIndexOf(":") + 1);
cursor.close();
cursor = context.getContentResolver().query(
MediaStore.Video.Media.EXTERNAL_CONTENT_URI,
null, MediaStore.Video.Media._ID + " = ? ", new String[]{document_id}, null);
cursor.moveToFirst();
String path = cursor.getString(cursor.getColumnIndex(MediaStore.Video.Media.DATA));
cursor.close();
return path;
}else
return getPath(context,uri);
} catch (Exception e) {
e.printStackTrace();
return getPath(context,uri);
}
}
private static String getPath(Context context,Uri uri){
try {
String[] proj = { MediaStore.Video.Media.DATA };
Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
cursor.moveToFirst();
String document_id = cursor.getString(0);
return document_id;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}

答案1

得分: 6

@SuppressLint("NewApi")
public String getPath(final Uri uri) {
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
    String selection = null;
    String[] selectionArgs = null;

    if (isKitKat) {
        if (isExternalStorageDocument(uri)) {
            // ... (Code block)
        }

        if (isDownloadsDocument(uri)) {
            // ... (Code block)
        }

        if (isMediaDocument(uri)) {
            // ... (Code block)
        }

        if (isGoogleDriveUri(uri)) {
            // ... (Code block)
        }

        if (isWhatsAppFile(uri)) {
            // ... (Code block)
        }

        if ("content".equalsIgnoreCase(uri.getScheme())) {
            // ... (Code block)
        }

        if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        }
    } else {
        if (isWhatsAppFile(uri)) {
            // ... (Code block)
        }

        if ("content".equalsIgnoreCase(uri.getScheme())) {
            // ... (Code block)
        }
    }

    return null;
}

private boolean fileExists(String filePath) {
    // ... (Code block)
}

private String getPathFromExtSD(String[] pathData) {
    // ... (Code block)
}

private String getDriveFilePath(Uri uri) {
    // ... (Code block)
}

private String copyFileToInternalStorage(Uri uri, String newDirName) {
    // ... (Code block)
}

private String getFilePathForWhatsApp(Uri uri) {
    // ... (Code block)
}

private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
    // ... (Code block)
}

private boolean isExternalStorageDocument(Uri uri) {
    // ... (Code block)
}

private boolean isDownloadsDocument(Uri uri) {
    // ... (Code block)
}

private boolean isMediaDocument(Uri uri) {
    // ... (Code block)
}

private boolean isGooglePhotosUri(Uri uri) {
    // ... (Code block)
}

public boolean isWhatsAppFile(Uri uri) {
    // ... (Code block)
}

private boolean isGoogleDriveUri(Uri uri) {
    // ... (Code block)
}

请注意,上述翻译的代码段可能存在排版问题,原始代码中的注释可能没有完全包括在内。此外,代码中的函数实现部分也被忽略,只返回了函数签名部分。如果您需要完整的代码实现,请使用原始英文代码。

英文:

Get real path of video selected from gallery with below method

@SuppressLint("NewApi")
public  String getPath( final Uri uri) {
// check here to KITKAT or new version
final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
String selection = null;
String[] selectionArgs = null;
// DocumentProvider
if (isKitKat ) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
String fullPath = getPathFromExtSD(split);
if (fullPath != "") {
return fullPath;
} else {
return null;
}
}
// DownloadsProvider
if (isDownloadsDocument(uri)) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
final String id;
Cursor cursor = null;
try {
cursor = context.getContentResolver().query(uri, new String[]{MediaStore.MediaColumns.DISPLAY_NAME}, null, null, null);
if (cursor != null && cursor.moveToFirst()) {
String fileName = cursor.getString(0);
String path = Environment.getExternalStorageDirectory().toString() + "/Download/" + fileName;
if (!TextUtils.isEmpty(path)) {
return path;
}
}
}
finally {
if (cursor != null)
cursor.close();
}
id = DocumentsContract.getDocumentId(uri);
if (!TextUtils.isEmpty(id)) {
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
String[] contentUriPrefixesToTry = new String[]{
"content://downloads/public_downloads",
"content://downloads/my_downloads"
};
for (String contentUriPrefix : contentUriPrefixesToTry) {
try {
final Uri contentUri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), Long.valueOf(id));
return getDataColumn(context, contentUri, null, null);
} catch (NumberFormatException e) {
//In Android 8 and Android P the id is not a number
return uri.getPath().replaceFirst("^/document/raw:", "").replaceFirst("^raw:", "");
}
}
}
}
else {
final String id = DocumentsContract.getDocumentId(uri);
if (id.startsWith("raw:")) {
return id.replaceFirst("raw:", "");
}
try {
contentUri = ContentUris.withAppendedId(
Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
}
catch (NumberFormatException e) {
e.printStackTrace();
}
if (contentUri != null) {
return getDataColumn(context, contentUri, null, null);
}
}
}
// MediaProvider
if (isMediaDocument(uri)) {
final String docId = DocumentsContract.getDocumentId(uri);
final String[] split = docId.split(":");
final String type = split[0];
Uri contentUri = null;
if ("image".equals(type)) {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI;
} else if ("video".equals(type)) {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI;
} else if ("audio".equals(type)) {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI;
}
selection = "_id=?";
selectionArgs = new String[]{split[1]};
return getDataColumn(context, contentUri, selection,
selectionArgs);
}
if (isGoogleDriveUri(uri)) {
return getDriveFilePath(uri);
}
if(isWhatsAppFile(uri)){
return getFilePathForWhatsApp(uri);
}
if ("content".equalsIgnoreCase(uri.getScheme())) {
if (isGooglePhotosUri(uri)) {
return uri.getLastPathSegment();
}
if (isGoogleDriveUri(uri)) {
return getDriveFilePath(uri);
}
if( Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q)
{
// return getFilePathFromURI(context,uri);
return copyFileToInternalStorage(uri,"userfiles");
// return getRealPathFromURI(context,uri);
}
else
{
return getDataColumn(context, uri, null, null);
}
}
if ("file".equalsIgnoreCase(uri.getScheme())) {
return uri.getPath();
}
}
else {
if(isWhatsAppFile(uri)){
return getFilePathForWhatsApp(uri);
}
if ("content".equalsIgnoreCase(uri.getScheme())) {
String[] projection = {
MediaStore.Images.Media.DATA
};
Cursor cursor = null;
try {
cursor = context.getContentResolver()
.query(uri, projection, selection, selectionArgs, null);
int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
if (cursor.moveToFirst()) {
return cursor.getString(column_index);
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
return null;
}
private  boolean fileExists(String filePath) {
File file = new File(filePath);
return file.exists();
}
private String getPathFromExtSD(String[] pathData) {
final String type = pathData[0];
final String relativePath = "/" + pathData[1];
String fullPath = "";
// on my Sony devices (4.4.4 & 5.1.1), `type` is a dynamic string
// something like "71F8-2C0A", some kind of unique id per storage
// don't know any API that can get the root path of that storage based on its id.
//
// so no "primary" type, but let the check here for other devices
if ("primary".equalsIgnoreCase(type)) {
fullPath = Environment.getExternalStorageDirectory() + relativePath;
if (fileExists(fullPath)) {
return fullPath;
}
}
// Environment.isExternalStorageRemovable() is `true` for external and internal storage
// so we cannot relay on it.
//
// instead, for each possible path, check if file exists
// we'll start with secondary storage as this could be our (physically) removable sd card
fullPath = System.getenv("SECONDARY_STORAGE") + relativePath;
if (fileExists(fullPath)) {
return fullPath;
}
fullPath = System.getenv("EXTERNAL_STORAGE") + relativePath;
if (fileExists(fullPath)) {
return fullPath;
}
return fullPath;
}
private String getDriveFilePath(Uri uri) {
Uri returnUri = uri;
Cursor returnCursor = context.getContentResolver().query(returnUri, null, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
*     * move to the first row in the Cursor, get the data,
*     * and display it.
* */
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
String name = (returnCursor.getString(nameIndex));
String size = (Long.toString(returnCursor.getLong(sizeIndex)));
File file = new File(context.getCacheDir(), name);
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(file);
int read = 0;
int maxBufferSize = 1 * 1024 * 1024;
int bytesAvailable = inputStream.available();
//int bufferSize = 1024;
int bufferSize = Math.min(bytesAvailable, maxBufferSize);
final byte[] buffers = new byte[bufferSize];
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
Log.e("File Size", "Size " + file.length());
inputStream.close();
outputStream.close();
Log.e("File Path", "Path " + file.getPath());
Log.e("File Size", "Size " + file.length());
} catch (Exception e) {
Log.e("Exception", e.getMessage());
}
return file.getPath();
}
/***
* Used for Android Q+
* @param uri
* @param newDirName if you want to create a directory, you can set this variable
* @return
*/
private String copyFileToInternalStorage(Uri uri,String newDirName) {
Uri returnUri = uri;
Cursor returnCursor = context.getContentResolver().query(returnUri, new String[]{
OpenableColumns.DISPLAY_NAME,OpenableColumns.SIZE
}, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
*     * move to the first row in the Cursor, get the data,
*     * and display it.
* */
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
String name = (returnCursor.getString(nameIndex));
String size = (Long.toString(returnCursor.getLong(sizeIndex)));
File output;
if(!newDirName.equals("")) {
File dir = new File(context.getFilesDir() + "/" + newDirName);
if (!dir.exists()) {
dir.mkdir();
}
output = new File(context.getFilesDir() + "/" + newDirName + "/" + name);
}
else{
output = new File(context.getFilesDir() + "/" + name);
}
try {
InputStream inputStream = context.getContentResolver().openInputStream(uri);
FileOutputStream outputStream = new FileOutputStream(output);
int read = 0;
int bufferSize = 1024;
final byte[] buffers = new byte[bufferSize];
while ((read = inputStream.read(buffers)) != -1) {
outputStream.write(buffers, 0, read);
}
inputStream.close();
outputStream.close();
}
catch (Exception e) {
Log.e("Exception", e.getMessage());
}
return output.getPath();
}
private String getFilePathForWhatsApp(Uri uri){
return  copyFileToInternalStorage(uri,"whatsapp");
}
private String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs) {
Cursor cursor = null;
final String column = "_data";
final String[] projection = {column};
try {
cursor = context.getContentResolver().query(uri, projection,
selection, selectionArgs, null);
if (cursor != null && cursor.moveToFirst()) {
final int index = cursor.getColumnIndexOrThrow(column);
return cursor.getString(index);
}
}
finally {
if (cursor != null)
cursor.close();
}
return null;
}
private  boolean isExternalStorageDocument(Uri uri) {
return "com.android.externalstorage.documents".equals(uri.getAuthority());
}
private  boolean isDownloadsDocument(Uri uri) {
return "com.android.providers.downloads.documents".equals(uri.getAuthority());
}
private  boolean isMediaDocument(Uri uri) {
return "com.android.providers.media.documents".equals(uri.getAuthority());
}
private  boolean isGooglePhotosUri(Uri uri) {
return "com.google.android.apps.photos.content".equals(uri.getAuthority());
}
public boolean isWhatsAppFile(Uri uri){
return "com.whatsapp.provider.media".equals(uri.getAuthority());
}
private  boolean isGoogleDriveUri(Uri uri) {
return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());
}

Happy Coding.

答案2

得分: 3

以下是您提供的代码部分的中文翻译:

// 导入必要的库
import ...

// 创建一个名为FileManager的对象
object FileManager {
    
    // 获取路径的函数
    fun getPath(context: Context, uri: Uri): String? {
        // 检查Android版本是否大于等于KITKAT
        val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT
        var selection: String? = null
        var selectionArgs: Array<String>? = null
        
        if (isKitKat) {
            // 根据URI的不同类型进行处理
            if (isExternalStorageDocument(uri)) {
                // 处理外部存储的文档类型
                ...
            }
            else if (isDownloadsDocument(uri)) {
                // 处理下载文件的文档类型
                ...
            }
            else if (isMediaDocument(uri)) {
                // 处理媒体文件的文档类型
                ...
            }
            else if (isGoogleDriveUri(uri)) {
                // 处理Google Drive文件的URI
                ...
            }
            else if (isWhatsAppFile(uri)) {
                // 处理WhatsApp文件的URI
                ...
            }
            else if ("content" == uri.scheme) {
                // 处理content类型的URI
                ...
            }
            else if ("file" == uri.scheme) {
                // 处理file类型的URI
                ...
            }
        }
        else {
            // 在Android版本低于KITKAT时的处理
            ...
        }
        
        return null
    }
    
    // 其他辅助函数...
    ...
}

// 启动选择文件的Intent
val intent = Intent(ACTION_GET_CONTENT)
intent.apply {
    type = "application/pdf"
    addCategory(Intent.CATEGORY_OPENABLE)
}
resultLauncher.launch(intent)

// 处理选择文件的结果
private val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result ->
    if (result.resultCode == Activity.RESULT_OK) {
        var file: File? = null
        val disposable = Single.fromCallable {
            val filePath = FileManager.getPath(this, result?.data?.data!!)
            file = File(filePath)
        }.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe({
            Timber.d("==File==Path===${file?.path}\nname==${file?.name}\nabsolutePath =${file?.absolutePath}")

        }, {
            it.printStackTrace()
        })
    }
}

注意:由于部分内容包含HTML转义字符(如">"和"""),这可能会导致在代码中显示不正确。实际应用中,您应该将这些转义字符还原为它们原来的字符。

英文:

The above answer which is given by tushar is abosulity correct, I have converted that code into kotlin, might be it helps someone.

import android.annotation.SuppressLint
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.text.TextUtils
import timber.log.Timber
import java.io.File
import java.io.FileOutputStream
import java.io.InputStream
import kotlin.math.min
@SuppressLint(&quot;Recycle&quot;)
@Suppress(&quot;RECEIVER_NULLABILITY_MISMATCH_BASED_ON_JAVA_ANNOTATIONS&quot;, &quot;DEPRECATION&quot;)
object FileManager {
fun getPath(context: Context, uri: Uri): String? {
// check here to KITKAT or new version
val isKitKat = Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.KITKAT
var selection: String? = null
var selectionArgs: Array&lt;String&gt;? = null
// DocumentProvider
if (isKitKat) {
// ExternalStorageProvider
if (isExternalStorageDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(&quot;:&quot;.toRegex()).toTypedArray()
//val type = split[0]
val fullPath = getPathFromExtSD(split)
return if (fullPath !== &quot;&quot;) {
fullPath
} else {
null
}
}
// DownloadsProvider
if (isDownloadsDocument(uri)) {
if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.M) {
var cursor: Cursor? = null
try {
cursor = context.contentResolver.query(uri, arrayOf(MediaStore.MediaColumns.DISPLAY_NAME), null, null, null)
if (cursor != null &amp;&amp; cursor.moveToFirst()) {
val fileName: String = cursor.getString(0)
val path: String = Environment.getExternalStorageDirectory().toString() + &quot;/Download/&quot; + fileName
if (!TextUtils.isEmpty(path)) {
return path
}
}
} finally {
cursor?.close()
}
val id: String = DocumentsContract.getDocumentId(uri)
if (!TextUtils.isEmpty(id)) {
if (id.startsWith(&quot;raw:&quot;)) {
return id.replaceFirst(&quot;raw:&quot;.toRegex(), &quot;&quot;)
}
val contentUriPrefixesToTry = arrayOf(&quot;content://downloads/public_downloads&quot;, &quot;content://downloads/my_downloads&quot;)
for (contentUriPrefix in contentUriPrefixesToTry) {
return try {
val contentUri: Uri = ContentUris.withAppendedId(Uri.parse(contentUriPrefix), java.lang.Long.valueOf(id))
getDataColumn(context, contentUri, null, null)
} catch (e: NumberFormatException) {
//In Android 8 and Android P the id is not a number
uri.path?.replaceFirst(&quot;^/document/raw:&quot;, &quot;&quot;)?.replaceFirst(&quot;^raw:&quot;, &quot;&quot;)
}
}
}
} else {
val id = DocumentsContract.getDocumentId(uri)
if (id.startsWith(&quot;raw:&quot;)) {
return id.replaceFirst(&quot;raw:&quot;.toRegex(), &quot;&quot;)
}
var contentUri : Uri?= null
try {
contentUri = ContentUris.withAppendedId(Uri.parse(&quot;content://downloads/public_downloads&quot;), java.lang.Long.valueOf(id))
} catch (e: NumberFormatException) {
e.printStackTrace()
}
if (contentUri != null) {
return getDataColumn(context, contentUri, null, null)
}
}
}
// MediaProvider
if (isMediaDocument(uri)) {
val docId = DocumentsContract.getDocumentId(uri)
val split = docId.split(&quot;:&quot;.toRegex()).toTypedArray()
val type = split[0]
var contentUri: Uri? = null
when (type) {
&quot;image&quot; -&gt; {
contentUri = MediaStore.Images.Media.EXTERNAL_CONTENT_URI
}
&quot;video&quot; -&gt; {
contentUri = MediaStore.Video.Media.EXTERNAL_CONTENT_URI
}
&quot;audio&quot; -&gt; {
contentUri = MediaStore.Audio.Media.EXTERNAL_CONTENT_URI
}
}
selection = &quot;_id=?&quot;
selectionArgs = arrayOf(split[1])
return getDataColumn(context, contentUri!!, selection, selectionArgs)
}
if (isGoogleDriveUri(uri)) {
return getDriveFilePath(context,uri)
}
if (isWhatsAppFile(uri)) {
return getFilePathForWhatsApp(context, uri)
}
if (&quot;content&quot;.equals(uri.scheme, ignoreCase = true)) {
if (isGooglePhotosUri(uri)) {
return uri.lastPathSegment
}
if (isGoogleDriveUri(uri)) {
return getDriveFilePath(context, uri)
}
return if (Build.VERSION.SDK_INT &gt;= Build.VERSION_CODES.Q) {
// return getFilePathFromURI(context,uri);
copyFileToInternalStorage(context, uri, &quot;userfiles&quot;)
// return getRealPathFromURI(context,uri);
} else {
getDataColumn(context, uri, null, null)
}
}
if (&quot;file&quot;.equals(uri.scheme, ignoreCase = true)) {
return uri.path
}
} else {
if (isWhatsAppFile(uri)) {
return getFilePathForWhatsApp(context, uri)
}
if (&quot;content&quot;.equals(uri.scheme, ignoreCase = true)) {
val projection = arrayOf(MediaStore.Images.Media.DATA)
val cursor: Cursor
try {
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)!!
val columnIndex: Int = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA)
if (cursor.moveToFirst()) {
return cursor.getString(columnIndex)
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
return null
}
private fun fileExists(filePath: String): Boolean {
val file = File(filePath)
return file.exists()
}
private fun getPathFromExtSD(pathData: Array&lt;String&gt;): String {
val type = pathData[0]
val relativePath = &quot;/&quot; + pathData[1]
var fullPath : String
// on my Sony devices (4.4.4 &amp; 5.1.1), `type` is a dynamic string
// something like &quot;71F8-2C0A&quot;, some kind of unique id per storage
// don&#39;t know any API that can get the root path of that storage based on its id.
//
// so no &quot;primary&quot; type, but let the check here for other devices
if (&quot;primary&quot;.equals(type, ignoreCase = true)) {
fullPath = Environment.getExternalStorageDirectory().toString() + relativePath
if (fileExists(fullPath)) {
return fullPath
}
}
// Environment.isExternalStorageRemovable() is `true` for external and internal storage
// so we cannot relay on it.
//
// instead, for each possible path, check if file exists
// we&#39;ll start with secondary storage as this could be our (physically) removable sd card
fullPath = System.getenv(&quot;SECONDARY_STORAGE&quot;) + relativePath
if (fileExists(fullPath)) {
return fullPath
}
fullPath = System.getenv(&quot;EXTERNAL_STORAGE&quot;) + relativePath
return if (fileExists(fullPath)) {
fullPath
} else fullPath
}
private fun getDriveFilePath(context: Context, uri: Uri): String? {
val returnUri: Uri = uri
val returnCursor: Cursor = context.contentResolver.query(returnUri, null, null, null, null)!!
/*
* Get the column indexes of the data in the Cursor,
*     * move to the first row in the Cursor, get the data,
*     * and display it.
* */
val nameIndex: Int = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
// val sizeIndex: Int = returnCursor.getColumnIndex(OpenableColumns.SIZE)
returnCursor.moveToFirst()
val name: String = returnCursor.getString(nameIndex)
// val size = returnCursor.getLong(sizeIndex).toString()
val file = File(context.cacheDir, name)
try {
val inputStream: InputStream? = context.contentResolver.openInputStream(uri)
val outputStream = FileOutputStream(file)
var read : Int
val maxBufferSize = 1 * 1024 * 1024
val bytesAvailable: Int = inputStream?.available()!!
//int bufferSize = 1024;
val bufferSize = min(bytesAvailable, maxBufferSize)
val buffers = ByteArray(bufferSize)
while (inputStream.read(buffers).also { read = it } != -1) {
outputStream.write(buffers, 0, read)
}
Timber.d(&quot;File Size Size ${file.length()}&quot;)
inputStream.close()
outputStream.close()
Timber.d(&quot;File Path Path ${file.path}&quot;)
Timber.d(&quot;File Size Size ${file.length()}&quot;)
} catch (e: Exception) {
Timber.e(&quot;Exception ${e.message}&quot;)
}
return file.path
}
/***
* Used for Android Q+
* @param uri
* @param newDirName if you want to create a directory, you can set this variable
* @return
*/
private fun copyFileToInternalStorage(context: Context, uri: Uri, newDirName: String): String? {
val returnUri: Uri = uri
val returnCursor: Cursor = context.contentResolver.query(returnUri, arrayOf(OpenableColumns.DISPLAY_NAME, OpenableColumns.SIZE), null, null, null)!!
/*
* Get the column indexes of the data in the Cursor,
*     * move to the first row in the Cursor, get the data,
*     * and display it.
* */
val nameIndex: Int = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
//val sizeIndex: Int = returnCursor.getColumnIndex(OpenableColumns.SIZE)
returnCursor.moveToFirst()
val name: String = returnCursor.getString(nameIndex)
// val size = returnCursor.getLong(sizeIndex).toString()
val output: File = if (newDirName != &quot;&quot;) {
val dir = File(context.filesDir.toString() + &quot;/&quot; + newDirName)
if (!dir.exists()) {
dir.mkdir()
}
File(context.filesDir.toString() + &quot;/&quot; + newDirName + &quot;/&quot; + name)
} else {
File(context.filesDir.toString() + &quot;/&quot; + name)
}
try {
val inputStream: InputStream? = context.contentResolver.openInputStream(uri)
val outputStream = FileOutputStream(output)
var read = 0
val bufferSize = 1024
val buffers = ByteArray(bufferSize)
while (inputStream?.read(buffers).also {
if (it != null) {
read = it
}
} != -1) {
outputStream.write(buffers, 0, read)
}
inputStream?.close()
outputStream.close()
} catch (e: Exception) {
Timber.e(&quot;Exception${e.message}&quot;)
}
return output.path
}
private fun getFilePathForWhatsApp(context: Context, uri: Uri): String? {
return copyFileToInternalStorage(context, uri, &quot;whatsapp&quot;)
}
private fun getDataColumn(context: Context, uri: Uri, selection: String?, selectionArgs: Array&lt;String&gt;?): String? {
var cursor: Cursor? = null
val column = &quot;_data&quot;
val projection = arrayOf(column)
try {
cursor = context.contentResolver.query(uri, projection, selection, selectionArgs, null)
if (cursor != null &amp;&amp; cursor.moveToFirst()) {
val index: Int = cursor.getColumnIndexOrThrow(column)
return cursor.getString(index)
}
} finally {
cursor?.close()
}
return null
}
private fun isExternalStorageDocument(uri: Uri): Boolean {
return &quot;com.android.externalstorage.documents&quot; == uri.authority
}
private fun isDownloadsDocument(uri: Uri): Boolean {
return &quot;com.android.providers.downloads.documents&quot; == uri.authority
}
private fun isMediaDocument(uri: Uri): Boolean {
return &quot;com.android.providers.media.documents&quot; == uri.authority
}
private fun isGooglePhotosUri(uri: Uri): Boolean {
return &quot;com.google.android.apps.photos.content&quot; == uri.authority
}
private fun isWhatsAppFile(uri: Uri): Boolean {
return &quot;com.whatsapp.provider.media&quot; == uri.authority
}
private fun isGoogleDriveUri(uri: Uri): Boolean {
return &quot;com.google.android.apps.docs.storage&quot; == uri.authority || &quot;com.google.android.apps.docs.storage.legacy&quot; == uri.authority
}
}

To launch

 val intent = Intent(ACTION_GET_CONTENT)
intent.apply {
type = &quot;application/pdf&quot;
addCategory(Intent.CATEGORY_OPENABLE)
}
resultLauncher.launch(intent)

and you can get the result in your acivity

 private val resultLauncher = registerForActivityResult(ActivityResultContracts.StartActivityForResult()) { result -&gt;
if (result.resultCode == Activity.RESULT_OK) {
var file: File? = null
val disposable = Single.fromCallable {
val filePath = FileManager.getPath(this, result?.data?.data!!)
file = File(filePath)
}.subscribeOn(Schedulers.io()).observeOn(AndroidSchedulers.mainThread()).subscribe({
Timber.d(&quot;==File==Path===${file?.path}\nname==${file?.name}\nabsolutePath =${file?.absolutePath}&quot;)
}, {
it.printStackTrace()
})
}
}

答案3

得分: -2

你不会尝试在Android 10中将URI转换为文件系统路径。

即使你成功管理了路径,它大多数情况下也是不可访问的。

你并不经常阅读stackoverflow页面,是吗?

英文:

You will not try yo convert an uri to a file system path in Android 10.

Even if you manage the path is mostly not accessable.

You are not a regular reader of stackoverflow pages are you?

huangapple
  • 本文由 发表于 2020年7月25日 13:41:28
  • 转载请务必保留本文链接:https://go.coder-hub.com/63084806.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定