みなさんこんにちは!
exも世間の波に乗り、Androidアプリを密かに始めていました!!?
最近は特に機種も増えてきて、賑わってきましたね。
しかし、開発側からすると嬉しいことだけではありません・・・
機種が増える=対応機種が増える わけでどこも苦労しているのではないでしょうか。
弊社も例外なく苦労しています・・・
そんなわけで、コードを交えて覗いてみたい方は、続きへお進みください!
exも世間の波に乗り、Androidアプリを密かに始めていました!!?
最近は特に機種も増えてきて、賑わってきましたね。
しかし、開発側からすると嬉しいことだけではありません・・・
機種が増える=対応機種が増える わけでどこも苦労しているのではないでしょうか。
弊社も例外なく苦労しています・・・
そんなわけで、コードを交えて覗いてみたい方は、続きへお進みください!
きてしまいましたね!?
Androidのアプリで、カメラボタンを押すと標準で入っているカメラアプリが立ち上がり、
写真を撮ると閉じて元のアプリの方に取り込まれるようなものを多く見かけると思います。
今回はそれのコードを元に、どんな罠があるのかを見ていきたいと思います!
とはいっても、残りが少なくなってきたので、ババンと載っけちゃいます・・Zzz
内蔵カメラアプリ起動
startActivityForResult() を呼び出すだけですが、そうした場合は、画像を受け取るときに
Intent 経由になるため、小さめの画像しか受け取れないのは有名な話かと思います。
そのため、EXTRA_OUTPUT にURIを指定し、そこに画像を保存してURIのみを
Intent 経由で受け取るようにします。
ここで問題が発生します。
カメラアプリがメーカー毎に仕様がことなるため、受け取り方がそれぞれ違います。。。
以下、確認しているパターン
2のパターンがなければ、data.getData() を参照する必要ないんですけどね・・・
3のパターンで、メンバ変数にURIを格納しておいても受け取り側で参照できない機種があることを発見し、回避するために、SharedPreferences を使用しています。
よくあるサンプルはメンバ変数に格納しているため、エラーで落ちてました (T_T)
撮影画像受け取り
新機種がでると、また困った子が出てくるかもしれません・・・
TODO 説明
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 経由で受け取るようにします。
ここで問題が発生します。
カメラアプリがメーカー毎に仕様がことなるため、受け取り方がそれぞれ違います。。。
以下、確認しているパターン
- EXTRA_OUTPUTで指定した場所に画像を保存し、data.getData() で保存した画像のURIが取得できる
- EXTRA_OUTPUTで指定した場所にとは違うところに画像を保存し、data.getData() で保存した画像のURIが取得できる
- EXTRA_OUTPUTで指定した場所に画像を保存し、data がnullになる
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 説明