如何在 Android 14 及更高版本中从 uri 获取 pdf 文件的路径而无需特定权限

问题描述 投票:0回答:1

我想获取pdf文件的路径,我从意向操作ACTION_OPEN_DOCUMENT中获取它作为uri,但是如果uri的媒体类型是文档,我如何获取它(通过调试我明白,我的代码第126行有什么问题)。对于图像,我没有任何问题,具有 read_media_images 或 read_external_storage 权限(适用于 android 12 及更低版本),但对于 pdf 文档,我有这个问题。我不想完全访问外部存储,因为谷歌播放可能会出现问题,因此是否可以在没有特殊权限的情况下获取pdf文件的路径,该路径在api 30及更高版本中使用以获得对外部存储的完全访问权限。非常感谢您的帮助。

package maximsblog.blogspot.com.visionsender;

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.text.TextUtils;

import androidx.loader.content.CursorLoader;

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;

class AndroidUtilities {
    static class IOUtils {
        private static final int BUFFER_SIZE = 1024 * 2;
        static int copy(InputStream input, OutputStream output) throws IOException {
            byte[] buffer = new byte[BUFFER_SIZE];
            BufferedInputStream b = new BufferedInputStream(input, BUFFER_SIZE);
            BufferedOutputStream out = new BufferedOutputStream(output, BUFFER_SIZE);
            int  count = 0;
            int n = 0;
            try {
                while((n =input.read(buffer, 0, BUFFER_SIZE))!= -1) {
                    out.write(buffer, 0, n);
                    count += n;
                }
                out.flush();
            } finally {
                try {
                    out.close();
                } catch (IOException e) {
                }
                try {
                    input.close();
                } catch (IOException e) {
                }
            }
            return count;
        }
    }
    static boolean isWhatsappUri(Uri uri) {
        return "com.whatsapp.provider.media".equals(uri.getAuthority());
    }
    static boolean isExternalStorageDocument(Uri uri) {
        return "com.android.externalstorage.documents".equals(uri.getAuthority());
    }

    static boolean isDownloadsDocument(Uri uri) {
        return "com.android.providers.downloads.documents".equals(uri.getAuthority());
    }

    static boolean isMediaDocument(Uri uri) {
        return "com.android.providers.media.documents".equals(uri.getAuthority());
    }

    static boolean isGooglePhotosUri(Uri uri) {
        return "com.google.android.apps.photos.content".equals(uri.getAuthority());
    }

    static String getDataColumn(Context context, Uri uri, String selection, String[] selectionArgs, String columnName) {
        Cursor cursor =null;
        if (columnName == null)
            columnName = "_data";
        try {
            cursor = context.getContentResolver().query(
                    uri, new String[] {columnName}, selection, selectionArgs,null);
            if (cursor == null) return uri.getPath();
            if (cursor.moveToFirst()) {
                int column_index = cursor.getColumnIndexOrThrow(columnName);
                if (columnName.equals("_data"))
                    return cursor.getString(column_index);
                else
                    return uri.toString() + "/" + cursor.getString(column_index);
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
        return null;
    }

    static String getDataColumn(Context context, Uri uri, String selection,
                                String[] selectionArgs) {
        return getDataColumn(context, uri, selection, selectionArgs, null);
    }

    @SuppressLint("NewApi")
    static String getRealPathFromURI_API19(Context context, Uri uri) {
        String result = null;
        if (DocumentsContract.isDocumentUri(context, uri)) {
            String[] split =null;
            String docId=null;
            if (isExternalStorageDocument(uri)) {
                docId = DocumentsContract.getDocumentId(uri);
                                                                                                                                                                                                                                                                                                                                                                                                                                              String type = split[0];
                if ("primary".equalsIgnoreCase(type)) {
                    return Environment.getExternalStorageDirectory().toString() + "/" + split[1];
                }
            } else if (isDownloadsDocument(uri)) {
                docId = DocumentsContract.getDocumentId(uri);
                Uri contentUri = ContentUris.withAppendedId(Uri.parse("content://downloads/public_downloads"), Long.valueOf(docId));
                return getDataColumn(context, contentUri, null, null);
            } else if (isMediaDocument(uri)) {
                docId = DocumentsContract.getDocumentId(uri);
                split = docId.split(":");
                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;
                }
                else if("document".equals(type)) { //in this line (126) we have a problems. How to get path of file for this case?
//contentUri =MediaStore.getDocumentUri(context,uri); //crash,when we call this method.
}
                String selection = "_id=?";
            return getDataColumn(context, contentUri, selection, new String[] {split[1]});
            }
        }
        else if ("content".equalsIgnoreCase(uri.getScheme())) {
            if (isGooglePhotosUri(uri))
                return uri.getLastPathSegment();
            return getDataColumn(context, uri, null, null);
        } else if ("file".equalsIgnoreCase(uri.getScheme())) {
            return uri.getPath();
        } else if (isWhatsappUri(uri)) {
            return getDataColumn(context, uri, null, null, "_display_name");
        }
        return null;
    }

    @SuppressLint("NewApi")
    static String getRealPathFromURI_API11to18(Context context, Uri contentUri) {
        if (isWhatsappUri(contentUri)) {
            return new File(contentUri.getPath()).getAbsolutePath();
        }
        String[] proj = new String[] {MediaStore.Images.Media.DATA};
        String result = null;
        CursorLoader cursorLoader = new CursorLoader(
                context,
                contentUri, proj, null, null, null
        );
        Cursor cursor = cursorLoader.loadInBackground();
        if (cursor != null) {
            cursor.moveToFirst();
            result = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
        }
        cursor.close();
        return result;
    }

    static String getRealPathFromURI_BelowAPI11(Context context, Uri contentUri) {
        if (isWhatsappUri(contentUri)) {
            return new File(contentUri.getPath()).getAbsolutePath();
        }
                Cursor cursor = context.getContentResolver().query(contentUri, new String[] {MediaStore.Images.Media.DATA}, null, null, null);
        cursor.moveToFirst();
        String result = cursor.getString(cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA));
        cursor.close();
        return result;
    }

    static String getRealPath(Context context, Uri uri) {
        if(Build.VERSION.SDK_INT < 11) return getRealPathFromURI_BelowAPI11(context, uri);
        else if(Build.VERSION.SDK_INT < 19) return getRealPathFromURI_API11to18(context, uri);
        else return getRealPathFromURI_API19(context, uri);
    }
    static String getFileName(String Fpath) {
        String[] result=Fpath.split("/");
        return result[result.length-1];
    }
    static void copy(Context context, Uri srcUri, File dstFile) {
        try {
            InputStream inputStream = context.getContentResolver().openInputStream(
                    srcUri);
            FileOutputStream outputStream = new FileOutputStream(dstFile);
            IOUtils.copy(inputStream, outputStream);
            inputStream.close();
            outputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    static String getFilePathFromURI(Context context, Uri contentUri) {
        String fileName = getFileName(contentUri.getPath());
        if (!TextUtils.isEmpty(fileName)) {
            File copyFile = new File(context.getCacheDir().toString() + "/" + fileName);
            copy(context, contentUri, copyFile);
            return copyFile.getAbsolutePath();
        }
        return null;
    }
}
java android kotlin uri android-external-storage
1个回答
0
投票

如何获取该文件的文件名

调用

DocumentFile.fromSingleUri()
获取代表由
DocumentFile
标识的文档的
Uri
。然后在 getName()
 上调用 
DocumentFile
 来获取显示名称。这可能是也可能不是“文件名”,但它应该是用户可识别的名称。

© www.soinside.com 2019 - 2024. All rights reserved.