プログラムでAndroidの組み込みギャラリーアプリから画像を取得/選択する


271

アプリケーション内からギャラリー組み込みアプリで画像/画像を開こうとしています。

画像のURIがあります(画像はSDカードにあります)。

何か提案はありますか?


結果を正しく取得できるように、より多くのテストコードを提供するように回答を更新しました。
Anthony Forloney、2010年

私の答えを見てください。これはhcplのコードの更新であり、astroファイルマネージャーとoiファイルマネージャーでも機能します。
2010

15
誰かが「Androidから画像を取得/選択...」という質問を更新する必要があります。現在の質問は私が画像を持っていると解釈し、デフォルトのギャラリーアプリで表示したいと考えています。
ビカス

@Vikas、あなたは正しいようです。1年以上前に私が何を達成しようとしたのか、そしてすべての回答(解決策として選択したものを含む)が実際に別の質問に実際に回答する理由を覚えていません...
Michael Kessler

実際、質問を完全に変更することが正しいかどうかはわかりません。36人がお気に入りに質問を追加しています...
マイケルケスラー

回答:


351

これは完全なソリューションです。この例のコードを、@ madによる以下の回答で提供される情報で更新しました。また、@ Khobaibから、picasa画像の処理方法を説明した以下の解決策を確認してください。

更新

私は元の回答を確認し、githubからチェックアウトしてシステムに直接インポートできるシンプルなAndroid Studioプロジェクトを作成しました。

https://github.com/hanscappelle/SO-2169649

(複数ファイルの選択にはまだ作業が必要であることに注意してください)

単一の画像の選択

ユーザーmadのおかげで、ファイルエクスプローラーからの画像がサポートされます。

public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.Button01)
                .setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {

                        // in onCreate or any event where your want the user to
                        // select a file
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent,
                                "Select Picture"), SELECT_PICTURE);
                    }
                });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // this will only work for images selected from gallery
            String[] projection = { MediaStore.Images.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            if( cursor != null ){
                int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                String path = cursor.getString(column_index);
                cursor.close();
                return path;
            }
            // this is our fallback here
            return uri.getPath();
    }

}

複数の画像を選択する

誰かがコメントでその情報を要求したので、情報を収集しておく方が良いです。

EXTRA_ALLOW_MULTIPLEインテントに追加のパラメーターを設定します。

intent.putExtra(Intent.EXTRA_ALLOW_MULTIPLE, true);

そして、そのパラメータの結果処理チェックで:

if (Intent.ACTION_SEND_MULTIPLE.equals(data.getAction()))
        && Intent.hasExtra(Intent.EXTRA_STREAM)) {
    // retrieve a collection of selected images
    ArrayList<Parcelable> list = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    // iterate over these images
    if( list != null ) {
       for (Parcelable parcel : list) {
         Uri uri = (Uri) parcel;
         // TODO handle the images one by one here
       }
   }
} 

これは、APIレベル18以上でのみサポートされていることに注意してください。


Astroファイルマネージャを使用すると機能しません。何かアイデアはありますか?
Rohith Nandakumar、2010

@hcpl回答ありがとうございます。複数の画像を取得する方法を教えてください...?
Noby

28
単一の画像を取得することは、最新のAndroidバージョン4.4(KitKat)では機能していないようです。クエリの_data列はnull値を返します。
クリストファーマッサー2013年

1
@hcpl「Intent.hasExtra」を意味するのではなく、「data.hasExtra」を意味する-データがonActivityResult()のIntentパラメータであると想定。
IgorGanapolsky 2013

2
このコードは完全にpreKitkatで機能していますが、それ以降、ドキュメントプロバイダーが存在します。私の回答では、キットカットで何をすべきかについて書きます。
14

135

これは、hcplが投稿した細かいコードの更新です。しかし、これはOIファイルマネージャー、astroファイルマネージャー、およびメディアギャラリーでも動作します(テスト済み)。だから私はそれがすべてのファイルマネージャーで動作すると思います(言及されたもの以外に他にたくさんありますか?)。彼が書いたコードにいくつかの修正を行いました。

public class BrowsePicture extends Activity {

    //YOU CAN EDIT THIS TO WHATEVER YOU WANT
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;
    //ADDED
    private String filemanagerstring;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ((Button) findViewById(R.id.Button01))
        .setOnClickListener(new OnClickListener() {

            public void onClick(View arg0) {

                // in onCreate or any event where your want the user to
                // select a file
                Intent intent = new Intent();
                intent.setType("image/*");
                intent.setAction(Intent.ACTION_GET_CONTENT);
                startActivityForResult(Intent.createChooser(intent,
                        "Select Picture"), SELECT_PICTURE);
            }
        });
    }

    //UPDATED
    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();

                //OI FILE Manager
                filemanagerstring = selectedImageUri.getPath();

                //MEDIA GALLERY
                selectedImagePath = getPath(selectedImageUri);

                //DEBUG PURPOSE - you can delete this if you want
                if(selectedImagePath!=null)
                    System.out.println(selectedImagePath);
                else System.out.println("selectedImagePath is null");
                if(filemanagerstring!=null)
                    System.out.println(filemanagerstring);
                else System.out.println("filemanagerstring is null");

                //NOW WE HAVE OUR WANTED STRING
                if(selectedImagePath!=null)
                    System.out.println("selectedImagePath is the right one for you!");
                else
                    System.out.println("filemanagerstring is the right one for you!");
            }
        }
    }

    //UPDATED!
    public String getPath(Uri uri) {
        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = managedQuery(uri, projection, null, null, null);
        if(cursor!=null)
        {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            int column_index = cursor
            .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            return cursor.getString(column_index);
        }
        else return null;
    }

