カメラで撮影をして保存してみる。

androidでカメラを使ってみる。

で画面にカメラの映像を表示できたので、今度は移した画像を撮影して保存してみたいと思います。

今回は:カメラの使用方法(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();
 }
}

以上です。

前後の記事

前の記事:

次の記事:

関連の記事

コメント

:D 睡眠不足

RUNの真ん中のボタンを押して起動するとLaunch error: Failed to connect to remote VM. Connection refused.と出ます。
何が問題なのでしょうか。

:D admin

おそらく、アンドロイドのパブリッシュ先がみつからないのかと思います。
アンドロイド端末をPCにつなげて、パブリッシュしてみてください。(端末をeclipseに認識する為にはドライバが必要です。)ドライバは「端末名 ドライバ」とかで検索で出てきますので、おためしください。

:D 睡眠不足

ドライバについてよくわかりません。
ドライバのあるサイトや端末をeclipseに認識させる手順を教えてください。
よろしくお願いします。

:D admin

一番新しい記事に書いてみました。eclipseに端末を認識させる方法。分かりづらいかと思いますが。。端末で開発をした方が早いし、カメラ機能も完璧に使えるので、ベターかと思いますので、わからなかったら、他で書いてる人もいるので、実機で開発してみてください!!

:D 睡眠不足

おかげさまで、端末の認識は成功しました。
しかし、(Activityをコピペしてビルドしただけの)アプリケーションが強制終了になってしまいました。
AQUOSPHONEのAndroid2.3.5です。
原因がわかりませんか。
よろしくお願いします。

:D admin

強制終了になる場合には、eclipseにLogCatという機能があるのでメニューのWindow-ShowView-LogCatにあるのですが、エラーの内容が記述されています。
カメラの場合は表示サイズを間違えていたりするとエラーだったり、マニフェストの書き忘れかなーとおもいますがいかがでしょうか。

:D 睡眠不足

一からProjectを作りなおした結果無事にビルドすることができました。
ありがとうございます。

ところでAndroidの画面ロックを作る方法を教えていただけないでしょうか。
よろしくお願いします。

:D admin

作成した事がないのでちょっと分からないです。。すいませn。。

:D ab

Nexus7のカメラアプリを起動させ、画像を保存するときはどうすればいいですか?
カメラアプリの起動まではできています。

コメントの投稿

  • サイト内検索

新作アプリの紹介

関連サイトの紹介

アンドロイドアプリ開発TIPS
きぐるみカメラ
ふらいぱん
アンドロイドのデザイン集
Page top↑