Android学习十---Android Camera

Android camera用来拍照和拍摄视频的先看一下最后实现的效果图

            最后的效果图

Android学习十---Android Camera_第1张图片Android学习十---Android Camera_第2张图片

一、准备

在你的应用程序上使用android拍照设备,需要考虑以下几个方面

1. 是否是一定需要camera

如果需要,那么就无法安装在没有摄像头的设备。

需要在mainfest 中声明

<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />

2. 是想用怎样的方式来使用相机

可以有两种方式
2.1 简单的拍照 使用已经存在camera apps 
2.2 需要更多定制的功能,创建一个camera app

3. 存储方式

是只能在本应用程序里使用还是可以被其他程序使用。

二、相关类

android.hardware.camera2
包中包含控制设备相机的基本类
Camera
过时不用的相机控制类
SurfaceView
提供实时的相机预览
MediaRecorder 
用来记录video
Intent
使用
MediaStore.ACTION_IMAGE_CAPTURE
MediaStore.ACTION_VIDEO_CAPTURE
两个Intent类型来捕获图像和视频

三、Manifest声明

camera许可
<uses-permission android:name="android.permission.CAMERA" />
camera特征
<uses-feature android:name="android.hardware.camera" />
存储许可
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

音视频录制

<uses-permission android:name="android.permission.RECORD_AUDIO" />

位置许可

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

四、使用已经存在的camera apps

使用方式是用Intent,使用Intent能够使用最少的代码来获取图片
流程主要是
创建一个camera Intent,Intent的类型包括,MediaStore.ACTION_IMAGE_CAPTUREMediaStore.ACTION_VIDEO_CAPTURE启动一个camera Intent,使用startActivityForResult()方法来执行一个camera intent,在启动Intent后,camera应用界面能够显示在设备屏幕来供使用
接受Intent的结果,使用onActivityResult()方法来接受Intent的回调和数据。当用户结束拍照后,系统调用这一方法。
下列代码显示如何创建一个camera intent并执行
private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100; private Uri fileUri; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // create Intent to take a picture and return control to the calling application Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE); // create a file to save the image intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri); // set the image file name // start the image capture Intent     startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);
}

 

接收camera intent的结果,主要是重载onActivityResult。

private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100; private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200; @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) { if (resultCode == RESULT_OK) { // Image captured and saved to fileUri specified in the Intent Toast.makeText(this, "Image saved to:\n" +
                     data.getData(), Toast.LENGTH_LONG).show();
        } else if (resultCode == RESULT_CANCELED) { // User cancelled the image capture } else { // Image capture failed, advise user         }
    }
}

!一但程序接受到一个成功的结果,那么应用程序就可以获取在指定路径下的图片。

五、创建一个Camera App

官方建议使用新的android.hardware.camera2,使用旧的Camera API会出现deprecated的警告。

一般创建一个定制Camera接口的步骤包括

1.检测和获取camera

/** Check if this device has a camera */ private boolean checkCameraHardware(Context context) { if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){ // this device has a camera return true; } else { // no camera on this device return false;
    }
}
/** A safe way to get an instance of the Camera object. */ public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); // attempt to get a Camera instance  } catch (Exception e){ // Camera is not available (in use or does not exist)  } return c; // returns null if camera is unavailable }

2.创建一个预览类

/** A basic Camera preview class */ public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback { private SurfaceHolder mHolder; private Camera mCamera; public CameraPreview(Context context, Camera camera) { super(context); mCamera = camera; // Install a SurfaceHolder.Callback so we get notified when the // underlying surface is created and destroyed. mHolder = getHolder(); mHolder.addCallback(this); // deprecated setting, but required on Android versions prior to 3.0  mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); } public void surfaceCreated(SurfaceHolder holder) { // The Surface has been created, now tell the camera where to draw the preview. try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch (IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } public void surfaceDestroyed(SurfaceHolder holder) { // empty. Take care of releasing the Camera preview in your activity.  } public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) { // If your preview can change or rotate, take care of those events here. // Make sure to stop the preview before resizing or reformatting it. if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch (Exception e){ // ignore: tried to stop a non-existent preview  } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch (Exception e){ Log.d(TAG, "Error starting camera preview: " + e.getMessage());
        }
    }
}