1
OIパスからビットマップ画像を取得するにはどうすればよいですか?
ビカス

2
コードを見てください。コメント/// NOW WE HAVE OUR WANTED STRING ...のある行で...これで十分です。次に、BitmapFactoryクラスを使用して、パスからビットマップを取得します
狂った

ありがとう!あなたは良い点を持っています、他のファイルマネージャーを試したことがない:)。
hcpl 2011年

2
私もカーソルを閉じたいです:)
pgsandstrom

7
に変更else return null;getPath(Uri uri)return uri.getPath();、最初のfilemanagerstring = selectedImageUri.getPath();チェックを取り除くこともできます。この方法では、1つの呼び出しを行っgetPath(Uri)てパスを取得するだけです(使用されたのがギャラリーでもファイルマネージャーでも)。
ashughes、2009

24

hcplのメソッドは、KitKatより前では完全に機能しますが、DocumentsProvider APIでは機能しません。そのためには、documentprovidersの公式Androidチュートリアルに従ってくださいhttps : //developer.android.com/guide/topics/providers/document-provider.html >ドキュメントを開き、ビットマップセクション。

単に私はhcplのコードを使用してそれを拡張しました:画像への取得されたパスを持つファイルが例外をスローする場合、私はこの関数を呼び出します:

private Bitmap getBitmapFromUri(Uri uri) throws IOException {
        ParcelFileDescriptor parcelFileDescriptor =
             getContentResolver().openFileDescriptor(uri, "r");
        FileDescriptor fileDescriptor = parcelFileDescriptor.getFileDescriptor();
        Bitmap image = BitmapFactory.decodeFileDescriptor(fileDescriptor);
        parcelFileDescriptor.close();
        return image;
}

Nexus 5でテスト済み。


本当に役立つ答えです。「写真」アプリから画像を選択するときに使用します。
Arun Badole 2014年

ローカルとサーバーの両方のファイルでこれを試しましたが、両方で機能しました。
Arun Badole 2014年

11

上記のコードに基づいて、私は以下のようにコードを反映しました、それがより適切かもしれません:

public String getPath(Uri uri) {
    String selectedImagePath;
    //1:MEDIA GALLERY --- query from MediaStore.Images.Media.DATA
    String[] projection = { MediaStore.Images.Media.DATA };
    Cursor cursor = managedQuery(uri, projection, null, null, null);
    if(cursor != null){
        int column_index = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
        cursor.moveToFirst();
        selectedImagePath = cursor.getString(column_index);
    }else{
        selectedImagePath = null;
    }

    if(selectedImagePath == null){
        //2:OI FILE Manager --- call method: uri.getPath()
        selectedImagePath = uri.getPath();
    }
    return selectedImagePath;
}

11

@hcplと@madから解決策を試してみました。hcplのソリューションは、ギャラリー内のローカル画像を適切にサポートし、それに加えてmadがより優れたソリューションを提供します-OI / Astro / Dropbox画像の読み込みにも役立ちます。しかし、私のアプリでは、picasaライブラリの作業中には、Androidギャラリーに統合され、両方のソリューションが失敗します。

私は少し検索して分析し、最終的にこの制限を克服するより優れたエレガントなソリューションができました。この場合私を助けてくれた彼のブログのDimitar Darazhanskiのおかげで、私は理解しやすいように少し修正しました。これが私の解決策です-

public class BrowsePicture extends Activity {

//YOU CAN EDIT THIS TO WHATEVER YOU WANT
private static final int SELECT_PICTURE = 1;

private String selectedImagePath;
//ADDED
private String filemanagerstring;

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    ((Button) findViewById(R.id.Button01))
    .setOnClickListener(new OnClickListener() {

        public void onClick(View arg0) {

            // in onCreate or any event where your want the user to
            // select a file
            Intent intent = new Intent();
            intent.setType("image/*");
            intent.setAction(Intent.ACTION_GET_CONTENT);
            startActivityForResult(Intent.createChooser(intent,
                    "Select Picture"), SELECT_PICTURE);
        }
    });
}

public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (resultCode == RESULT_OK) {
        if (requestCode == SELECT_PICTURE) {
            Uri selectedImageUri = data.getData();
            Log.d("URI VAL", "selectedImageUri = " + selectedImageUri.toString());
            selectedImagePath = getPath(selectedImageUri);

            if(selectedImagePath!=null){         
                // IF LOCAL IMAGE, NO MATTER IF ITS DIRECTLY FROM GALLERY (EXCEPT PICASSA ALBUM),
                // OR OI/ASTRO FILE MANAGER. EVEN DROPBOX IS SUPPORTED BY THIS BECAUSE DROPBOX DOWNLOAD THE IMAGE 
                // IN THIS FORM - file:///storage/emulated/0/Android/data/com.dropbox.android/...
                System.out.println("local image"); 
            }
            else{
                System.out.println("picasa image!");
                loadPicasaImageFromGallery(selectedImageUri);
            }
        }
    }
}


