您的位置:首页 > 其它

拍照、录视频

2015-09-13 15:14 591 查看

在Manifest中的声明

1.相机权限声明:

<!--如果是使用系统的相机拍照,可以不用声明此权限--><uses-permission android:name="android.permission.CAMERA" />

2.功能声明:

<!--只有带有摄像头的Android设备才能安装--><uses-feature android:name="android.hardware.camera" /><!--不要求只有待有摄像头的Android设备才能安装--><uses-feature android:name="android.hardware.camera" android:required="false" />

3.存储权限声明:

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

4.录制视频的权限声明:

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

5.位置权限:

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

用系统的相机拍照或录制视频的步骤:

1.创建Intent

2.startActivityForResult()

3.onActivityResult()


拍照的Intent:

private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;private Uri fileUri;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);fileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);}


视频的Intent:

private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;private Uri fileUri;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);fileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);intent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1); // 设置视频质量,从0到1由低到高,还可以设置时长(<code><a target=_blank href="http://developer.android.com/reference/android/provider/MediaStore.html#EXTRA_DURATION_LIMIT">MediaStore.EXTRA_DURATION_LIMIT</a></code>)和大小(<code><a target=_blank href="http://developer.android.com/reference/android/provider/MediaStore.html#EXTRA_SIZE_LIMIT">MediaStore.EXTRA_SIZE_LIMIT</a></code>)startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);}


接收Intent:

