从Google云端硬盘URI

时间:2017-12-04 12:07:41

标签: android uri filepath google-drive-android-api

我正在使用Android文件选择并从应用程序存储中选择文件(图像,视频,文档)。我有一个函数“getPath”。我从uri得到路径。我对图库图像或下载文档没有任何问题。但是当我从谷歌驱动器中选择一个文件时,我无法获得路径。这是google drive uri“content://com.google.android.apps.docs.storage/document/acc%3D25%3Bdoc%3D12” 你能帮我解决一下吗?

这也是我的“getPath”功能。

public static String getPath(final Context context, final Uri uri) {

    // check here to KITKAT or new version
    final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;

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

        // ExternalStorageProvider
        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];
            }
        }
        // DownloadsProvider
        else if (isDownloadsDocument(uri)) {

            final String id = DocumentsContract.getDocumentId(uri);
            final Uri contentUri = ContentUris.withAppendedId(
                    Uri.parse("content://downloads/public_downloads"),
                    Long.valueOf(id));

            return getDataColumn(context, contentUri, null, null);
        }
        // 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);
        }
        else if(isGoogleDriveUri(uri)){
                //Get google drive path here

        }
    }
    // 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();
    }

    return nopath;
}

public static String iStreamToString(InputStream is1)
{
    BufferedReader rd = new BufferedReader(new InputStreamReader(is1), 4096);
    String line;
    StringBuilder sb =  new StringBuilder();
    try {
        while ((line = rd.readLine()) != null) {
            sb.append(line);
        }
        rd.close();

    } catch (IOException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    String contentOfMyInputStream = sb.toString();
    return contentOfMyInputStream;
}

3 个答案:

答案 0 :(得分:6)

  

我对图库图片或下载文档没有任何问题

您将在许多设备上使用。

  

但是当我从谷歌驱动器中选择一个文件时,我无法获得路径

没有路径。 ACTION_GET_CONTENT不允许用户选择文件。它允许用户选择一段内容。该内容可能是本地文件。该内容也可能是:

您有两个主要选择。如果想要文件,请使用a third-party file chooser library替换问题中的所有代码。

或者,如果您仍想使用ACTION_GET_CONTENTACTION_OPEN_DOCUMENT,则可以Uri中的data.getData()获取onActivityResult()并执行两项操作事情:

  • 首先,使用DocumentFile.fromSingleUri()获取指向DocumentFile的{​​{1}}对象。您可以在Uri上致电getName()以获取内容的“显示名称”,这应该是用户可以识别的内容。

  • 然后,使用DocumentFileContentResolver来获取内容本身,类似于使用openInputStream()获取文件中的字节的方式。

答案 1 :(得分:5)

我也遇到了同样的问题,发现当我们从谷歌驱动器中选择图像时,它的uri就像下面一样

 Array
 (
     [0] => Array
         (
             [Loc] => 124
             [0] => 124
             [34] => 1
             [35] => 1
             [38] => 2
             [39] => 2
             [40] => 1
             [41] => 1
         )

     [1] => Array
         (
             [Loc] => 424
             [0] => 424
             [34] => 1
             [35] => 1
             [38] => 0
             [39] => 0
             [40] => 0
             [41] => 0
         )

     [2] => Array
         (
             [Loc] => 1512
             [0] => 1512
             [34] => 1
             [35] => 1
             [38] => 0
             [39] => 0
             [40] => 0
             [41] => 0
         )

     [3] => Array
         (
             [Loc] => 1612
             [0] => 1612
             [34] => 0
             [35] => 0
             [38] => 1
             [39] => 1
             [40] => 2
             [41] => 2
         )

     [4] => Array
         (
             [Loc] => 1711
             [0] => 1711
             [34] => 0
             [35] => 0
             [38] => 1
             [39] => 1
             [40] => 1
             [41] => 1
         )

 )

我们无法直接获取文件的路径,因为它不在我们的设备中。所以我们首先将文件下载到某个目的地然后我们可以使用该路径来完成我们的工作。以下是相同

的代码
com.google.android.apps.docs.storage

现在您的文件已保存在所需的目标路径中,您可以使用它。

答案 2 :(得分:2)

Get file path from Google Drive we can easily access by Using File Provider by using following steps Code is working fine.

1) Add provider path in AndroidManifest file inside Applcation Tag.
<application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme">
        <activity android:name="com.satya.filemangerdemo.activity.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <provider
            android:name="android.support.v4.content.FileProvider"
            android:authorities="${applicationId}.provider"
            android:exported="false"
            android:grantUriPermissions="true">
            <meta-data
                android:name="android.support.FILE_PROVIDER_PATHS"
                android:resource="@xml/provider_paths"/>
        </provider>
    </application>


2) provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:android="http://schemas.android.com/apk/res/android">
    <cache-path
        name="my_cache"
        path="." />
    <cache-path
        name="cache"
        path="." />
    <external-cache-path
        name="external_cache"
        path="." />
    <files-path
        name="files"
        path="." />
</paths>

3)FileUtils.java

public class FileUtils {
    private static Uri contentUri = null;
 @SuppressLint("NewApi")
    public static String getPath(final Context context, final Uri uri) {
        // check here to KITKAT or new version
        final boolean isKitKat = Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT;
        // DocumentProvider
        if (isKitKat && DocumentsContract.isDocumentUri(context, uri))
          {
            / MediaProvider
             if (isMediaDocument(uri)) {
                 if (isGoogleDriveUri(uri)) {
                return getDriveFilePath(uri, context);
            }


          }
      }

4) isGoogleDriveUri method 

  private static boolean isGoogleDriveUri(Uri uri) {
        return "com.google.android.apps.docs.storage".equals(uri.getAuthority()) || "com.google.android.apps.docs.storage.legacy".equals(uri.getAuthority());
    }

5)getDriveFilePath method 
 private static String getDriveFilePath(Uri uri, Context context) {
        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();
    }