カメラアプリとの連携
カメラアプリのエミュレートができたところで、いよいよコーディングに入っていきます。
カメラアプリへの暗黙的インテント
カメラアイコンをタップした時の処理メソッドはonCameraImageClick()なので、ここに暗黙的インテントを利用した、カメラアプリ起動のソースコードを記述します。以下のonCameraImageClick()メソッドをUseCameraActivityに追記してください。
public void onCameraImageClick(View view) {
Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); // (1)
startActivityForResult(intent, 200); // (2)
}
追記したらアプリを起動してください。図1と変わらない画面ですが、画面をタップすると今度は以下のようにカメラアプリが起動するようになっています。
適当なタイミングでシャッターを切ってください。シャッター横に「✔」のアイコンが表示されます。これをタップしてください。すると、元のカメラ連携サンプルアプリに戻ってきます。
このように、無事カメラアプリと連携できるようになりました。
では、ソースコードを見ていきましょう。基本部分は前回解説した暗黙的インテントと差がありません。(1)でIntentオブジェクトをnewし、(2)でアクティビティを起動しています。ただ、少し前回から変わっています。暗黙的インテントでは、Intentをnewするときにアクションを指定しますが、カメラアプリの場合は、(1)のように、
MediaStore.ACTION_IMAGE_CAPTURE
とMediaStoreの定数を使います。また、これだけでカメラアプリを表すので第2引数のURIオブジェクトは不要です。
For Result
ところで、(2)に注目してください。今までのアクティビティ起動は
startActivity(intent);
でした。ところが、今回はstartActivityForResult()と「ForResult」がついています。アクティビティを起動する際、前回の地図アプリのように起動先アクティビティをそのまま使い続ける場合もありますが、今回のカメラのように一通りの処理(例えば撮影など)が終了した際に、起動元アクティビティに処理を戻すこともできます。カメラアプリの場合は、そもそもそういう使い方を想定していますので、
MediaStore.ACTION_IMAGE_CAPTURE
で起動し、撮影が終了すれば、必ず元のアプリに戻ってきます。その際、何らかの処理を行う必要があります。今回でいえば、撮影された画像を表示することです。その場合はstartActivityForResult()で起動します。そうすると、戻ってきたときにonActivityResult()メソッドが実行されるという仕組みになっています。
そのstartActivityForResult()ですが、第2引数があります。今回は「200」という数値を渡しています。この使い方については後述します。
戻ってきたときの処理
では、そのonActivityResult()メソッドを記述しましょう。以下のソースコードを追記してください。
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == 200 && resultCode == RESULT_OK) { // (1)
Bitmap bitmap = data.getParcelableExtra("data"); // (2)
ImageView ivCamera = (ImageView) findViewById(R.id.ivCamera); // (3)
ivCamera.setImageBitmap(bitmap); // (3)
}
}
追記できた時点でアプリを再起動し、画面をタップしてカメラアプリで撮影、✔をタップという一連の操作を行ってください。カメラ連携サンプルアプリに戻ると、以下のように撮影された画像が表示されていると思います。
では、ソースコードを解説していきましょう。まず、onActivityResult()の引数を理解しておく必要があります。
第1引数:int requestCode
先述のstartActivityForResult()の第2引数の値がそのままここに渡されます。もし、同一アクティビティから別の複数のアクティビティを起動する場合、どのアクティビティからの戻りなのかを区別するために利用する数値です。こちらは任意の値が利用できます。したがって、あらかじめどの数値をどのアクティビティの起動に利用するのかを設計しておく必要があります。
第2引数:int resultCode
起動先アクティビティが、起動元に戻す際に処理が正常に終了したかどうかを伝えてくれる引数です。定数値を利用し、値は以下の2種しかありません。
RESULT_OK:処理が成功 RESULT_CANCEL:処理をキャンセル
第3引数:Intent data
このアクティビティ起動に関連したIntentオブジェクトそのものです。データの引き渡しがある場合は、この中のextrasを使ってデータを取り出せます。
上記引数が理解できると(1)が理解できると思います。リスト3の(2)の第2引数で「200」を渡しているので、ImageViewにカメラで撮影された画像を表示するのはrequestCodeが「200」の場合で、かつ、カメラアプリでの処理が成功した場合、つまりresultCodeがRESULT_OKの場合のみです。これが(1)のifブロックの意味です。
では、ifブロックの中を見ていきましょう。大まかな手順としては、
- カメラアプリが撮影した画像を取得(リスト4の(2))
- その画像をImageViewに適用(リスト4の(3))
となります。
手順1.にあたるのがリスト4の(2)です。カメラアプリは撮影した画像をBitmapオブジェクトの形式に加工し、Intentオブジェクトに格納したうえで処理を戻してくれます。そのため、まずは第3引数のIntentオブジェクトdataからそれを取得します。Bitmapオブジェクトの名前は「data」です。
次に、手順2.にあたるのがリスト4の(3)の2行です。こちらは特に解説する必要はないでしょう。
