SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

DeveloperZine(デベロッパージン)- エンジニアの意思決定を支える技術情報メディア ProductZine

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

Android Studio 2で始めるアプリ開発入門

Androidカメラアプリとの連携

Android Studio 2で始めるアプリ開発入門 第15回


ストレージ経由での連携

 これで、一通りカメラアプリとの連携ができました。しかし図7を見てもわかるように、非常に小さな画像しか取得できません。そこで、撮影された画像をいったんストレージに保存したうえでそれを取得する方法をとることにします。

Uri

 Androidでは端末のストレージに保存された画像や音楽、電話帳などは標準で公開されています。これらの公開されたデータを特定する際、AndroidではURIで表します。また前回と同様に、このURI文字列をオブジェクトとして扱えるUriというクラスがAndroidには用意されています。今回、カメラアプリで撮影された画像をいったんストレージに保存しますが、その保存された画像を表すURIですべてをやり取りします。そこで、UseCameraActivityを以下のように改造します。

リスト5 UseCameraActivityの改造
public class UseCameraActivity extends AppCompatActivity {
 private Uri _imageUri;  // (1)

 @Override
 protected void onActivityResult(int requestCode, int resultCode, Intent data) {
  if(requestCode == 200 && resultCode == RESULT_OK) {
   ImageView ivCamera = (ImageView) findViewById(R.id.ivCamera);  // (2)
   ivCamera.setImageURI(_imageUri);  // (3)
  }
 }
      ~省略~
}

 まず、画像のUriオブジェクトのフィールドを追加しています。それが(1)です。さらに、onActivityResult()内を(2)と(3)の2行だけに変更しています。(2)は既に存在するコードです。画像URIを利用する場合、リスト4のようにIntentオブジェクトから画像オブジェクトを取得する必要がなく、ImageViewのsetImageURI()メソッドにUriオブジェクトを渡すだけでその画像が表示されます。それが(3)です。

 これで、画像の表示部分はできました。

URI指定でのカメラ起動

 では、次にこのURI指定でカメラアプリを起動するように改造していきましょう。カメラアプリの起動ですので、onCameraImageClick()メソッド内の改造です。以下のように書き換えてください。

リスト6 onCameraImageClick()メソッドの改造
public void onCameraImageClick(View view) {
 SimpleDateFormat dateFormat = new SimpleDateFormat("yyyyMMddHHmmss");  // (1)
 Date now = new Date(System.currentTimeMillis());  // (1)
 String nowStr = dateFormat.format(now);  // (1)
 String fileName = "UseCameraActivityPhoto_" + nowStr +".jpg";  // (1)

 ContentValues values = new ContentValues();  // (2)
 values.put(MediaStore.Images.Media.TITLE, fileName);  // (3)
 values.put(MediaStore.Images.Media.MIME_TYPE, "image/jpeg");  // (4)

 ContentResolver resolver = getContentResolver();  // (5)
 _imageUri = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);  // (6)

 Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);  // (7)
 intent.putExtra(MediaStore.EXTRA_OUTPUT, _imageUri);  // (8)
 startActivityForResult(intent, 200);  // (9)
}

 (7)と(9)はもともと記述されていたコードです。(7)でnewしたIntentオブジェクトのExtra情報としてUriオブジェクトを渡すのが最終目標です。それが(8)です。その際、キーとして定数「MediaStore.EXTRA_OUTPUT」を渡します。ただ、このままでは_imageUriはnullのままです。ですので、あらかじめこの_imageUriの中身を生成しておく必要があります。そのソースコードが(1)~(6)です。

 実際にUriオブジェクトを生成してくれるのがContentResolverオブジェクトです。これを取得しているのが(5)です。これは、ActivityのメソッドgetContentResolver()メソッドで取得できます(正確には親クラスであるContextWrapperのメソッドです)。このContentResolverオブジェクトのinsertメソッドを使うことで、新しいデータの格納先を確保し、それを表すUriオブジェクトを生成してくれます。それが(6)です。その際、引数として2個必要です。第1引数はデータの格納先を表すUriオブジェクトです。画像ファイルを格納するストレージを表すUriオブジェクトは、定数が用意されています。それが「MediaStore.Images.Media.EXTERNAL_CONTENT_URI」です。第2引数は、具体的にどういったデータなのかを表す値が格納されたContentValuesオブジェクトです。これを生成しているのが(2)~(4)です。

 (2)でContentValuesをnewします。ContentValuesオブジェクトはMapオブジェクトのようにさまざまなデータを、しかもデータ型をあまり気にせずに格納できる仕組みがあります。データを格納するにはput()メソッドを使います。

 (3)でそのメソッドを使い、画像のファイル名を指定しています。その際のキーは「MediaStore.Images.Media.TITLE」です。値は画像のファイル名なので任意の文字列でいいのですが、撮影のたびにファイル名が変化するようにタイムスタンプを使用してユニークになるようにしています。その文字列を生成しているのが(1)の4行です。

 (4)で同様にput()メソッドを使い、ファイルの種類を指定しています。その際のキーは「MediaStore.Images.Media.MIME_TYPE」で、値は「image/jpeg」です。これでJPEG画像が生成されます。