// NEW METHOD FOR PICASA IMAGE LOAD
private void loadPicasaImageFromGallery(final Uri uri) {
    String[] projection = {  MediaColumns.DATA, MediaColumns.DISPLAY_NAME };
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        cursor.moveToFirst();

        int columnIndex = cursor.getColumnIndex(MediaColumns.DISPLAY_NAME);
        if (columnIndex != -1) {
            new Thread(new Runnable() {
                // NEW THREAD BECAUSE NETWORK REQUEST WILL BE MADE THAT WILL BE A LONG PROCESS & BLOCK UI
                // IF CALLED IN UI THREAD 
                public void run() {
                    try {
                        Bitmap bitmap = android.provider.MediaStore.Images.Media.getBitmap(getContentResolver(), uri);
                        // THIS IS THE BITMAP IMAGE WE ARE LOOKING FOR.
                    } catch (Exception ex) {
                        ex.printStackTrace();
                    }
                }
            }).start();
        }
    }
    cursor.close();
}


public String getPath(Uri uri) {
    String[] projection = {  MediaColumns.DATA};
    Cursor cursor = getContentResolver().query(uri, projection, null, null, null);
    if(cursor != null) {
        //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
        //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
        cursor.moveToFirst();
        int columnIndex = cursor.getColumnIndexOrThrow(MediaColumns.DATA);
        String filePath = cursor.getString(columnIndex);
        cursor.close();
        return filePath;
    }
    else 
        return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
}

確認して、問題がある場合はお知らせください。私はそれをテストしました、そしてそれはすべての場合にうまくいきます。

これが皆さんのお役に立てば幸いです。


10

SDカードディレクトリに画像用の画像フォルダがあると仮定します。

Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
// tells your intent to get the contents
// opens the URI for your image directory on your sdcard
intent.setType("file:///sdcard/image/*"); 
startActivityForResult(intent, 1);

その後、アクティビティのコンテンツをどのように処理するかを決定できます。

これは画像のパス名を取得する例でした。返された結果を処理できることを確認するために、コードでこれをテストしてください。ニーズに合わせて、必要に応じてコードを変更できます。

protected final void onActivityResult(final int requestCode, final int
                     resultCode, final Intent i) {
    super.onActivityResult(requestCode, resultCode, i);

  // this matches the request code in the above call
  if (requestCode == 1) {
      Uri _uri = i.getData();

    // this will be null if no image was selected...
    if (_uri != null) {
      // now we get the path to the image file
     cursor = getContentResolver().query(_uri, null,
                                      null, null, null);
     cursor.moveToFirst();
     String imageFilePath = cursor.getString(0);
     cursor.close();
     }
   }

私のアドバイスは、画像が正しく機能するようにすることです。問題は、SDカードの画像にアクセスすることの内容だと思います。SDカードに画像表示するをご覧ください

おそらく正しいプロバイダーを提供する例によって、それを稼働させることができれば、コードの回避策を見つけることができるはずです。

この質問をあなたの進捗状況に合わせて更新して、私に最新情報を提供してください。幸運を


@Anthony、ご回答ありがとうございます。残念ながら私にはうまくいきません。次のエラーが表示されます:android.content.ActivityNotFoundException: No Activity found to handle Intent { act=android.intent.action.GET_CONTENT typ=file:///sdcard/images/* }
マイケルケスラー

startActivityforResultアクティビティを呼び出して提供する必要があります。私が次に何をするかを決めることについて私が言及していたのは、私の悪いことです。
Anthony Forloney、2010年

それでも動作しません...フォルダが存在し、フォルダ内に画像ファイルがあることを確認します。呼び出しstartActivityForResult(intent, 1);てもまだこのエラーが発生します...このコードはアクティビティの外にありますが、アクティビティへの参照があり、startActivityForResultその参照でメソッドを呼び出します-おそらくこれが理由ですか?
Michael Kessler

いや、それは理由で1はありません、あなたの通過は何ですか?試してみるIMAGE_PICK
Anthony Forloney、2010年

1
2番目のパラメーターは私にとっては単なるものですよね。これは、結果とともに私に返される単なるintです。のIntent.ACTION_PICK代わりにも試してみましたIntent.ACTION_GET_CONTENT。どういう意味IMAGE_PICKですか?そのような定数はありません。私も試しましたintent.setData(Uri.fromFile(new File("/sdcard/image/")));。私はこれらの可能なすべての組み合わせを試しましたが、何も機能しないようです...
マイケルケスラー

10

これはこのトピックへの私の再訪であり、ここですべての情報を収集し、さらに他の関連するスタックオーバーフローの質問から収集します。メモリ不足の状態と画像の回転を処理しながら、一部のプロバイダーから画像を返します。ギャラリー、picasa、ドロップボックスなどのファイルマネージャーをサポートしています。使い方は簡単です。入力として、コンストラクタはコンテンツリゾルバとURIを受け取ります。出力は最終的なビットマップです。

/**
 * Creates resized images without exploding memory. Uses the method described in android
 * documentation concerning bitmap allocation, which is to subsample the image to a smaller size,
 * close to some expected size. This is required because the android standard library is unable to
 * create a reduced size image from an image file using memory comparable to the final size (and
 * loading a full sized multi-megapixel picture for processing may exceed application memory budget).
 */

public class UserPicture {
    static int MAX_WIDTH = 600;
    static int MAX_HEIGHT = 800;
    Uri uri;
    ContentResolver resolver;
    String path;
    Matrix orientation;
    int storedHeight;
    int storedWidth;

    public UserPicture(Uri uri, ContentResolver resolver) {
        this.uri = uri;
        this.resolver = resolver;
    }

    private boolean getInformation() throws IOException {
        if (getInformationFromMediaDatabase())
            return true;

        if (getInformationFromFileSystem())
            return true;

        return false;
    }

    /* Support for gallery apps and remote ("picasa") images */
    private boolean getInformationFromMediaDatabase() {
        String[] fields = { Media.DATA, ImageColumns.ORIENTATION };
        Cursor cursor = resolver.query(uri, fields, null, null, null);

        if (cursor == null)
            return false;

        cursor.moveToFirst();
        path = cursor.getString(cursor.getColumnIndex(Media.DATA));
        int orientation = cursor.getInt(cursor.getColumnIndex(ImageColumns.ORIENTATION));
        this.orientation = new Matrix();
        this.orientation.setRotate(orientation);
        cursor.close();

        return true;
    }

    /* Support for file managers and dropbox */
    private boolean getInformationFromFileSystem() throws IOException {
        path = uri.getPath();

        if (path == null)
            return false;

        ExifInterface exif = new ExifInterface(path);
        int orientation = exif.getAttributeInt(ExifInterface.TAG_ORIENTATION,
                                               ExifInterface.ORIENTATION_NORMAL);

        this.orientation = new Matrix();
        switch(orientation) {
            case ExifInterface.ORIENTATION_NORMAL:
                /* Identity matrix */
                break;
            case ExifInterface.ORIENTATION_FLIP_HORIZONTAL:
                this.orientation.setScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_180:
                this.orientation.setRotate(180);
                break;
            case ExifInterface.ORIENTATION_FLIP_VERTICAL:
                this.orientation.setScale(1, -1);
                break;
            case ExifInterface.ORIENTATION_TRANSPOSE:
                this.orientation.setRotate(90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_90:
                this.orientation.setRotate(90);
                break;
            case ExifInterface.ORIENTATION_TRANSVERSE:
                this.orientation.setRotate(-90);
                this.orientation.postScale(-1, 1);
                break;
            case ExifInterface.ORIENTATION_ROTATE_270:
                this.orientation.setRotate(-90);
                break;
        }

        return true;
    }

    private boolean getStoredDimensions() throws IOException {
        InputStream input = resolver.openInputStream(uri);
        Options options = new Options();
        options.inJustDecodeBounds = true;
        BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);

        /* The input stream could be reset instead of closed and reopened if it were possible
           to reliably wrap the input stream on a buffered stream, but it's not possible because
           decodeStream() places an upper read limit of 1024 bytes for a reset to be made (it calls
           mark(1024) on the stream). */
        input.close();

        if (options.outHeight <= 0 || options.outWidth <= 0)
            return false;

        storedHeight = options.outHeight;
        storedWidth = options.outWidth;

        return true;
    }

    public Bitmap getBitmap() throws IOException {
        if (!getInformation())
            throw new FileNotFoundException();

        if (!getStoredDimensions())
            throw new InvalidObjectException(null);

        RectF rect = new RectF(0, 0, storedWidth, storedHeight);
        orientation.mapRect(rect);
        int width = (int)rect.width();
        int height = (int)rect.height();
        int subSample = 1;

        while (width > MAX_WIDTH || height > MAX_HEIGHT) {
            width /= 2;
            height /= 2;
            subSample *= 2;
        }

        if (width == 0 || height == 0)
            throw new InvalidObjectException(null);

        Options options = new Options();
        options.inSampleSize = subSample;
        Bitmap subSampled = BitmapFactory.decodeStream(resolver.openInputStream(uri), null, options);

        Bitmap picture;
        if (!orientation.isIdentity()) {
            picture = Bitmap.createBitmap(subSampled, 0, 0, options.outWidth, options.outHeight,
                                          orientation, false);
            subSampled.recycle();
        } else
            picture = subSampled;

        return picture;
    }
}

参照:


9

ダウンロード可能なソースコードを使用したイメージピッカーに関する便利なチュートリアルが2つあります。

Android画像ピッカーを作成する方法

Androidで画像を選択してトリミングする方法

ただし、アプリはいつか強制的に閉じる必要があるため、次のようにandroid:configChanges属性をマニフェストファイルのメインアクティビティに追加することで修正できます。

<activity android:name=".MainActivity"
                  android:label="@string/app_name" android:configChanges="keyboardHidden|orientation" >

カメラAPIは方向付けでコントロールを失ったようですので、これはそれを助けるでしょう。:)


7

2.3(Gingerbread)-4.4(Kitkat)、5.0(Lollipop)および6.0(Marshmallow)の解決策の下でも:-

ステップ1ギャラリーを開いて写真を選択するためのコード:

public static final int PICK_IMAGE = 1;
private void takePictureFromGalleryOrAnyOtherFolder() 
{
    Intent intent = new Intent();
    intent.setType("image/*");
    intent.setAction(Intent.ACTION_GET_CONTENT);
    startActivityForResult(Intent.createChooser(intent, "Select Picture"), PICK_IMAGE);
}

ステップ2データを取得するためのコードonActivityResult

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
            super.onActivityResult(requestCode, resultCode, data);
            if (resultCode == Activity.RESULT_OK) {
               if (requestCode == PICK_IMAGE) {
                    Uri selectedImageUri = data.getData();
                    String imagePath = getRealPathFromURI(selectedImageUri);
                   //Now you have imagePath do whatever you want to do now
                 }//end of inner if
             }//end of outer if
      }

 public String getRealPathFromURI(Uri contentUri) {
        //Uri contentUri = Uri.parse(contentURI);

        String[] projection = { MediaStore.Images.Media.DATA };
        Cursor cursor = null;
        try {
            if (Build.VERSION.SDK_INT > 19) {
                // Will return "image:x*"
                String wholeID = DocumentsContract.getDocumentId(contentUri);
                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];
                // where id is equal to
                String sel = MediaStore.Images.Media._ID + "=?";

                cursor = context.getContentResolver().query(
                        MediaStore.Images.Media.EXTERNAL_CONTENT_URI,
                        projection, sel, new String[] { id }, null);
            } else {
                cursor = context.getContentResolver().query(contentUri,
                        projection, null, null, null);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

        String path = null;
        try {
            int column_index = cursor
                    .getColumnIndex(MediaStore.Images.Media.DATA);
            cursor.moveToFirst();
            path = cursor.getString(column_index).toString();
            cursor.close();
        } catch (NullPointerException e) {
            e.printStackTrace();
        }
        return path;
    }

私はマシュマロでNexus 5を使用しています。使用している電話。
Pankaj

イムはまた、GoogleのネクサスをUSNGが、画像の名前や私のギャラリー選択した画像イム取得ヌルのパスを取得するためにfaled
Erum

java.lang.SecurityException:Permission Denial:read com.android.providers.media.MediaProvider uri content:// media / external / images / media from pid = 31332、uid = 11859 require android.permission.READ_EXTERNAL_STORAGE、or grantUriPermission()このエラーが発生する
Erum

あなたはその表示を追加する許可を持っていますREAD_EXTERNAL_STORAGE
Pankaj

はい、すでにマニフェストに権限を追加していますが、実行時にJavaファイルに権限を追加しませんでした
Erum

6

画像と動画を表示するには、次のことを試してください。

    Intent intent = new Intent();
    intent = new Intent(Intent.ACTION_PICK, android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
    startActivityForResult(intent, 1);
    startActivityForResult(Intent.createChooser(intent,"Wybierz plik"), SELECT_FILE);

5

万が一に備えて。ビットマップを取得するためにこれを行います:

InputStream is = context.getContentResolver().openInputStream(imageUri);
Bitmap bitmap = BitmapFactory.decodeStream(is);

これが最も簡単な答えです(そして私のために働いた唯一の答えです)。よくできました!
デルリン2017

5

上記の答えは正しいです。HTC M8でギャラリーから画像を選択するとアプリケーションがクラッシュするという別の問題に直面しました。画像パスにnull値を取得しています。私は次の解決策で修正して最適化しました。onActivityResultメソッド

protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    if ((requestCode == RESULT_LOAD_IMAGE) && (resultCode == RESULT_OK)) {
     if (data != null) {

            Uri selectedImageUri = null;
            selectedImageUri = data.getData();
            String[] filePathColumn = { MediaStore.Images.Media.DATA };

            Cursor imageCursor = mainActivity.getContentResolver().query(
                    selectedImageUri, filePathColumn, null, null, null);

            if (imageCursor == null) {
                return;
            }

            imageCursor.moveToFirst();
            int columnIndex = imageCursor.getColumnIndex(filePathColumn[0]);
            picturePath = imageCursor.getString(columnIndex);
            if (picturePath == null) {
                picturePath = selectedImageUri.getPath();
                String wholeID = DocumentsContract
                        .getDocumentId(selectedImage);

                // Split at colon, use second item in the array
                String id = wholeID.split(":")[1];

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

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

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

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

                if (cursor.moveToFirst()) {
                    picturePath = cursor.getString(columnIndex);
                }

                cursor.close();
            }
            picturePathAbs = new File(picturePath).getAbsolutePath();
            imageCursor.close();
        }

}


同様の問題に直面し、picturePathは常にnullです。私はあなたの解決策を試してみましたが機能しません、それに加えてgetDocumentIdが必要です> API 19
Stoycho Andreev

3
package com.ImageConvertingDemo;

import java.io.BufferedInputStream;
import java.io.FileInputStream;

import android.app.Activity;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.util.Log;
import android.widget.EditText;
import android.widget.ImageView;

public class MyActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        EditText tv = (EditText)findViewById(R.id.EditText01);
        ImageView iv = (ImageView)findViewById(R.id.ImageView01);
        FileInputStream in;
        BufferedInputStream buf;
            try 
            {
                in = new FileInputStream("/sdcard/smooth.png");
                buf = new BufferedInputStream(in,1070);
                System.out.println("1.................."+buf);
                byte[] bMapArray= new byte[buf.available()];
                tv.setText(bMapArray.toString());
                buf.read(bMapArray);
                Bitmap bMap = BitmapFactory.decodeByteArray(bMapArray, 0, bMapArray.length);

                /*for (int i = 0; i < bMapArray.length; i++) 
                {
                System.out.print("bytearray"+bMapArray[i]);
                }*/
                iv.setImageBitmap(bMap);
                //tv.setText(bMapArray.toString());
                //tv.setText(buf.toString());
                if (in != null) 
                {
                    in.close();
                }
                if (buf != null) 
                {
                    buf.close();
                }

            } 
            catch (Exception e) 
            {
                Log.e("Error reading file", e.toString());
            }
    }
}

