web-dev-qa-db-ja.com

SDカードマシュマロのファイルのURIから実際のパスを取得します

SDカードに存在するファイルを選択したい内部ストレージにないサーバーをアップロードしますが、サイズを取得するためのパスを取得できません。以下のコードを使用してファイルを選択する意図を開始しました。

_ intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
 intent.addCategory(Intent.CATEGORY_OPENABLE);
 intent.setType("*/*");
 String[] mimetypes = {"application/*"};
 intent.putExtra(Intent.EXTRA_MIME_TYPES, mimetypes);
 startActivityForResult(
      Intent.createChooser(intent, "Select a File to Upload"), FILE_SELECT_CODE);
_

私が使用しているファイルへのパスを取得するために この回答 そしてユーザーがsdcard(リムーバブル)からファイルを選択しない限りそれは機能します。コードをデバッグして、typeprimaryでないことがわかった場合、この条件の範囲内にはなりません。

_if("primary".equalsIgnoreCase(type)){
     return Environment.getExternalStorageDirectory() + "/" + split[1];
} 
_

それで、私の質問は、他に何があるのか​​ということです。つまり、型がプライマリでない場合はどうなりますか?その場合、どのようにファイルへのパスを取得できますか?私は多くの質問とチュートリアルを検索しましたが、それらのいずれにも他にはありません。 この回答 のelse部分も試しましたが、System.getenv() return null for "SECONDARY_STORAGE" and-のため、機能しません。 sdcard for "EXTERNAL_STORAGE"。試してみると、ファイルが見つからないという例外が発生します。

_if ("primary".equalsIgnoreCase(type)) {
    return Environment.getExternalStorageDirectory() + "/" + split[1];
}else{
    return System.getenv("EXTERNAL_STORAGE") + "/" + split[1];
}
_

ファイルのURIとドキュメントIDは次のようになります。

ri:content://com.Android.externalstorage.documents/document/0EF9-3110%3Adevice-2016-12-02-130553.png

docId:0EF9-3110:device-2016-12-02-130553.png

何か助けは??

8
Jaiprakash Soni

Android Device Managerに時間を費やした後、解決策を見つけました。次のとおりです。

ドキュメントタイプIDがプライマリでない場合は、次を使用してパスを作成します。

filePath = "/storage/" + type + "/" + split[1];

EDIT: DocumentUriの場合、ファイルタイプに基づいてcontentUriを選択します

これが完全な機能です:

public static String getRealPathFromURI_API19(Context context, Uri uri) {
    String filePath = "";

    // 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];
        } else {

            if (Build.VERSION.SDK_INT > 20) {
                    //getExternalMediaDirs() added in API 21
                    File extenal[] = context.getExternalMediaDirs();
                    if (extenal.length > 1) {
                        filePath = extenal[1].getAbsolutePath();
                        filePath = filePath.substring(0, filePath.indexOf("Android")) + split[1];
                    }
             }else{
                    filePath = "/storage/" + type + "/" + split[1];
             }
            return filePath;
        }

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

        Cursor cursor = null;
        final String column = "_data";
        final String[] projection = {column};

        try {
            cursor = context.getContentResolver().query(uri, projection, null, null, null);
            if (cursor != null && cursor.moveToFirst()) {
                final int index = cursor.getColumnIndexOrThrow(column);
                String result = cursor.getString(index);
                cursor.close();
                return result;
            }
        } finally {
            if (cursor != null)
                cursor.close();
        }
    } else if (DocumentsContract.isDocumentUri(context, uri)) {
        // MediaProvider
        String wholeID = DocumentsContract.getDocumentId(uri);

        // Split at colon, use second item in the array
        String[] ids = wholeID.split(":");
        String id;
        String type;
        if (ids.length > 1) {
            id = ids[1];
            type = ids[0];
        } else {
            id = ids[0];
            type = ids[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[]{id};
        final String column = "_data";
        final String[] projection = {column};
        Cursor cursor = context.getContentResolver().query(contentUri, 
            projection, selection, selectionArgs, null);

        if (cursor != null) {
            int columnIndex = cursor.getColumnIndex(column);

            if (cursor.moveToFirst()) {
                filePath = cursor.getString(columnIndex);
            }
            cursor.close();
        }
        return filePath;
    } else {
        String[] proj = {MediaStore.Audio.Media.DATA};
        Cursor cursor = context.getContentResolver().query(uri, proj, null, null, null);
        if (cursor != null) {
            int column_index = cursor.getColumnIndexOrThrow(MediaStore.Audio.Media.DATA);
            if (cursor.moveToFirst())
                filePath = cursor.getString(column_index);
            cursor.close();
        }


        return filePath;
    }
    return null;
}
12
Jaiprakash Soni

アップロードコードを変更します。どこかにあります

FileInputStream fis = new FileInputStream(path);

への変更

InputStream is = getContentResolver().openInputStream(uri);

したがって、URIを直接使用してください。ファイルパスは必要ありません。

3
greenapps

アプリケーションにFileProviderを実装するのは非常に簡単です。まず、AndroidManifest.xmlの次のようなタグの下にFileProviderタグを追加する必要があります:AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:Android="http://schemas.Android.com/apk/res/Android"
    ...
    <application
        ...
        <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>
</manifest>

次に、resフォルダーの下のxmlフォルダーにprovider_paths.xmlファイルを作成します。フォルダーが存在しない場合は、作成する必要がある場合があります。

res/xml/provider_paths.xml

<?xml version="1.0" encoding="utf-8"?>
<paths xmlns:Android="http://schemas.Android.com/apk/res/Android">
    <external-path name="external_files" path="."/>
</paths>

完了!これでFileProviderが宣言され、使用できるようになりました。

最後のステップは、MainActivity.Javaで以下のコード行を変更することです。

Uri photoURI = Uri.fromFile(createImageFile());
to



 Uri photoURI = FileProvider.getUriForFile(MainActivity.this,
            BuildConfig.APPLICATION_ID + ".provider",
            createImageFile());

そして....完了!これで、アプリケーションは、AndroidNougat。Yah!を含むすべてのAndroidバージョンで完全に正常に動作するはずです。

0
g7pro