ストレージ利用のパーミッション付与

 これで一通り、ストレージ経由でのカメラアプリ連携のコーディングが終了しました。ただし、この状態でアプリ起動後にカメラアイコンをタップしてもエラーで終了します。ストレージを利用するにはパーミッションをアプリに与える必要があります。そこを記述しましょう。

 まず、AndroidManifest.xmlに以下の1行を追加してください。

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

 次に、onCameraImageClick()メソッドの1番初めに以下のコードを追記してください。

リスト7 onCameraImageClick()メソッドへの追記
public void onCameraImageClick(View view) {
 if(ActivityCompat.checkSelfPermission(this, Manifest.permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
  String[] permissions = {Manifest.permission.WRITE_EXTERNAL_STORAGE};
  ActivityCompat.requestPermissions(this, permissions, 2000);
  return;
 }
      ~省略~
}

 前回解説したパーミッションチェックコードです。パーミッション名が今回はストレージ利用のため、

Manifest.permission.WRITE_EXTERNAL_STORAGE

と、なっていること以外は前回と全く同じコードなので、解説は不要でしょう。

 この状態でアプリを再起動し、カメラアイコンをタップしてください。以下の許可を求めるダイアログが表示されるので「許可」をタップしてください。

図8 許可を求めるダイアログ
図8 許可を求めるダイアログ

 カメラ連携サンプルアプリの画面に戻るので、もう一度カメラアイコンをタップしてください。無事カメラアプリが起動します。あとは、ストレージを経由しない場合と同様に操作してください。カメラアプリからこのアプリに戻ってきた時に画像が表示されますが、ストレージを経由しない場合と違い、解像度の高い画像が表示されているはずです。

 なお、AVDによるカメラのエミュレーターでは、そもそもの画像解像度が高くないため、ストレージ経由にしてもあまり差を感じないかもしれませんが、実機では確実に差が出ます。

パーミッション許可後

 ここまでの実装で問題なく動作しますが、1点ユーザビリティが悪い部分があります。それは、許可ダイアログで許可した後にそのままカメラアプリへ遷移しないところです。これを解決するにはUseCameraActivityに、以下のメソッドを追記する必要があります。

リスト8 onCameraImageClick()メソッドへの追記
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
 if(requestCode == 2000 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
  ImageView ivCamera = (ImageView) findViewById(R.id.ivCamera);  // (1)
  onCameraImageClick(ivCamera);  // (2)
 }
}

 onRequestPermissionsResult()メソッドに関しては前回解説しています。ここではパーミッションが許可された時に、もう一度onCameraImageClick()を呼び出すようにしています。それが(2)です。ただ、onCameraImageClick()は引数としてタップされた画面部品オブジェクトを渡すことになっています。このメソッドはImageViewをタップする前提なので、あらかじめその部品を取得しています。それが(1)です。

 これで、パーミッション許可ダイアログで許可を与えた後、すぐカメラアプリに遷移するようになります。

まとめ

 今回は前回の続きとして、暗黙的インテントを利用してのカメラアプリとの連携を扱いました。次回はマテリアルデザインとツールバーを扱います。

この記事は参考になりましたか?

連載通知を行うには会員登録(無料)が必要です。
既に会員の方はを行ってください。
Android Studio 2で始めるアプリ開発入門連載記事一覧

もっと読む

この記事の著者

WINGSプロジェクト 齊藤 新三(サイトウ シンゾウ)

WINGSプロジェクトについて>有限会社 WINGSプロジェクトが運営する、テクニカル執筆コミュニティ(代表 山田祥寛)。主にWeb開発分野の書籍/記事執筆、翻訳、講演等を幅広く手がける。 2026年時点での登録メンバは約50名で、現在も執筆メンバを募集中。興味のある方は、どしどし応募頂きたい。著書記事多数。 RSS X: @WingsPro_info(公式)、@WingsPro_info/wings(メンバーリスト) Facebook <個人紹介>WINGSプロジェクト所属のテクニカルライター。Web系製作会社のシステム部門、SI会社を経てフリーランスとして独立。屋号はSarva(サルヴァ)。HAL大阪の非常勤講師を兼務。

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

山田 祥寛(ヤマダ ヨシヒロ)

静岡県榛原町生まれ。一橋大学経済学部卒業後、NECにてシステム企画業務に携わるが、2003年4月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト」代表。主な著書に「独習シリーズ(Java・C#・Python・PHP・Ruby・JSP&サーブレットなど)」「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravelなど)」「改訂3版JavaScript本格入門」「これからはじめるLaravel実践入門」「はじめてのAndroidアプリ開発 Kotlin編 」他、著書多数

※プロフィールは、執筆時点、または直近の記事の寄稿時点での内容です

この記事は参考になりましたか?

この記事をシェア

CodeZine(コードジン)
https://codezine.jp/article/detail/9913 2018/05/23 15:37

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー