Android アプリ始めてました。

みなさんこんにちは!

exも世間の波に乗り、Androidアプリを密かに始めていました!!?
最近は特に機種も増えてきて、賑わってきましたね。

しかし、開発側からすると嬉しいことだけではありません・・・
機種が増える=対応機種が増える わけでどこも苦労しているのではないでしょうか。
弊社も例外なく苦労しています・・・

そんなわけで、コードを交えて覗いてみたい方は、続きへお進みください!
きてしまいましたね!?

Androidのアプリで、カメラボタンを押すと標準で入っているカメラアプリが立ち上がり、
写真を撮ると閉じて元のアプリの方に取り込まれるようなものを多く見かけると思います。
今回はそれのコードを元に、どんな罠があるのかを見ていきたいと思います!

とはいっても、残りが少なくなってきたので、ババンと載っけちゃいます・・Zzz

内蔵カメラアプリ起動
	private SharedPreferences sp;

	public void onClickCameraButton(){
		long dateTaken = System.currentTimeMillis();
		String filename = DateFormat.format("yyyy-MM-dd_kk.mm.ss", dateTaken).toString() + ".jpg";

		ContentResolver contentResolver = getContentResolver();
		ContentValues values = new ContentValues(5);
		values.put(Images.Media.MIME_TYPE, "image/jpeg");
		values.put(Images.Media.DATE_MODIFIED, System.currentTimeMillis()/1000);
		values.put(Images.Media.TITLE, filename);
		values.put(Images.Media.DISPLAY_NAME, filename);
		values.put(Images.Media.DATE_TAKEN,System.currentTimeMillis());
		Uri pictureUri = contentResolver.insert(
				Images.Media.EXTERNAL_CONTENT_URI, values);

		if(sp == null) sp = getPreferences(MODE_PRIVATE);
		Editor editor = sp.edit();
		editor.putString("pictureUri", pictureUri.toString());
		editor.commit();

		Intent intent = new Intent();
		intent.setAction("android.media.action.IMAGE_CAPTURE");
		intent.putExtra(MediaStore.EXTRA_OUTPUT, pictureUri);
		startActivityForResult(intent, MY_INTENT_CAMERA);
	}
単純にカメラアプリを起動するだけなら、setAction() でカメラアプリを指定して、
startActivityForResult() を呼び出すだけですが、そうした場合は、画像を受け取るときに
Intent 経由になるため、小さめの画像しか受け取れないのは有名な話かと思います。
そのため、EXTRA_OUTPUT にURIを指定し、そこに画像を保存してURIのみを
Intent 経由で受け取るようにします。
ここで問題が発生します。
カメラアプリがメーカー毎に仕様がことなるため、受け取り方がそれぞれ違います。。。
以下、確認しているパターン
  1. EXTRA_OUTPUTで指定した場所に画像を保存し、data.getData() で保存した画像のURIが取得できる
  2. EXTRA_OUTPUTで指定した場所にとは違うところに画像を保存し、data.getData() で保存した画像のURIが取得できる
  3. EXTRA_OUTPUTで指定した場所に画像を保存し、data がnullになる
上記パターンを網羅するため、予め保存場所のURIをもっておき、画像を受け取るときにdata.getData() が取得できなかった場合に、もっておいた保存場所のURIを参照する方法にしました。
2のパターンがなければ、data.getData() を参照する必要ないんですけどね・・・
3のパターンで、メンバ変数にURIを格納しておいても受け取り側で参照できない機種があることを発見し、回避するために、SharedPreferences を使用しています。
よくあるサンプルはメンバ変数に格納しているため、エラーで落ちてました (T_T)

撮影画像受け取り
@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		if (resultCode != RESULT_OK) {
			// 正しい結果が得られなかった場合の処理
			// 撮影キャンセルなどするとこっちに来る
			
			if(sp == null) sp = getPreferences(MODE_PRIVATE);
			Uri tmpUri = Uri.parse(sp.getString("pictureUri", ""));
			if(tmpUri != null){
				ContentResolver contentResolver = getContentResolver();
				try{
					contentResolver.delete(tmpUri, null, null);
				}catch (Exception e) {
					// 対象ファイルがない場合エラー
				}
				sp.edit().remove("pictureUri");
			}
			return;
		}

		if (requestCode == MY_INTENT_CAMERA) {
			// 撮影成功時の処理
			
			Uri resultUri = null;
			if(sp == null){
				sp = getPreferences(MODE_PRIVATE);
			}
			if(data != null && data.getData() != null){
				resultUri = data.getData();
			}else{
				resultUri = Uri.parse(sp.getString("pictureUri", ""));
			}
			
			// resultUri に撮影した画像のURIが格納されている
			// 後は煮るなり焼くなりご自由に♪
			// 使い終わったらURIにある画像の削除を忘れずに!
			
			return;
		}
	}
今のところ、これで画像は受け取れています。
新機種がでると、また困った子が出てくるかもしれません・・・


TODO 説明