題名の通りAndroidでカメラとギャラリーから画像を得るにあたって少し、戸惑った所があるのでメモします。
AndroidではActivity(画面)を変更するときにIntentを使います。
Activityはスタックとして積まれていきます。
activityの時にactivity2に画面遷移するときにIntentを使って移動すると言った感じになります。
Intentは他のActivityを呼ぶものと考えてもらえるとわかりやすいと思います。
Intentには明示的なインテントと暗黙的なインテントが存在し、それぞれExplicit Intents・Implicit Intentsといいます。
明示的なインテントとは同じアプリ内のActivityを呼ぶときに使い、暗黙的なインテントとは暗黙的なだけになんとなくできそうなアプリをスマホ内で探して起動したアプリのActivityを呼ぶときに使います。
今回はカメラとギャラリーを開いて画像を得るので、暗黙的なインテントを使います。
二つのボタンが有り、それぞれをCameraButtonとGallaryButtonとして書きます。
まずは、カメラとギャラリーのインテントを飛ばすところです。
// メンバ変数 Uri m_uri; // ファイルの場所を示すもの final int RESULT_PICK_IMAGEFILE = 1001; // どこからIntentを飛ばしたかの判別するものでIntentを飛ばす時と、帰ってきた時に使う private ImageView imageView; // 画像を貼る場所 // カメラから画像を取得するIntentを飛ばす(カメラを起動するまで) CameraButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ String photoName = DateFormat.format("P_yyyyMMdd_kkmmss", System.currentTimeMillis()).toString() + ".jpg"; ContentValues contentValues = new ContentValues(); contentValues.put(MediaStore.Images.Media.TITLE, photoName); contentValues.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg"); m_uri = getContentResolver().insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues); Intent intentCamera = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); intentCamera.putExtra(MediaStore.EXTRA_OUTPUT, m_uri); startActivityForResult(intentCamera, RESULT_PICK_IMAGEFILE); } }); // ギャラリーから取得するIntentを飛ばす(ギャラリーを起動するまで) GallaryButton.setOnClickListener(new View.OnClickListener(){ @Override public void onClick(View v){ Log.d("DEBUG", "toGallaryButton was clicked."); Intent intentGallery; if (Build.VERSION.SDK_INT < 19) { intentGallery = new Intent(Intent.ACTION_GET_CONTENT); intentGallery.setType("image/*"); } else { intentGallery = new Intent(Intent.ACTION_OPEN_DOCUMENT); intentGallery.addCategory(Intent.CATEGORY_OPENABLE); intentGallery.setType("image/jpeg"); } startActivityForResult(intentGallery, RESULT_PICK_IMAGEFILE); } }); // 次にカメラで写真を撮ったり、ギャラリーで写真選択した時帰ってくる関数
ここまでは、他のアプリを起動するまでです。
ここからはカメラで写真を撮ったり、ギャラリーで写真を選択した後に帰ってくる関数です。
@Override public void onActivityResult(int requestCode, int resultCode, Intent resultData) { // ここがカメラとギャラリーから帰ってきたことを確認する。 if (requestCode == RESULT_PICK_IMAGEFILE && resultCode == Activity.RESULT_OK) { Uri uri = m_uri; String filePath = ""; if (resultData != null) { // ギャラリーからの時 uri = resultData.getData(); // pathの取得 apiによって違う if (Build.VERSION.SDK_INT < 19) { ContentResolver cr = getContentResolver(); String[] columns = {MediaStore.Images.Media.DATA }; Cursor c = cr.query(uri, columns, null, null, null); c.moveToFirst(); filePath = c.getString(0); c.close(); }else{ String strDocId = DocumentsContract.getDocumentId(uri); String[] strSplittedDocId = strDocId.split(":"); String strId = strSplittedDocId[strSplittedDocId.length - 1]; Cursor crsCursor = getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI , new String[] {MediaStore.MediaColumns.DATA} , "_id=?", new String []{strId}, null ); crsCursor.moveToFirst(); filePath = crsCursor.getString(0); } }else{ // カメラの時、pathの取得 apiによって違う if (Build.VERSION.SDK_INT < 19) { ContentResolver cr = getContentResolver(); String[] columns = {MediaStore.Images.Media.DATA }; Cursor c = cr.query(uri, columns, null, null, null); c.moveToFirst(); filePath = c.getString(0); c.close(); }else{ final List<String> paths = uri.getPathSegments(); String strId = paths.get(3); Cursor crsCursor = getContentResolver().query( MediaStore.Images.Media.EXTERNAL_CONTENT_URI , new String[] {MediaStore.MediaColumns.DATA} , "_id=?", new String []{strId}, null ); crsCursor.moveToFirst(); filePath = crsCursor.getString(0); } } //ここでFilePathやuriを使って画像をImageViewに貼る } }
ここですこし困ったことはKitKat以前と以後で色々めんどくさいことですね。
ただ画像をはるだけならuriだけでいいのでここまで複雑ではないのですが、今回はこの後のこともあってURIだけでなくFilePathも欲しかったので、そのためのコードになってます。
カメラであってもギャラリーであってもAPIが19未満の時は受け取り方は同じです。2回書いちゃってるので汚いですが、ギャラリーでしかresultData.getData();が呼べないのでこんなになっちゃってます。変えるものめんどくさくって…
APIが19以上の時はカメラとギャラリーでコードが変わります。
これもホントは同じはずなんですが、私の持ってるスマホ(Zenfone2とxperia z1f)では何故か分ける必要があったので変えました。
最後にコメントでImageViewで画像を貼るとあったのですが、スマホによってまたここでも少し厄介事があったので、また次に書きます。