1
あなたは答える前に質問を理解しませんでした。また、何をしようとしているかについての説明は含まれていません。また、コードは確立されたJavaプログラミング標準のいくつかを破ります。
Torben

3
public class BrowsePictureActivity extends Activity {

    // this is the action code we use in our intent, 
    // this way we know we're looking at the response from our own action
    private static final int SELECT_PICTURE = 1;

    private String selectedImagePath;

    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        ((Button) findViewById(R.id.Button01))
                .setOnClickListener(new OnClickListener() {

                    public void onClick(View arg0) {

                        // in onCreate or any event where your want the user to
                        // select a file
                        Intent intent = new Intent();
                        intent.setType("image/*");
                        intent.setAction(Intent.ACTION_GET_CONTENT);
                        startActivityForResult(Intent.createChooser(intent,
                                "Select Picture"), SELECT_PICTURE);
                    }
                });
    }

    public void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == RESULT_OK) {
            if (requestCode == SELECT_PICTURE) {
                Uri selectedImageUri = data.getData();
                selectedImagePath = getPath(selectedImageUri);
            }
        }
    }

    /**
     * helper to retrieve the path of an image URI
     */
    public String getPath(Uri uri) {
            // just some safety built in 
            if( uri == null ) {
                // TODO perform some logging or show user feedback
                return null;
            }
            // try to retrieve the image from the media store first
            // this will only work for images selected from gallery
            String[] projection = { MediaStore.Images.Media.DATA };
            Cursor cursor = managedQuery(uri, projection, null, null, null);
            if( cursor != null ){
                int column_index = cursor
                .getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
                cursor.moveToFirst();
                return cursor.getString(column_index);
            }
            // this is our fallback here
            return uri.getPath();
    }

}

