如何在 Android Pie 中获取 pdf 文件的实际文件路径? [复制]

Posted

技术标签:

【中文标题】如何在 Android Pie 中获取 pdf 文件的实际文件路径? [复制]【英文标题】:How to get Actual file path of a pdf file in Android Pie? [duplicate] 【发布时间】:2019-05-27 22:34:31 【问题描述】:

目前我面临无法检索 pdf 的实际文件路径的问题。我尝试了所有我得到的解决方案,但无法在 android Pie 中获得实际的文件路径。任何帮助都将不胜感激。

代码:- 意图打开文件管理器并允许选择pdf文件。

Intent intent = new Intent();
intent.setType("application/pdf");
intent.setAction(Intent.ACTION_GET_CONTENT);
String[] mimetypes = "application/pdf";
intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
startActivityForResult(Intent.createChooser(intent, "Choose Pdf"), REQUEST_CODE_SELECT_IMAGE);

点击/选择任何 pdf 文件后编译器移动到 onActivityResult:-

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) 
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) 
        case REQUEST_CODE_SELECT_IMAGE:
            String template_file_uri = null;
            String extension = null;
            switch (resultCode) 
                case Activity.RESULT_OK:
                    try 

                        String path = null;
                        if (android.os.Build.VERSION.SDK_INT <= Build.VERSION_CODES.LOLLIPOP) 
                            Uri selectedFileUri = data.getData();
                            String mimeType = getContentResolver().getType(selectedFileUri);
                            Log.e(TAG, "onActivityResult() REQUEST_CODE_SELECT_IMAGE RESULT_OK uri : " + selectedFileUri + " mimetype " + mimeType);
                            Log.e(TAG, ":::>>selectedFileUri::: " + selectedFileUri);

                            int lastDot = selectedFileUri.toString().lastIndexOf('.');
                            if (lastDot == -1) 
                                // No dots - what do you want to do?
                                ApplicationHelper.showToast(activity, "Please select only pdf file !!!");
                             else 
                                extension = selectedFileUri.toString().substring(lastDot);
                                Log.e(TAG, "extension: " + extension);
                            

                            if (extension.equals(".pdf") || mimeType.equals("application/pdf")) 
                                template_file_uri = selectedFileUri.toString();
                                displayFromUri(selectedFileUri);
                                getRealPathFromURI = ApplicationHelper.getRealPathFromURI(activity, selectedFileUri);

                             else 
                                Log.e(TAG, "else ext: " + extension);
                                ApplicationHelper.showToast(activity, "Please select only pdf file !!!");
                                template_file_uri = null;
                            
                            Log.e(TAG, "::::>>>getRealPathFromURI::: " + getRealPathFromURI);

                         else 
                            Uri selectedFileUri = data.getData();
                            String path1 = getPath(activity, selectedFileUri);
                        

                     catch (Exception e) 
                        e.printStackTrace();
                    

                    break;

                case Activity.RESULT_CANCELED:
                    template_file_uri = null;
                    break;

                default:
                    break;
            
            break;

        default:
            break;

    

getRealPathFromURI 方法:-

@TargetApi(Build.VERSION_CODES.KITKAT)
public static String getRealPathFromURI(Context context, Uri uri) 
    Log.i(TAG, "getRealPathFromURI() uri " + uri);
    String pattern = "/^[ A-Za-z0-9_@./#&+-]*$/";
    uri = Uri.parse(uri.toString().replaceAll(pattern, uri.toString()));

    String path = FileUtils.getPath(context, uri);
    Log.i(TAG, "getRealPathFromURI() get path " + path);
    if (ApplicationHelper.isStringValid(path)) 
        if (!path.contains("://")) 
            path = "file://" + path;
        
        path = path.replaceAll(pattern, path);
        //path = path.replace(" ", "%20");
     else 
        path = uri.toString();
    
    Log.i(TAG, "getRealPathFromURI() return path " + path);
    return path;

FileUtils:-

 @TargetApi(Build.VERSION_CODES.KITKAT)
public static String getPath(final Context context, final Uri uri) 
    Log.i(TAG, "getPath() uri " + uri);
    if (DEBUG)
        Log.d(TAG + " File -",
                "Authority: " + uri.getAuthority() +
                        ", Fragment: " + uri.getFragment() +
                        ", Port: " + uri.getPort() +
                        ", Query: " + uri.getQuery() +
                        ", Scheme: " + uri.getScheme() +
                        ", Host: " + uri.getHost() +
                        ", Segments: " + uri.getPathSegments().toString()
        );

    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;


    if (isInternalStorageDocument(uri)) 
        return uri.toString();
    

    // DocumentProvider
    else if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) 

        if (isExternalStorageDocument(uri)) 
            final String docId = DocumentsContract.getDocumentId(uri);
            final String[] split = docId.split(":");
            final String type = split[0];

            if ("primary".equalsIgnoreCase(type)) 
                return Environment.getExternalStorageDirectory() + "/" + split[1];
            

            // TODO handle non-primary volumes
        
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) 

            try 
                final String id = DocumentsContract.getDocumentId(uri);
//                    final long id = Long.parseLong(DocumentsContract.getDocumentId(uri));
                final Uri contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), Long.valueOf(id));
                Log.e(TAG, "Uri....");
            return getDataColumn(context, contentUri, null, null);
             catch (NumberFormatException e) 
                e.printStackTrace();
            
        
        // MediaProvider
        else 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;
            

            final String selection = "_id=?";
            final String[] selectionArgs = new String[]
                    split[1]
            ;

            return getDataColumn(context, contentUri, selection, selectionArgs);
        
    
    // MediaStore (and general)
    else if ("content".equalsIgnoreCase(uri.getScheme())) 

        // Return the remote address
        if (isGooglePhotosUri(uri))
            return uri.getLastPathSegment();

        return getDataColumn(context, uri, null, null);
    
    // File
    else if ("file".equalsIgnoreCase(uri.getScheme())) 
        return uri.getPath();
     else if (!ApplicationHelper.haveAuthority(uri)) 
        return Constants.AUTHORITY_FILE + uri.toString();
    

    return null;

