[android]ギャラリーもしくはカメラから画像を持ってくる

  • 73
    Like
  • 3
    Comment
More than 1 year has passed since last update.

はじめに

    javaの基本的な理解はできている
    androidStudioの導入が完了している
同じく、開発初心者による備忘録のような形になります。
Day1.AndroidStudioにおけるプロジェクトの作り方
Day2.Androidアプリケーションの構成
Day3.アプリケーションのレイアウト
Day4.onClickListenerの実装とその後の処理
Day5.Activityのライフサイクル
Day6.xmlで枠を指定する
Day7.SDカードのpathの取得

ギャラリーもしくはカメラから画像を持ってくる

よくある処理だと思うので備忘録的に書き記しておきます。
御託はいいからコードをよこせという人は一番下まで飛ばしちゃってください。

つまったポイント

SDKのversionが19以上以下で処理が変わることに気づくのが遅かった

各種Intentの用意

カメラのIntent

.java
        String photoName = System.currentTimeMillis() + ".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);

カメラのほうは特に詰まることなく記述できました。
説明する箇所もないかと思います。

ギャラリー(ドキュメント)のIntent

余談ですがこのドキュメントというのわかりずらいので変えてほしいですね
上で一度触れていますがSDKversionが19以上の時とそれより下の時に呼び出す[intent.]が違います。具体的に見ていただくのが一番早いと思いますのでコードを下に記します。

.java
 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");
        }

createChooserについて

Intentのメソッドの一つにcreateChooserがあります。
暗示的Intentを使用する際createChooserを使用しないとデフォルトのダイアログが出てきます。これはよく見る「常にこのアプリを使用する」のチェックボックス付のダイアログです。もし、createChooserを使った場合これがなくなります。ちなみに、startActivityには対応していますがstartServiceには対応してないので注意してください。
また、ダイアログ上部の文も変えることができるという利点(?)があります。
もちろん必須メソッドではないです。

.java
        Intent intent = Intent.createChooser(intentCamera, "画像の選択");
        intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {intentGallery});
        startActivityForResult(intent, REQUEST_CHOOSER);

createChooserを用いてintentを持たせておき(ここではカメラのintentを)、そこにputExtraで「EXTRA_INITIAL_INTENTS」(ギャラリーのintentを)を与えています。
そしてそれをstartActivityForResultで起動します。

startActivityForResultについて

移動先Acitivtyから値を返してもらいたいときに使います。
呼び出されるメソッドは「onActivityResult」です。具体的に呼び出されるタイミングとしては移動先Activityがfinish()されたときです。
引数は

.java
startActivityForResult(Intent intent,int requestCode);
onActivityResult(int requestCode,int resultCode,Intent data);

onActivityResult

requestCodeはstartActivityForResultの第二引数がそのまま入ります。これをswitch文で分けることで処理を分けれます。
resultCode起動先のActivity.setResultの第一引数です。

コードを残して終了

.java
public class mainActivity extends ActionBarActivity {

    private Uri m_uri;
    private static final int REQUEST_CHOOSER = 1000;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        setViews();
    }
    private void setViews(){
        Button button = (Button)findViewById(R.id.buttonPanel);
        button.setOnClickListener(button_onClick);
    }
    private View.OnClickListener button_onClick = new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            showGallery();
        }
    };

    private void showGallery() {

        //カメラの起動Intentの用意
        String photoName = System.currentTimeMillis() + ".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);

        // ギャラリー用のIntent作成
        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");
        }
        Intent intent = Intent.createChooser(intentCamera, "画像の選択");
        intent.putExtra(Intent.EXTRA_INITIAL_INTENTS, new Intent[] {intentGallery});
        startActivityForResult(intent, REQUEST_CHOOSER);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);

        if(requestCode == REQUEST_CHOOSER) {

            if(resultCode != RESULT_OK) {
                // キャンセル時
                return ;
            }

            Uri resultUri = (data != null ? data.getData() : m_uri);

            if(resultUri == null) {
                // 取得失敗
                return;
            }

            // ギャラリーへスキャンを促す
            MediaScannerConnection.scanFile(
                    this,
                    new String[]{resultUri.getPath()},
                    new String[]{"image/jpeg"},
                    null
            );

            // 画像を設定
            ImageView imageView = (ImageView)findViewById(R.id.imageView);
            imageView.setImageURI(resultUri);
        }
    }
}


以上です