3

特定のタイプのファイルを取得する

この例では、画像のコピーを取得します。

static final int REQUEST_IMAGE_GET = 1;

public void selectImage() {
    Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
    intent.setType("image/*");
    if (intent.resolveActivity(getPackageManager()) != null) {
        startActivityForResult(intent, REQUEST_IMAGE_GET);
    }
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_GET && resultCode == RESULT_OK) {
        Bitmap thumbnail = data.getParcelable("data");
        Uri fullPhotoUri = data.getData();
        // Do work with photo saved at fullPhotoUri
        ...
    }
}

特定の種類のファイルを開く

4.4以降で実行しているときに、別のアプリによって管理されているファイルを開くように要求した

static final int REQUEST_IMAGE_OPEN = 1;

public void selectImage() {
    Intent intent = new Intent(Intent.ACTION_OPEN_DOCUMENT);
    intent.setType("image/*");
    intent.addCategory(Intent.CATEGORY_OPENABLE);
    // Only the system receives the ACTION_OPEN_DOCUMENT, so no need to test.
    startActivityForResult(intent, REQUEST_IMAGE_OPEN);
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == REQUEST_IMAGE_OPEN && resultCode == RESULT_OK) {
        Uri fullPhotoUri = data.getData();
        // Do work with full size photo saved at fullPhotoUri
        ...
    }
}

元のソース


2

以前の回答に加えて、正しいパス(AndroZipなど)の取得に問題がある場合は、これを使用できます。

  public String getPath(Uri uri ,ContentResolver contentResolver) {
        String[] projection = {  MediaStore.MediaColumns.DATA};
        Cursor cursor;
        try{
            cursor = contentResolver.query(uri, projection, null, null, null);
        } catch (SecurityException e){
            String path = uri.getPath();
            String result = tryToGetStoragePath(path);
            return  result;
        }
        if(cursor != null) {
            //HERE YOU WILL GET A NULLPOINTER IF CURSOR IS NULL
            //THIS CAN BE, IF YOU USED OI FILE MANAGER FOR PICKING THE MEDIA
            cursor.moveToFirst();
            int columnIndex = cursor.getColumnIndexOrThrow(MediaStore.MediaColumns.DATA);
            String filePath = cursor.getString(columnIndex);
            cursor.close();
            return filePath;
        }
        else
            return uri.getPath();               // FOR OI/ASTRO/Dropbox etc
    }

    private String tryToGetStoragePath(String path) {
        int actualPathStart = path.indexOf("//storage");
        String result = path;

        if(actualPathStart!= -1 && actualPathStart< path.length())
            result = path.substring(actualPathStart+1 , path.length());

        return result;
    }

ここで画像のURIを知る必要がありますか?ギャラリーから任意の画像を選択したい場合はどうなりますか?
IgorGanapolsky 2013

ギャラリーから受け取るインテントは、URLを提供します
bugraoral

1

ギャラリーから単一の画像を選択するための答えを見つけてください

import android.app.Activity;
import android.net.Uri;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.TextView;

import java.io.ByteArrayOutputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;

public class PickImage extends Activity {

