GraveDollの備忘録ブログ

勉強したことや捗るグッズの備忘録です。

修行その壱「フォトメモ」(5)

放置していたフォトメモの修行を再開しますw
今回はonActivityResult()内のエラー処理部分を追加しました。
エラー処理をきちんとしていないと、突然強制終了されてイラッとするので気をつけたいですね。

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;

import android.app.Activity;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.PackageManager;
import android.content.res.Configuration;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Matrix;
import android.net.Uri;
import android.os.Bundle;
import android.os.Environment;
import android.provider.MediaStore;
import android.view.Display;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Toast;

// メイン画面(Activity)
public class PhotoMemoActivity extends Activity {

	static final int REQUEST_CAPTURE_IMAGE = 100;/* onActivityResult内で識別するためのID */
	// 描画対象のViewを保持するメンバ変数
	private PhotoMemoView view;
	private Uri saveUri;// 写真を格納場所を示すURI
	String directory;// 写真を格納するディレクトリ
	String fileName;// 写真のファイル名

	// 画面(Activity)が生成されるときの処理
	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);

		// 外部ストレージがない場合、メッセージを出して終了
		if (!Environment.getExternalStorageState().equals(
				Environment.MEDIA_MOUNTED)) {
			Toast.makeText(this, R.string.message_externalstorage_not_mounted,
					Toast.LENGTH_SHORT).show();
			finish();
		} else {
			fileName = "IMG" + String.valueOf(System.currentTimeMillis())
					+ ".png";// IMG+現在時刻.pngというファイル名で保存される
			directory = Environment.getExternalStorageDirectory()
					+ getPackageName();// パッケージ名のディレクトリに格納
			// 撮影した写真を格納するディレクトリを作成する(すでに存在する場合は、作成されない)
			new File(Environment.getExternalStorageDirectory()
					+ getPackageName()).mkdir();
			saveUri = Uri.fromFile(new File(directory, fileName));// URI設定
			view = null;// Viewを初期化

			if (!callCamera(saveUri)) {
				// カメラアプリを呼び出せなかった旨を表示し、
				Toast.makeText(this, R.string.message_no_camera,
						Toast.LENGTH_SHORT).show();
				// 写真のないViewを生成
				view = new PhotoMemoView(this);
				// Viewを画面に表示する
				setContentView(view);
			}
		}
	}

	private boolean callCamera(Uri saveUri) {
		Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// カメラアプリ呼び出しインテント生成
		intent.putExtra(MediaStore.EXTRA_OUTPUT, saveUri);// カメラアプリをインテントで呼び出すときに写真格納場所情報を渡すよう設定
		// 暗黙的インテントに応答できるアプリが1つ以上あるなら、
		if (getPackageManager().queryIntentActivities(intent,
				PackageManager.MATCH_DEFAULT_ONLY).size() > 0) {
			// カメラアプリ起動
			startActivityForResult(intent, REQUEST_CAPTURE_IMAGE);
			return true;
		} else {
			return false;
		}
	}

	@Override
	protected void onActivityResult(int requestCode, int resultCode, Intent data) {
		super.onActivityResult(requestCode, resultCode, data);
		if (REQUEST_CAPTURE_IMAGE == requestCode
				&& resultCode == Activity.RESULT_OK) {
			// (画面回転問題への対策)この時点で、画面が横向きであれば
			if (getResources().getConfiguration().orientation == Configuration.ORIENTATION_LANDSCAPE) {
				// 画面を横向きに固定する
				setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
				// そうでなければ(画面が縦向きであれば)、
			} else {
				// 画面を縦向きに固定する
				setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
			}
			File file = new File(directory, fileName);// 写真を格納するディレクトリ
			Bitmap capturedImage = null;

			try {
				if (file.exists()) {// 写真が存在するなら
					// 写真を読み込む
					capturedImage = loadBitmap(new FileInputStream(file));
				}
				// 存在せず、インテントの戻り値に写真ファイルへのURIを返す場合(撮影した写真を取り出すためのコンテントプロバイダを提供するカメラアプリの場合)、コンテントプロバイダから写真を読み込む
				else if (data != null && data.getData() != null) {
					capturedImage = loadBitmap(getContentResolver()
							.openInputStream(data.getData()));
				} else {
					// いずれでもない場合(写真の取り込みに失敗)
					// 写真のないViewを生成する
					view = new PhotoMemoView(this);
					setContentView(view);
				}
			} catch (FileNotFoundException e) {
				e.printStackTrace();
			}

			if (capturedImage != null) {
				// 描画対象のViewを生成し、
				view = new PhotoMemoView(this, capturedImage);
				// 描画対象のViewを画面に表示する
				setContentView(view);
				view.setImageBitmap(capturedImage);// ビットマップ画像をimageViewに表示
			} else {
				// 写真を取り込めなかった旨を表示し、
				Toast.makeText(this, "写真を取り込みに失敗しました。", Toast.LENGTH_SHORT)
						.show();
				// 写真のないViewを生成する
				view = new PhotoMemoView(this);
			}

		}
	}

	// ファイル等のInputStreamから画像(撮影した写真)を読み込む
	private Bitmap loadBitmap(InputStream is) {
		// 読み込む画像のデータサイズの上限(1MB)
		final int BITMAP_SIZE_MAX = 1 * 1024 * 1024;

		// 読み込んだ画像を格納するBitmapを用意する
		Bitmap bitmap = null;
		try {
			// ファイルサイズ(InputStreamのサイズ)が、読み込む上限を超えている場合、
			if (is.available() > BITMAP_SIZE_MAX) {
				// 画像を小さくして読み込む(大きな画像を読み込んだ場合に発生するメモリ不足への対策)
				BitmapFactory.Options options = new BitmapFactory.Options();
				options.inSampleSize = is.available() / BITMAP_SIZE_MAX + 1;
				bitmap = BitmapFactory.decodeStream(is, null, options);
				// 上限を超えていない場合、
			} else {
				// そのまま読み込む
				bitmap = BitmapFactory.decodeStream(is);
			}
			is.close();
		} catch (IOException e) {
			e.printStackTrace();
		}
		// 読み込んだ画像を返す
		return bitmap;
	}

	// 端末のメニューボタンが押されたときの処理
	@Override
	public boolean onCreateOptionsMenu(Menu menu) {
		// res/menu/menu.xmlを読み込み、メニューを生成する
		getMenuInflater().inflate(R.menu.menu, menu);
		return super.onCreateOptionsMenu(menu);
	}

	// メニューの項目が選ばれたときの処理
	@Override
	public boolean onOptionsItemSelected(MenuItem item) {
		// 選ばれたメニューの種類(ID)に応じて、処理する
		switch (item.getItemId()) {
		// メニュー「線の太さ」の処理
		case R.id.menu_paintwidth:
			// まだ処理を実装していない旨のメッセージを表示する
			Toast.makeText(this, R.string.message_no_function,
					Toast.LENGTH_SHORT).show();
			break;
		// メニュー「線の色」の処理
		case R.id.menu_paintcolor:
			// まだ処理を実装していない旨のメッセージを表示する
			Toast.makeText(this, R.string.message_no_function,
					Toast.LENGTH_SHORT).show();
			break;
		default:
			break;
		}
		return super.onOptionsItemSelected(item);
	}
}