【问题讨论】:

您可以在这里发布您所做的代码吗? 你需要什么文件路径?你不能只使用它的InputStream吗? 如果遇到任何崩溃,请将代码与堆栈跟踪一起发布。 请查看更新后的问题。 @theapache64。我也使用了 InputStream 但没有得到任何东西。 请查看更新后的问题。 @ChintakPatel 【参考方案1】:

使用下面的类文件,只需传递 Uri 即可提供文件路径。

然后申请为

val filePathFromUri = FilePath.getPath(this, uri)
val file = File(filePathFromUri)
val absolutePath = file.absolutePath

在您的代码中,您可以在 onActivityResult() 中获取 Uri。

import android.annotation.TargetApi
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 java.util.*

object FilePath 
    val imageExts: ArrayList<String>
        get() 
            val imageTypes = arrayOf("png", "jpg", "jpeg", "bmp", "gif")
            val imageExts = imageTypes.indices.mapTo(ArrayList())  imageTypes[it] 

            return imageExts
        

    val videoExts: ArrayList<String>
        get() 
            val videoTypes = arrayOf("mpeg", "mp4", "gif", "wmv", "mov", "mpg", "3gp", "flv")
            val videoExts = videoTypes.indices.mapTo(ArrayList())  videoTypes[it] 
            return videoExts
        

    val docExts: ArrayList<String>
        get() 
            val docTypes = arrayOf("doc", "docx", "pdf", "txt")
            val docExts = docTypes.indices.mapTo(ArrayList())  docTypes[it] 
            return docExts
        


    @TargetApi(Build.VERSION_CODES.KITKAT)
    fun getPath(context: Context, uri: Uri): String? 

        val isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT

        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri)) 
            // ExternalStorageProvider
            if (isExternalStorageDocument(uri)) 

                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":".toRegex()).dropLastWhile  it.isEmpty() .toTypedArray()
                val type = split[0]

                if ("primary".equals(type, ignoreCase = true)) 
                    return Environment.getExternalStorageDirectory().toString() + "/" + split[1]
                
             else if (isDownloadsDocument(uri)) 

                val decodedURI = Uri.decode(uri.toString())

                if (decodedURI.contains("raw:")) 
                    return decodedURI.substring(decodedURI.indexOf("raw:") + 4)
                

                val id = DocumentsContract.getDocumentId(Uri.parse(decodedURI))

                val contentUri = ContentUris.withAppendedId(
                        Uri.parse("content://downloads/public_downloads"), java.lang.Long.valueOf(id)!!)

                return getDataColumn(context, contentUri, null, null)
             else if (isMediaDocument(uri)) 

                val docId = DocumentsContract.getDocumentId(uri)
                val split = docId.split(":".toRegex()).dropLastWhile  it.isEmpty() .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 = "_id=?"
                val selectionArgs = arrayOf(split[1])

                return getDataColumn(context, contentUri, selection, selectionArgs)
            // MediaProvider
            // DownloadsProvider
         else if ("content".equals(uri.scheme, ignoreCase = true)) 
            return getDataColumn(context, uri, null, null)
         else if ("file".equals(uri.scheme, ignoreCase = true)) 
            return uri.path
        // File
        // MediaStore (and general)

        return null
    

    /**
     * Get the value of the data column for this Uri. This is useful for
     * MediaStore Uris, and other file-based ContentProviders.
     *
     * @param context The context.
     * @param uri The Uri to query.
     * @param selection (Optional) Filter used in the query.
     * @param selectionArgs (Optional) Selection arguments used in the query.
     * @return The value of the _data column, which is typically a file path.
     */
    fun getDataColumn(context: Context, uri: Uri?, selection: String?,
                      selectionArgs: Array<String>?): String? 

        var cursor: Cursor? = null
        val column = "_data"
        val projection = arrayOf(column)

        try 
            cursor = context.contentResolver.query(uri!!, projection, selection, selectionArgs, null)
            if (cursor != null && cursor.moveToFirst()) 
                val column_index = cursor.getColumnIndexOrThrow(column)
                return cursor.getString(column_index)
            
         finally 
            if (cursor != null)
                cursor.close()
        
        return null
    


    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is ExternalStorageProvider.
     */
    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.
     */
    fun isDownloadsDocument(uri: Uri): Boolean 
        return "com.android.providers.downloads.documents" == uri.authority
    

    /**
     * @param uri The Uri to check.
     * @return Whether the Uri authority is MediaProvider.
     */
    fun isMediaDocument(uri: Uri): Boolean 
        return "com.android.providers.media.documents" == uri.authority
    

【讨论】:

你能发布一个Java的答案吗?

以上是关于如何在 Android Pie 中获取 pdf 文件的实际文件路径? [复制]的主要内容,如果未能解决你的问题,请参考以下文章

如何从android pie中的内容uri获取文件路径

如何解决 GPS 在后台 android Pie 中自动关闭?

FusedLocationProviderClient 在 Android Pie 9.0 中返回错误的纬度经度

如何在Android 9(Pie)中备份数据库?

Android(9)Pie中如何允许所有网络连接类型HTTP和HTTPS?

Python matplotlib pie饼图中文乱码