    Button btnOpen, btnGet, btnPick;
    TextView textInfo1, textInfo2;
    ImageView imageView;

    private static final int RQS_OPEN_IMAGE = 1;
    private static final int RQS_GET_IMAGE = 2;
    private static final int RQS_PICK_IMAGE = 3;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.image_pick);
        btnOpen = (Button)findViewById(R.id.open);
        btnGet = (Button)findViewById(R.id.get);
        btnPick = (Button)findViewById(R.id.pick);
        textInfo1 = (TextView)findViewById(R.id.info1);
        textInfo2 = (TextView)findViewById(R.id.info2);
        imageView = (ImageView) findViewById(R.id.image);

        btnOpen.setOnClickListener(btnOpenOnClickListener);
        btnGet.setOnClickListener(btnGetOnClickListener);
        btnPick.setOnClickListener(btnPickOnClickListener);
    }

    View.OnClickListener btnOpenOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_OPEN_DOCUMENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnGetOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent();
            intent.setAction(Intent.ACTION_GET_CONTENT);
            intent.addCategory(Intent.CATEGORY_OPENABLE);
            intent.setType("image/*");

            startActivityForResult(intent, RQS_OPEN_IMAGE);
        }
    };

    View.OnClickListener btnPickOnClickListener = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            Intent intent = new Intent(Intent.ACTION_PICK,
                    android.provider.MediaStore.Images.Media.EXTERNAL_CONTENT_URI);
            startActivityForResult(intent, RQS_PICK_IMAGE);
        }
    };

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (resultCode == Activity.RESULT_OK) {


            if (requestCode == RQS_OPEN_IMAGE ||
                    requestCode == RQS_GET_IMAGE ||
                    requestCode == RQS_PICK_IMAGE) {

                imageView.setImageBitmap(null);
                textInfo1.setText("");
                textInfo2.setText("");

                Uri mediaUri = data.getData();
                textInfo1.setText(mediaUri.toString());
                String mediaPath = mediaUri.getPath();
                textInfo2.setText(mediaPath);

                //display the image
                try {
                    InputStream inputStream = getBaseContext().getContentResolver().openInputStream(mediaUri);
                    Bitmap bm = BitmapFactory.decodeStream(inputStream);

                   ByteArrayOutputStream stream = new ByteArrayOutputStream();
                    byte[] byteArray = stream.toByteArray();

                    imageView.setImageBitmap(bm);

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

0

ギャラリーやカメラから画像を開く最も簡単な方法。

元の参照:プログラムでAndroidのギャラリーから画像を取得する

次のメソッドは、ギャラリーまたはカメラから画像を受け取り、ImageViewに表示します。選択した画像は内部に保存されます。

xmlのコード

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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:orientation="vertical"
    tools:context="com.exampledemo.parsaniahardik.uploadgalleryimage.MainActivity">

    <Button
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:id="@+id/btn"
        android:layout_gravity="center_horizontal"
        android:layout_marginTop="20dp"
        android:textAppearance="?android:attr/textAppearanceLarge"
        android:text="Capture Image and upload to server" />

    <TextView
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Below image is fetched from server"
        android:layout_marginTop="5dp"
        android:textSize="23sp"
        android:gravity="center"
        android:textColor="#000"/>

    <ImageView
        android:layout_width="300dp"
        android:layout_height="300dp"
        android:layout_gravity="center"
        android:layout_marginTop="10dp"
        android:scaleType="fitXY"
        android:src="@mipmap/ic_launcher"
        android:id="@+id/iv"/>

</LinearLayout>

JAVAクラス

import android.content.Intent;
import android.graphics.Bitmap;
import android.media.MediaScannerConnection;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.ImageView;
import android.widget.Toast;
import com.androidquery.AQuery;
import org.json.JSONException;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.HashMap;

public class MainActivity extends AppCompatActivity implements AsyncTaskCompleteListener{

    private ParseContent parseContent;
    private Button btn;
    private ImageView imageview;
    private static final String IMAGE_DIRECTORY = "/demonuts_upload_camera";
    private final int CAMERA = 1;
    private AQuery aQuery;

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

        parseContent = new ParseContent(this);
        aQuery = new AQuery(this);

        btn = (Button) findViewById(R.id.btn);
        imageview = (ImageView) findViewById(R.id.iv);

        btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                Intent intent = new Intent(android.provider.MediaStore.ACTION_IMAGE_CAPTURE);
                startActivityForResult(intent, CAMERA);
            }
        });

    }

    @Override
    public void onActivityResult(int requestCode, int resultCode, Intent data) {

        super.onActivityResult(requestCode, resultCode, data);
        if (resultCode == this.RESULT_CANCELED) {
            return;
        }
        if (requestCode == CAMERA) {
            Bitmap thumbnail = (Bitmap) data.getExtras().get("data");
            String path = saveImage(thumbnail);
            try {
                uploadImageToServer(path);
            } catch (IOException e) {
                e.printStackTrace();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }
    }

    private void uploadImageToServer(final String path) throws IOException, JSONException {

        if (!AndyUtils.isNetworkAvailable(MainActivity.this)) {
            Toast.makeText(MainActivity.this, "Internet is required!", Toast.LENGTH_SHORT).show();
            return;
        }

        HashMap<String, String> map = new HashMap<String, String>();
        map.put("url", "https://demonuts.com/Demonuts/JsonTest/Tennis/uploadfile.php");
        map.put("filename", path);
        new MultiPartRequester(this, map, CAMERA, this);
        AndyUtils.showSimpleProgressDialog(this);
    }

    @Override
    public void onTaskCompleted(String response, int serviceCode) {
        AndyUtils.removeSimpleProgressDialog();
        Log.d("res", response.toString());
        switch (serviceCode) {

            case CAMERA:
                if (parseContent.isSuccess(response)) {
                    String url = parseContent.getURL(response);
                    aQuery.id(imageview).image(url);
                }
        }
    }

    public String saveImage(Bitmap myBitmap) {
        ByteArrayOutputStream bytes = new ByteArrayOutputStream();
        myBitmap.compress(Bitmap.CompressFormat.JPEG, 90, bytes);
        File wallpaperDirectory = new File(
                Environment.getExternalStorageDirectory() + IMAGE_DIRECTORY);
        // have the object build the directory structure, if needed.
        if (!wallpaperDirectory.exists()) {
            wallpaperDirectory.mkdirs();
        }

        try {
            File f = new File(wallpaperDirectory, Calendar.getInstance()
                    .getTimeInMillis() + ".jpg");
            f.createNewFile();
            FileOutputStream fo = new FileOutputStream(f);
            fo.write(bytes.toByteArray());
            MediaScannerConnection.scanFile(this,
                    new String[]{f.getPath()},
                    new String[]{"image/jpeg"}, null);
            fo.close();
            Log.d("TAG", "File Saved::--->" + f.getAbsolutePath());

            return f.getAbsolutePath();
        } catch (IOException e1) {
            e1.printStackTrace();
        }
        return "";
    }
}

