web-dev-qa-db-ja.com

GoogleドライブURIからパスを取得

Androidファイル選択とアプリストレージ(画像、動画、ドキュメント)からのファイルの選択)を使用しています。「getPath」関数があります。uriからパスを取得しています。ギャラリーには問題ありません。画像またはドキュメントをダウンロードします。しかし、Googleドライブからファイルを選択すると、パスを取得できません。これは、Googleドライブの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;
}
9

ギャラリーの画像やドキュメントのダウンロードに問題はありません

あなたは、多くのデバイスで。

しかし、Googleドライブからファイルを選択すると、パスを取得できません

パスはありません。 _ACTION_GET_CONTENT_では、ユーザーはファイルを選択できません。これにより、ユーザーはコンテンツの一部を選択できます。そのコンテンツmightはローカルファイルである可能性があります。そのコンテンツは次のようになることもあります。

2つの主なオプションがあります。 onlyfilesを必要とする場合は、- a third -party file chooser library 質問のすべてのコードを置き換えます。

または、_ACTION_GET_CONTENT_または_ACTION_OPEN_DOCUMENT_を引き続き使用する場合は、data.getData()から取得したUrionActivityResult()で取得し、それで2つのことを行います。

  • まず、DocumentFile.fromSingleUri()を使用して、そのDocumentFileを指すUriオブジェクトを取得します。 DocumentFilegetName()を呼び出して、コンテンツの「表示名」を取得できます。これは、ユーザーが認識できるものでなければなりません。

  • 次に、ContentResolverを使用してファイル自体のバイト数を取得するのと同じように、FileInputStreamopenInputStream()を使用してコンテンツ自体を取得します。

5
CommonsWare

私も同じ問題で立ち往生しており、Googleドライブから画像を選択すると、そのURIは以下のようになります

com.google.Android.apps.docs.storage

デバイスにないため、ファイルのパスを直接取得できません。そのため、最初に特定の宛先にファイルをダウンロードしてから、そのパスを使用して作業を行うことができます。以下は同じコードです

FileOutputStream fos = null;
    try {
         fos = new FileOutputStream(getDestinationFilePath());
         try (BufferedOutputStream out = new BufferedOutputStream(fos); 
         InputStream in = mContext.getContentResolver().openInputStream(uri)) 
           {
            byte[] buffer = new byte[8192];
            int len = 0;

            while ((len = in.read(buffer)) >= 0) {
                  out.write(buffer, 0, len);
                 }

             out.flush();
            } finally {
                       fos.getFD().sync();
                      }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                    }

            File file = new File(destinationFilePath);
            if (Integer.parseInt(String.valueOf(file.length() / 1024)) > 1024) {
            InputStream imageStream = null;



            try {
                 imageStream = mContext.getContentResolver().openInputStream(uri);
                        } catch (FileNotFoundException e) {
                            e.printStackTrace();
                        }

これで、ファイルが目的の宛先パスに保存され、使用できるようになります。

4
Ankit Shukla
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();
    }
0
satyawan hajare