3.创建一个预览的布局

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="horizontal"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
  <FrameLayout android:id="@+id/camera_preview"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:layout_weight="1"
    />

  <Button android:id="@+id/button_capture"
    android:text="Capture"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:layout_gravity="center"
    />
</LinearLayout>

 

public class CameraActivity extends Activity { private Camera mCamera; private CameraPreview mPreview; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Create an instance of Camera mCamera = getCameraInstance(); // Create our Preview view and set it as the content of our activity. mPreview = new CameraPreview(this, mCamera); FrameLayout preview = (FrameLayout) findViewById(R.id.camera_preview);
        preview.addView(mPreview);
    }
}

4.开始监听捕获事件

private PictureCallback mPicture = new PictureCallback() { @Override public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(MEDIA_TYPE_IMAGE); if (pictureFile == null){ Log.d(TAG, "Error creating media file, check storage permissions: " +
                e.getMessage());
            return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage());
        }
    }
};

5.捕获并保存文件

// Add a listener to the Capture button Button captureButton = (Button) findViewById(id.button_capture); captureButton.setOnClickListener( new View.OnClickListener() { @Override public void onClick(View v) { // get an image from the camera mCamera.takePicture(null, null, mPicture);
        }
    }
);

保存图片到SD卡中

private PictureCallback mPicture = new PictureCallback() { /** Create a File for saving an image or video */

        @Override
        public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(); if (pictureFile == null) { Log.d(TAG,"Error creating media file, check storage permissions: "); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage()); } camera.startPreview(); } }; private File getOutputMediaFile() { // To be safe, you should check that the SDCard is mounted // using Environment.getExternalStorageState() before doing this. 
        File mediaStorageDir = new File( Environment .getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp"); // This location works best if you want the created images to be shared // between applications and persist after your app has been uninstalled. // Create the storage directory if it does not exist if (!mediaStorageDir.exists()) { if (!mediaStorageDir.mkdirs()) { Log.d("MyCameraApp", "failed to create directory"); return null; } } // Create a media file name  File mediaFile; String timeStamp = String.format("%d.jpg", System.currentTimeMillis()); mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_" + timeStamp + ".jpg"); return mediaFile;
    }

6.释放相机

public class CameraActivity extends Activity { private Camera mCamera; private SurfaceView mPreview; private MediaRecorder mMediaRecorder; ... @Override protected void onPause() { super.onPause(); releaseMediaRecorder(); // if you are using MediaRecorder, release it first releaseCamera(); // release the camera immediately on pause event  } private void releaseCamera(){ if (mCamera != null){ mCamera.release(); // release the camera for other applications mCamera = null;
        }
    }
}

caution:

相机是一个共享资源,所以每次使用完毕后要记得调用Camera.release()来释放,否则后续想要获取相机的应用都会被关闭。

六、注意问题

6.1 拍完成照片后,停在拍照完成的界面,无法继续拍摄

在onPictureTaken的实现最后添加一个启动预览camera.startPreview();

private PictureCallback mPicture = new PictureCallback() { /** Create a File for saving an image or video */

        @Override
        public void onPictureTaken(byte[] data, Camera camera) { File pictureFile = getOutputMediaFile(); if (pictureFile == null) { Log.d(TAG,"Error creating media file, check storage permissions: "); return; } try { FileOutputStream fos = new FileOutputStream(pictureFile); fos.write(data); fos.close(); } catch (FileNotFoundException e) { Log.d(TAG, "File not found: " + e.getMessage()); } catch (IOException e) { Log.d(TAG, "Error accessing file: " + e.getMessage());
            }
            camera.startPreview();

        }

    };

代码:

https://github.com/dawnminghuang/android_camera

参考资料

http://developer.android.com/guide/topics/media/camera.html

你可能感兴趣的:(android,Camera,demos)