使用 KitKat 存储访问框架后打开 Google Drive File Content URI

Posted

技术标签:

【中文标题】使用 KitKat 存储访问框架后打开 Google Drive File Content URI【英文标题】:Open a Google Drive File Content URI after using KitKat Storage Access Framework 【发布时间】:2014-09-30 00:42:42 【问题描述】:

我正在使用适用于 android 4.4 的存储访问框架并打开文件选择器。

除了从 Google Drive 中选择文件外,一切正常,我只能弄清楚如何将其作为输入流打开,但我想获得一个 java File 对象。

返回的内容 uri 如下所示:content://com.google.android.apps.docs.storage/document/acc%3D4%3Bdoc%3D2279

其他类似但没有可让我获取文件名、文件大小和内容的有效解决方案的问题:

Get real path from URI, Android KitKat new storage access framework Android Gallery on KitKat returns different Uri for Intent.ACTION_GET_CONTENT

我还查看了 Paul Burke 的 FileChooser (https://github.com/iPaulPro/aFileChooser),这是问题列表中最常见的问题。

如何从该内容 uri 中获取文件?

我目前的解决方法是从输入流中写出一个临时文件。

谢谢!

【问题讨论】:

你找到解决办法了吗? 【参考方案1】:

好的。我发现正确的方法是将来自其他帖子的输入流与来自 contentresolver 的一些数据结合使用。

这里有一些很难找到的 android 文档供参考:https://developer.android.com/training/secure-file-sharing/retrieve-info.html

获取mimetype、文件名和文件大小的相关代码:

Uri returnUri = returnIntent.getData();
String mimeType = getContentResolver().getType(returnUri);
Cursor returnCursor =
        getContentResolver().query(returnUri, null, null, null, null);
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
TextView nameView = (TextView) findViewById(R.id.filename_text);
TextView sizeView = (TextView) findViewById(R.id.filesize_text);
nameView.setText(returnCursor.getString(nameIndex));
sizeView.setText(Long.toString(returnCursor.getLong(sizeIndex)));

并获取文件内容:

getContentResolver().openInputStream(uri)

希望这对其他人有所帮助。

【讨论】:

遇到同样的问题,***.com/questions/30206483/… 请看一下,给出一些解决方案 它只获取文件名,但我想获取谷歌驱动文件的内容 uri 你找到了 mimeType,但你没有使用它。您使用参数“uri”调用“.openInputStream”,但您没有告诉我们您是如何获得该变量的。一些更多的信息将不胜感激.. @Moonbloom 知道文件名后可以创建一个空文件File.createTempFile(String prefix, String suffix),然后将InputStream复制到这个文件中。 ***.com/questions/11501418/…【参考方案2】:

这段代码解决了我的问题,当我尝试从谷歌驱动器中选择图像时,应用程序崩溃了,

 private void setImagePath(Intent data) throws Exception 

        String wholeID="";
        Uri selectedImage = data.getData();
        if(Build.VERSION.SDK_INT<=Build.VERSION_CODES.JELLY_BEAN_MR2)
            wholeID=getUriPreKitkat(selectedImage);
        else  
            wholeID = DocumentsContract.getDocumentId(selectedImage);

        

        // Split at colon, use second item in the array
        Log.i("debug","uri google drive "+wholeID);
        String id = wholeID.split(":")[1];

        String[] column = MediaStore.Images.Media.DATA;

        // where id is equal to
        String sel = MediaStore.Images.Media._ID + "=?";

        Cursor cursor = getActivity().getContentResolver().
                query(MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        column, sel, new String[]id, null);


        int columnIndex = cursor.getColumnIndex(column[0]);

        if (cursor.moveToFirst()) 
            filePath = cursor.getString(columnIndex);
        
        cursor.close();

    

【讨论】:

【参考方案3】:

添加到@Keith Entzeroth 答案,在得到 fileNamefileSizeInput Stream 之后,这是获取文件的方式

 public static File getFile(final Context context, final Uri uri) 
        Log.e(TAG,"inside getFile==");
        ContentResolver contentResolver = context.getContentResolver();
        try 
            String mimeType = contentResolver.getType(uri);
            Cursor returnCursor =
                    contentResolver.query(uri, null, null, null, null);
            int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
            int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
            returnCursor.moveToFirst();
            String fileName = returnCursor.getString(nameIndex);
            String fileSize = Long.toString(returnCursor.getLong(sizeIndex));
            InputStream inputStream =  contentResolver.openInputStream(uri);


            File tempFile = File.createTempFile(fileName, "");
            tempFile.deleteOnExit();
            FileOutputStream out = new FileOutputStream(tempFile);
            IOUtils.copyStream(inputStream,out);
            return tempFile;

          catch (Exception e)
            e.printStackTrace();
            return null;
        
    

【讨论】:

解决方案确实有效,但是文件扩展名旁边有一些数字

以上是关于使用 KitKat 存储访问框架后打开 Google Drive File Content URI的主要内容,如果未能解决你的问题,请参考以下文章

从URI获取真实路径,Android KitKat新的存储访问框架[重复]

如何在存储访问框架中设置不常见的文件扩展名?

KitKat ACTION_OPEN_DOCUMENT 在三星设备上不显示文档

使用存储访问框架打开特定目录

Android:从存储访问框架获得的 URI 中使用意图选择器打开文件

Android 4.4 KitKat 随机崩溃