で画面にカメラの映像を表示できたので、今度は移した画像を撮影して保存してみたいと思います。
今回は:カメラの使用方法(2)を参考にさせていたふぁきました。
画像を取得する為にはmyCamera.takePicture()を実行すると、キャプチャを取得してくれる。
タッチをした時に実行をするので、
@Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (myCamera != null) myCamera.takePicture(mShutterListener, null, mPictureListener); } } return true; }
とします。
takePicture()には3つのデータを引数でcallback関数をいれるが、1つ目はシャッターを切った瞬間、2つ目はrowデータを取得した段階、3つ目はjpegに圧縮した段階で実行がされる。
rawデータは十分な要領がなければコピーできないので、nullかもしれないようです。
なので必然的に3つ目の関数で画像の保存などを行います。
private Camera.PictureCallback mPictureListener =new Camera.PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { } };
が画像の保存の部分です。
最初にデータの取得を確認をします。
if (data != null) { //空じゃない場合 }
次に以前ファイルの保存で勉強したように
private boolean sdcardWriteReady(){ String state = Environment.getExternalStorageState(); return (Environment.MEDIA_MOUNTED.equals(state)); }
を用意して、保存ができるかの確認をしてみます。
if(sdcardWriteReady()){ //保存できる。 }
次にディレクトリを用意してディレクトリが存在しない場合はディレクトリを作成します。
File file = new File(Environment.getExternalStorageDirectory().getPath() + "/cmr/"); if(!file.exists()){ file.mkdir(); }
他の画像と被らないようなファイル名を用意します。
String imgName = Environment.getExternalStorageDirectory().getPath() + "/cmr/" + System.currentTimeMillis() +".jpg";
作成した名前のファイルに画像を保存します。
foStream = new FileOutputStream(imgName); foStream.write(data); foStream.close();
アンドロイドのデータベースへの登録を行います。※登録をしないとギャラリーなどですぐに確認できません。
ContentValues values = new ContentValues(); ContentResolver contentResolver = context.getContentResolver(); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put("_data", imgName); contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values);
以上で完了です。
上記の分岐でエラーが出現した場合の文言を任意で決めて作成をします。また、連打防止の対策なども含めております。
package in.andante.camerapre; import java.io.*; import android.content.ContentResolver; import android.content.ContentValues; import android.content.Context; import android.hardware.Camera; import android.os.Environment; import android.provider.MediaStore; import android.provider.MediaStore.Images; import android.view.MotionEvent; import android.view.SurfaceHolder; import android.view.SurfaceView; import android.widget.Toast; public class CameraView extends SurfaceView implements SurfaceHolder.Callback{ private Camera myCamera; private Context context; private Boolean bool = true; public CameraView(Context context){ super(context); this.context = context; getHolder().addCallback(this); getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder){ myCamera = Camera.open(); try { myCamera.setPreviewDisplay(holder); } catch (Exception e) { e.printStackTrace(); } } public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){ Camera.Parameters parameters = myCamera.getParameters(); //parameters.setPreviewSize(width, height)不要でした。すいません; myCamera.setParameters(parameters); myCamera.startPreview(); } public void surfaceDestroyed(SurfaceHolder holder){ myCamera.release(); myCamera = null; } // シャッターが押されたときに呼ばれるコールバック private Camera.ShutterCallback mShutterListener = new Camera.ShutterCallback() { public void onShutter() { // TODO Auto-generated method stub } }; // JPEGイメージ生成後に呼ばれるコールバック private Camera.PictureCallback mPictureListener =new Camera.PictureCallback() { public void onPictureTaken(byte[] data, Camera camera) { if (data != null) { if(!sdcardWriteReady()){ Toast.makeText(context, "SDCARDが認識されません。", Toast.LENGTH_SHORT).show(); bool = true; camera.startPreview(); return; } FileOutputStream foStream = null; //フォルダのパスを表示します。。 File file = new File(Environment.getExternalStorageDirectory().getPath() + "/cmr/"); //フォルダが存在しなかった場合にフォルダを作成します。 if(!file.exists()){ file.mkdir(); } //これで他のとかぶらない名前の設定ができました。 String imgName = Environment.getExternalStorageDirectory().getPath() + "/cmr/" + System.currentTimeMillis() +".jpg"; try { foStream = new FileOutputStream(imgName); foStream.write(data); foStream.close(); ContentValues values = new ContentValues(); ContentResolver contentResolver = context.getContentResolver(); values.put(Images.Media.MIME_TYPE, "image/jpeg"); values.put("_data", imgName); try { contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, values); }catch(Exception e){ Toast.makeText(context, "再起動後に画像が認識されます。", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } } catch (Exception e) { Toast.makeText(context, "ファイルの保存中にエラーが発生しました。", Toast.LENGTH_SHORT).show(); e.printStackTrace(); } bool = true; camera.startPreview(); }else{ Toast.makeText(context, "データが取得できませんでした。", Toast.LENGTH_SHORT).show(); bool = true; camera.startPreview(); } } }; @Override public boolean onTouchEvent(MotionEvent event) { if (event.getAction() == MotionEvent.ACTION_DOWN) { if (myCamera != null && bool) { bool = false; myCamera.takePicture(mShutterListener, null, mPictureListener); } } return true; } //書き込みができるかどうかを判別する関数 private boolean sdcardWriteReady(){ String state = Environment.getExternalStorageState(); return (Environment.MEDIA_MOUNTED.equals(state)); } }
またmanifestは以下です。
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="in.andante.camerapre" android:versionCode="1" android:versionName="1.0"> <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.CAMERA"></uses-permission> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:name=".CameraPre" android:label="@string/app_name" android:screenOrientation="landscape" android:theme="@android:style/Theme.Black.NoTitleBar.Fullscreen"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
メインのjavaのファイルは以下です。
package in.andante.camerapre; import android.app.Activity; import android.os.Bundle; public class CameraPre extends Activity { /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); CameraView view = new CameraView(this); setContentView(view); //setContentView(R.layout.main); } protected void onResume(){ super.onResume(); } protected void onStop(){ super.onStop(); } public void onDestroy(){ super.onDestroy(); } }
以上です。