Android関連 > fileスキームのURIに変換する(Android)

fileスキームのURIに変換する(Android)

TODO: 要検証

ギャラリー等からファイル選択時の戻り値から得られるURI は content スキームとなっている。( content://xxxxx/xxxx/xxxx/ )
この場合のURIが 呼び出し先(ギャラリー等)のコンテンツプロバイダを示すURIになっていると、URIを退避しておいて後で使用するような場合に、
うまく再利用できない事がある。( SecurityException )
※ 呼び出し先で grantUriPermissions 等が適切に行われている場合は問題ない?

そこで、戻り値のURIをいったん fileスキームのURIに変換して再利用する方法を記載する。

概要

以下のように fileスキームのURIに変換する

変換前のURI
content://media/external/images/media/33

変換後のURI
file:///storage/sdcard/test1.jpg

実装例

res/layout/activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent"
    android:layout_height="match_parent" android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    android:paddingBottom="@dimen/activity_vertical_margin" tools:context=".MainActivity">

    <TextView android:text="@string/hello_world" android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/textView" />

    <LinearLayout
        android:orientation="vertical"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:layout_below="@+id/textView"
        android:layout_centerHorizontal="true">

        <Button
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text="New Button"
            android:id="@+id/button" />

        <ImageView
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:id="@+id/imageView" />

    </LinearLayout>


</RelativeLayout>

MainActivity.java

package net.magata.examplegallery;

import android.content.ContentResolver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.graphics.Bitmap;
import android.net.Uri;
import android.provider.MediaStore;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;

import java.io.File;


public class MainActivity extends ActionBarActivity {

    private static final int REQUEST_PIC_IMAGE = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button button = (Button) findViewById(R.id.button);
        button.setOnClickListener(new View.OnClickListener(){
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
                intent.addCategory(Intent.CATEGORY_OPENABLE);
                intent.setDataAndType(Uri.parse("file:///sdcard/Pictures"), "image/*"); // テスト用にPATHを固定
                startActivityForResult(intent, REQUEST_PIC_IMAGE);
            }
        });
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_PIC_IMAGE) {
            picImageResult(resultCode, data);
        }
    }

    /**
     * ギャラリーで画像選択後の処理
     * @param resultCode 結果
     * @param data ギャラリーからの戻り値
     */
    private void picImageResult(int resultCode, Intent data){

        Log.v("TEST", "picImageResult");

        if (data == null) {
            return;
        }

        Log.v("TEST", data.toString());

        Uri uri = data.getData();
        if (uri != null) {

            // FileスキームのURIに変換する
            Uri convUri = getFileSchemeUri(uri);

            // ファイルPATHを取得する
            String path = getPath(convUri);

            // サムネイル画像を取得する
            Bitmap thumbnail = getThumbnail(path);
            ImageView imageView = (ImageView)findViewById(R.id.imageView);
            if (thumbnail != null) {
                imageView.setImageBitmap(thumbnail);
            }

            // TODO: uriを保存しておく必要がある場合は convUri の方を使用する

            Log.i("TEST", "orgUri   : " + uri);
            Log.i("TEST", "convUri  : " + convUri);
            Log.i("TEST", "path     : " + path);
        }
    }

    /**
     * URIをFileスキームのURIに変換する.
     * @param uri 変換前のURI  例) content://media/external/images/media/33
     * @return 変換後のURI     例) file:///storage/sdcard/test1.jpg
     */
    private Uri getFileSchemeUri(Uri uri){
        Uri fileSchemeUri = uri;
        String path = getPath(uri);
        fileSchemeUri = Uri.fromFile(new File(path));
        return fileSchemeUri;
    }

    /**
     * ファイルのサムネイル画像を取得する.
     * @param path ファイルPATH
     * @return サムネイル画像
     */
    private Bitmap getThumbnail(String path){
        ContentResolver resolver = getContentResolver();
        Cursor cursor = resolver.query(
                MediaStore.Images.Media.EXTERNAL_CONTENT_URI, // データの種類
                null,                                         // 項目(null:全項目)
                MediaStore.Images.ImageColumns.DATA + " = ?", // フィルタ条件
                new String[]{path},                           // フィルタ用パラメータ
                null                                          // ソート
        );
        // サムネイルの取得
        if (cursor.moveToFirst()) {
            long id = cursor.getLong(cursor.getColumnIndex("_id"));
            Bitmap thumbnail = MediaStore.Images.Thumbnails.getThumbnail(resolver, id, MediaStore.Images.Thumbnails.MICRO_KIND, null);
            return thumbnail;
        }
        return null;
    }

    /**
     * URIからファイルPATHを取得する.
     * @param uri URI
     * @return ファイルPATH
     */
    private String getPath(Uri uri) {
        String path = uri.toString();
        if (path.matches("^file:.*")) {
            return path.replaceFirst("file://", "");
        } else if (!path.matches("^content:.*")) {
            return path;
        }
        Context context = getApplicationContext();
        ContentResolver contentResolver = context.getContentResolver();
        String[] columns = { MediaStore.Images.Media.DATA };
        Cursor cursor = contentResolver.query(uri, columns, null, null, null);
        if (cursor != null){
            if (cursor.getCount() > 0) {
                cursor.moveToFirst();
                path = cursor.getString(0);
            }
            cursor.close();
        }
        return path;
    }
}

トップ   差分 バックアップ リロード   一覧 単語検索 最終更新   ヘルプ   最終更新のRSS
Last-modified: 2017-03-20 (月) 20:20:26 (2593d)