0

ここに私の例があります、あなたのケースとして正確ではないかもしれません。


APIプロバイダーからbase64形式を取得し、それにファイル名とファイル拡張子を付けて、ファイルシステムの特定の場所に保存するとします。

public static void shownInBuiltInGallery(final Context ctx, String strBase64Image, final String strFileName, final String strFileExtension){

new AsyncTask<String, String, File>() {
    @Override
    protected File doInBackground(String... strBase64Image) {

        Bitmap bmpImage = convertBase64StringToBitmap(strBase64Image[0], Base64.NO_WRAP);

        if(bmpImage == null) {
            cancel(true);
            return null;
        }

        byte[] byImage = null;

        if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_JPG) == 0) {
            byImage = convertToJpgByte(bmpImage); // convert bitmap to binary for latter use
        } else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_PNG) == 0){
            byImage = convertToPngByte(bmpImage); // convert bitmap to binary for latter use
        } else if(strFileExtension.compareToIgnoreCase(FILE_EXTENSION_BMP) == 0){
            byImage = convertToBmpByte(bmpImage); // convert bitmap to binary for latter use
        } else {
            cancel(true);
            return null;
        }

        if(byImage == null) {
            cancel(true);
            return null;
        }

        File imageFolder = ctx.getExternalCacheDir();

        if(imageFolder.exists() == false){
            if(imageFolder.mkdirs() == false){
                cancel(true);
                return null;
            }
        }

        File imageFile = null;

        try {
            imageFile = File.createTempFile(strFileName, strFileExtension, imageFolder);
        } catch (IOException e){
            e.printStackTrace();
        }

        if(imageFile == null){
            cancel(true);
            return null;
        }

        if (imageFile.exists() == true) {
            if(imageFile.delete() == false){
                cancel(true);
                return null;
            }
        }

        FileOutputStream fos = null;

        try {
            fos = new FileOutputStream(imageFile.getPath());
            fos.write(byImage);
            fos.flush();
            fos.close();
        } catch (java.io.IOException e) {
            e.printStackTrace();
        } finally {
            fos = null;
        }

        return imageFile;
    }

    @Override
    protected void onPostExecute(File file) {
        super.onPostExecute(file);

            String strAuthority = ctx.getPackageName() + ".provider";
            Uri uriImage = FileProvider.getUriForFile(ctx, strAuthority, file);

            Intent intent = new Intent(Intent.ACTION_VIEW);
            intent.setDataAndType(uriImage, "image/*");
            intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
            ctx.startActivity(intent);

    }
}.execute(strBase64Image);}

AndroidManifest.xmlの最初の場所で適切なファイルプロバイダーを設定することを忘れないでください

        <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/file_paths"/>
    </provider>

ここで、ファイルパスは... / res / xml / file_path.xml内のxmlです。

<?xml version="1.0" encoding="utf-8"?>

<external-files-path name="external_files" path="Accessory"/>

<external-path name="ex_Download" path="Download/" />
<external-path name="ex_Pictures" path="Pictures/" />

<external-files-path name="my_Download" path="Download/" />
<external-files-path name="my_Pictures" path="Pictures/" />
<external-cache-path name="my_cache" path="." />

<files-path name="private_Download" path="Download/" />
<files-path name="private_Pictures" path="Pictures/" />
<cache-path name="private_cache" path="." />


簡単に言えば、最初にファイルプロバイダーを準備し、Uriをインテントに渡して既知のアクセス可能な画像ソースを取得します。それ以外の場合は、画像を目的の場所に保存してからその場所を(Uriとして)インテントに渡します。

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.