private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (requestCode == CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE) {if (resultCode == RESULT_OK) {// 返回在Intent中指定的图片保存路径fileUriToast.makeText(this, "Image saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();} else if (resultCode == RESULT_CANCELED) {// 用户取消拍摄图像后} else {// 图像捕获失败}}if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {if (resultCode == RESULT_OK) {// 返回在Intent中指定的视频保存路径fileUriToast.makeText(this, "Video saved to:\n" + data.getData(), Toast.LENGTH_LONG).show();} else if (resultCode == RESULT_CANCELED) {// 用户取消录制后} else {// 视屏录制失败}}}以上用到的:getOutputMediaFile(int type)private static File getOutputMediaFile(int type){// 检查SD卡File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp");// 这个地方是个好位置,如果你想给别的应用程序共享图片和视频,或者你希望你的应用在卸载之后忍让能够使用图片和视频,不太明白这是什么意思,求指点// 是在这里把照片和视频加到设备的媒体库中吗?// 如果目录不存在就创建if (! mediaStorageDir.exists()){if (! mediaStorageDir.mkdirs()){Log.d("MyCameraApp", "failed to create directory");return null;}}// Create a media file nameString timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());File mediaFile;if (type == MEDIA_TYPE_IMAGE){mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");} else if(type == MEDIA_TYPE_VIDEO) {mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4");} else {return null;}return mediaFile;}

自定义相机的介绍:

第一步,先检查是否支持自定义相机

/** Check if this device has a camera */private boolean checkCameraHardware(Context context) {if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)){// 设备有摄像头return true;} else {// 设备没有摄像头return false;}}可以通过Camera.getParameters()或者Camera.Parameters获取摄像头的许多功能特性和参数还可以通过Camera.getCameraInfo()获知摄像头的前、后属性和图片的方向

第二步,创建预览视图

/** 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;mHolder = getHolder();mHolder.addCallback(this);// 不建议使用,但在3.0之前要求调用mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);}public void surfaceCreated(SurfaceHolder holder) {try {mCamera.setPreviewDisplay(holder);mCamera.startPreview();} catch (IOException e) {Log.d(TAG, "Error setting camera preview: " + e.getMessage());}}public void surfaceDestroyed(SurfaceHolder holder) {// 记得在onDestory中释放preview}<pre name="code" class="java"> // 注意preview的改变或者旋转,如果要改变大小或者格式,确保preview先stoppublic void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {if (mHolder.getSurface() == null){return;}// 改变之前先stoptry {mCamera.stopPreview();} catch (Exception e){}//设置新的大小,方向和格式// 重新打开预览try {mCamera.setPreviewDisplay(mHolder);mCamera.startPreview();} catch (Exception e){Log.d(TAG, "Error starting camera preview: " + e.getMessage());}}}

第三步,预览布局

<?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"><FrameLayoutandroid:id="@+id/camera_preview"android:layout_width="fill_parent"android:layout_height="fill_parent"android:layout_weight="1"/><Buttonandroid: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;@Overridepublic void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);setContentView(R.layout.main);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);}}/** 以一种安全的方式获取相机实例,捕获异常信息为了防止相机获取不成功的情况 */public static Camera getCameraInstance(){Camera c = null;try {c = Camera.open();}catch (Exception e){// 摄像头不可用(正在使用/没有摄像头)}return c; // 如果摄像头不可用,则返回null}

第四步,拍照监听

// Add a listener to the Capture buttonButton captureButton = (Button) findViewById(id.button_capture);captureButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {mCamera.takePicture(null, null, mPicture);}});

第五步,捕获和保存

Camera.PictureCallback();private PictureCallback mPicture = new PictureCallback() {@Overridepublic 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());}}};

第六步,释放摄像头

Camera.realse();注:摄像头是共享的,所以在使用是必须小心的管理它,在使用完之后也要记得释放,否则下次调用时将会报错。

视频捕获

视频拍摄要求小心的管理Camera对象和MediaRecorder类,除了Camera.open()和Camera.close(),还要管理Camera.lock()和Camera.unlock()

1.打开摄像头

Camera.open()

2.连接预览

Camera.setPreviewDisplay()

3.打开预览

Camera.startPreview()

4.开始录制


a.解锁相机

Camera.unlock()


b.配置MediaRecorder

1.
setCamera()
2.
setAudioSource()
-->
MediaRecorder.AudioSource.CAMCORDER
3.
setVideoSource()
-->
MediaRecorder.VideoSource.CAMERA
.4.设置视频输出格式和编码:2.2+:
MediaRecorder.setProfile
CamcorderProfile.get()
2.2-:
setOutputFormat()
-->
MediaRecorder.OutputFormat.MPEG_4
setAudioEncoder()
-->
MediaRecorder.AudioEncoder.AMR_NB
setVideoEncoder()
-->
MediaRecorder.VideoEncoder.MPEG_4_SP
5.
setOutputFile()
6.
setPreviewDisplay()


c.准备MediaRecorder

MediaRecorder.prepare()


d.开始MediaRcorder

MediaRecorder.start()
private boolean prepareVideoRecorder(){mCamera = getCameraInstance();mMediaRecorder = new MediaRecorder();// Step 1: Unlock and set camera to MediaRecordermCamera.unlock();mMediaRecorder.setCamera(mCamera);// Step 2: Set sourcesmMediaRecorder.setAudioSource(MediaRecorder.AudioSource.CAMCORDER);mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA);// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_HIGH));// Step 4: Set output filemMediaRecorder.setOutputFile(getOutputMediaFile(MEDIA_TYPE_VIDEO).toString());// Step 5: Set the preview outputmMediaRecorder.setPreviewDisplay(mPreview.getHolder().getSurface());// Step 6: Prepare configured MediaRecordertry {mMediaRecorder.prepare();} catch (IllegalStateException e) {Log.d(TAG, "IllegalStateException preparing MediaRecorder: " + e.getMessage());releaseMediaRecorder();return false;} catch (IOException e) {Log.d(TAG, "IOException preparing MediaRecorder: " + e.getMessage());releaseMediaRecorder();return false;}return true;}
在2.2之前
// Step 3: Set output format and encoding (for versions prior to API Level 8)mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.DEFAULT);mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.DEFAULT);还可以配置以下参数
setVideoEncodingBitRate()

setVideoSize()

setVideoFrameRate()

setAudioEncodingBitRate()

setAudioChannels()

setAudioSamplingRate()

5.停止录制

1.
MediaRecorder.stop()
2.
MediaRecorder.reset()
3.
MediaRecorder.release()
4.
Camera.lock()

6.停止预览

Camera.stopPreview()

7.释放摄像头

Camera.release()

开始和停止

Unlock the camera with
Camera.unlock()

Configure
MediaRecorder
as shown in the code example above
Start recording using
MediaRecorder.start()

Record the video
Stop recording using
MediaRecorder.stop()

Release the media recorder with
MediaRecorder.release()

Lock the camera using
Camera.lock()
private boolean isRecording = false;// Add a listener to the Capture buttonButton captureButton = (Button) findViewById(id.button_capture);captureButton.setOnClickListener(new View.OnClickListener() {@Overridepublic void onClick(View v) {if (isRecording) {// stop recording and release cameramMediaRecorder.stop();  // stop the recordingreleaseMediaRecorder(); // release the MediaRecorder objectmCamera.lock();         // take camera access back from MediaRecorder// inform the user that recording has stoppedsetCaptureButtonText("Capture");isRecording = false;} else {// initialize video cameraif (prepareVideoRecorder()) {// Camera is available and unlocked, MediaRecorder is prepared,// now you can start recordingmMediaRecorder.start();// inform the user that recording has startedsetCaptureButtonText("Stop");isRecording = true;} else {// prepare didn't work, release the camerareleaseMediaRecorder();// inform user}}}});

释放摄像头

public class CameraActivity extends Activity {private Camera mCamera;private SurfaceView mPreview;private MediaRecorder mMediaRecorder;...@Overrideprotected void onPause() {super.onPause();releaseMediaRecorder(); // if you are using MediaRecorder, release it firstreleaseCamera(); // release the camera immediately on pause event}private void releaseMediaRecorder(){if (mMediaRecorder != null) {mMediaRecorder.reset(); // clear recorder configurationmMediaRecorder.release(); // release the recorder objectmMediaRecorder = null;mCamera.lock(); // lock camera for later use}}private void releaseCamera(){if (mCamera != null){mCamera.release(); // release the camera for other applicationsmCamera = null;}}}

保存

两个标准路径保存文件:
Environment.getExternalStoragePublicDirectory
(
Environment.DIRECTORY_PICTURES
):共享路径,当应用程序卸载后不会被删除
Context.getExternalFilesDir
(
Environment.DIRECTORY_PICTURES
):当应用程序卸载后会被删除
public static final int MEDIA_TYPE_IMAGE = 1;public static final int MEDIA_TYPE_VIDEO = 2;private static Uri getOutputMediaFileUri(int type){return Uri.fromFile(getOutputMediaFile(type));}private static File getOutputMediaFile(int type){//应该先检查SD卡的状态File mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES), "MyCameraApp");if (! mediaStorageDir.exists()){if (! mediaStorageDir.mkdirs()){Log.d("MyCameraApp", "failed to create directory");return null;}}String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());File mediaFile;if (type == MEDIA_TYPE_IMAGE){mediaFile = new File(mediaStorageDir.getPath() + File.separator + "IMG_"+ timeStamp + ".jpg");} else if(type == MEDIA_TYPE_VIDEO) {mediaFile = new File(mediaStorageDir.getPath() + File.separator + "VID_"+ timeStamp + ".mp4");} else {return null;}return mediaFile;}

摄像头的功能

Android支持许多你可以控制的摄像头功能,比如图片格式,闪光模式,焦点设置等等。以下列举通用的摄像头功能和描述怎么使用它们。许多功能是通过
Camera.Parameters
对象设置的。
FeatureAPI LevelDescription
Face Detection14人脸识别
Metering Areas14为一张图片制定一个或多个白平衡调节
Focus Areas14为一张图片摄者一个或多个焦点区域
White Balance Lock
14自动调节白平衡
Exposure Lock
14自动调节曝光
Video
Snapshot
14捕获图片
Time Lapse Video11延时视频
Multiple Cameras
9支持多个摄像头,包含前置和后置谁想头
%29]Focus Distance
9摄像头和拍摄物之间的距离
Zoom
8设置图片的放大率
ExposureCompensation
8增减曝光值
GPS Data
5包含或忽略图片的地理位置信息
White Balance
5设置平衡模式,影响图片的颜色值
Focus Mode
5设置焦点:automatic, fixed, macro or infinity
Scene Mode
5预设场景,比如夜晚,海滩,雪景或者烛光晚餐
JPEG Quality
5图片质量
Flash Mode
5闪光模式
Color Effects
5对图片使用颜色
Anti-Banding
5减小由于JPEG压缩对颜色渐变的影响
Picture Format
1指定图片的格式
Picture Size
1指定保存图片的尺寸
注:由于硬件和软件实现的不同,这些功能不是所有的设备都支持。所以在使用的时候需要现检查一下是否支持特定的功能。比如支持是否自动对焦:// get Camera parametersCamera.Parameters params = mCamera.getParameters();List<String> focusModes = params.getSupportedFocusModes();if (focusModes.contains(Camera.Parameters.FOCUS_MODE_AUTO)) {// Autofocus mode is supported}你也可以使用
Camera.Parameters
中的getSupported...(),isSupported...(),或者getMax...()方法去判断某些特定的摄像头功能。最后,可以在Manifest中声明指定的摄像头相关功能,这样Google Play会限制没有该功能的设备不予下载使用应用程序。摄像头功能的使用:// get Camera parametersCamera.Parameters params = mCamera.getParameters();// set the focus modeparams.setFocusMode(Camera.Parameters.FOCUS_MODE_AUTO);// set Camera parametersmCamera.setParameters(params);大多数摄像头的功能都可以通过如上方式设置,但是有一些功能不能被随便设置,比如拍摄图片大小和方向,必须要先停止预览,改变之后再重新预览,4.0之后,想要改变方向可以不用重启预览。还有一些功能需要编写更多的代码才能实现,比如:Metering and focus areas
Face detection
Time lapse video测光和调距:在一些摄影场景中,自定对焦和测光不能满足预期的效果,从4.0(api14)开始,允许自己定义这些功能属性:// Create an instance of CameramCamera = getCameraInstance();// set Camera parametersCamera.Parameters params = mCamera.getParameters();if (params.getMaxNumMeteringAreas() > 0){ // check that metering areas are supportedList<Camera.Area> meteringAreas = new ArrayList<Camera.Area>();Rect areaRect1 = new Rect(-100, -100, 100, 100); // specify an area in center of imagemeteringAreas.add(new Camera.Area(areaRect1, 600)); // set weight to 60%Rect areaRect2 = new Rect(800, -1000, 1000, -800); // specify an area in upper right of imagemeteringAreas.add(new Camera.Area(areaRect2, 400)); // set weight to 40%params.setMeteringAreas(meteringAreas);}mCamera.setParameters(params);人脸识别功能:人脸识别开启式,
setWhiteBalance(String)
,
setFocusAreas(List)
setMeteringAreas(List)
不起作用。第一步:检验是否支持人脸识别功能;
通过getMaxNumDetectedFaces()
第二步:创建人脸识别监听;class MyFaceDetectionListener implements Camera.FaceDetectionListener {@Overridepublic void onFaceDetection(Face[] faces, Camera camera) {if (faces.length > 0){Log.d("FaceDetection", "face detected: "+ faces.length +" Face 1 Location X: " + faces[0].rect.centerX() +"Y: " + faces[0].rect.centerY() );}}}第三步:想camera中添加监听;mCamera.setFaceDetectionListener(new MyFaceDetectionListener());第四步:开始识别public void startFaceDetection(){// Try starting Face DetectionCamera.Parameters params = mCamera.getParameters();// start face detection only *after* preview has startedif (params.getMaxNumDetectedFaces() > 0){// camera supports face detection, so can start it:mCamera.startFaceDetection();}}每次开始预览的时候都必须打开人脸识别,在surfaceCreated()和surfaceChanged中都要调用startFaceDetection()public void surfaceCreated(SurfaceHolder holder) {try {mCamera.setPreviewDisplay(holder);mCamera.startPreview();startFaceDetection(); // start face detection feature} catch (IOException e) {Log.d(TAG, "Error setting camera preview: " + e.getMessage());}}public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {if (mHolder.getSurface() == null){// preview surface does not existLog.d(TAG, "mHolder.getSurface() == null");return;}try {mCamera.stopPreview();} catch (Exception e){// ignore: tried to stop a non-existent previewLog.d(TAG, "Error stopping camera preview: " + e.getMessage());}try {mCamera.setPreviewDisplay(mHolder);mCamera.startPreview();startFaceDetection(); // re-start face detection feature} catch (Exception e){// ignore: tried to stop a non-existent previewLog.d(TAG, "Error starting camera preview: " + e.getMessage());}}注:不要相机界面Activity的onCreate()中调用人脸识别方法,这个时候的preview还不可用,要在starPreview()之后调用人脸识别。延时摄影:延时摄运行用户把几张图片合成一个几秒或者几分钟的视频剪辑。这个功能需要使用MediaRecorder对象来记录图像的延时序列。要用MediaRecorder对象来记录延时视频,要想录制普通视频一样,必须要先配置,例如把每秒采集的帧数设置到较小,并使用一个延时品质设置// Step 3: Set a CamcorderProfile (requires API Level 8 or higher)mMediaRecorder.setProfile(CamcorderProfile.get(CamcorderProfile.QUALITY_TIME_LAPSE_HIGH));...// Step 5.5: Set the video capture rate to a low numbermMediaRecorder.setCaptureRate(0.1); // capture a frame every 10 seconds
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: