Android 调用系统中的相机应用

来源:互联网 发布:javascript格式化xml 编辑:程序博客网 时间:2024/04/29 22:04

通过Intent直接调用系统相机

  直接调用系统的相机应用,只需要在Intent对象中传入相应的参数即可,总体来说需要以下三步

  1. Compose a Camera Intent

  MediaStore.ACTION_IMAGE_CAPTURE 拍照;

  MediaStore.ACTION_VIDEO_CAPTURE录像。


  2. Start the Camera Intent

  使用startActivityForResult()方法,并传入上面的intent对象。

  之后,系统自带的相机应用就会启动,用户就可以用它来拍照或者录像。

 

  3. Receive the Intent Result

   用onActivityResult()接收传回的图像,当用户拍完照片或者录像,或者取消后,系统都会调用这个函数。

 

关于接收图像

  如果不设置接收图像的部分,拍照完毕后将会返回到原来的activity,相片会自动存储在拍照应用的默认存储位置。

 

  为了接收图像,需要做以下几个工作:

  1.指定图像的存储位置,一般图像都是存储在外部存储设备,即SD卡上。

  你可以考虑的标准的位置有以下两个:

  Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES)

  这个方法返回图像和视频的标准共享位置,别的应用也可以访问,如果你的应用被卸载了,这个路径下的文件是会保留的

  为了区分,你可以在这个路径下为你的应用创建一个子文件夹。

  Context.getExternalFilesDir(Environment.DIRECTORY_PICTURES)

  这个方法返回的路径是和你的应用相关的一个存储图像和视频的方法。

  如果应用被卸载,这个路径下的东西全都会被删除。

  这个路径没有什么安全性限制,别的应用也可以自由访问里面的文件。

 

  2.为了接收intent的结果,需要覆写activity中的 onActivityResult() 方法。

  前面说过,可以不设置相机返回的图像结果的操作,此时在startActivityForResult()中不需要给intent传入额外的数据,这样在onActivityResult()回调时,返回的Intent data不为null,照片存在系统默认的图片存储路径下。

  但是如果想得到这个图像,你必须制定要存储的目标File,并且把它作为URI传给启动的intent,使用MediaStore.EXTRA_OUTPUT作为关键字。

  这样的话,拍摄出来的照片将会存在这个特殊指定的地方,此时没有thumbnail会被返回给activity的回调函数,所以接收到的Intent data为null

 

程序实例

  附上程序代码,其中视频存储的返回结果部分没有写代码,视频拍摄后会存入系统应用的默认位置。

在原来的基础上添加静默拍照。


//系统自带相机应用测试package com.kelly.systemcameraandvedio;import java.io.File;import java.text.SimpleDateFormat;import java.util.Date;import android.app.Activity;import android.content.Intent;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.hardware.Camera;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.provider.MediaStore;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ImageView;import android.widget.RelativeLayout;import android.widget.Toast;public class MainActivity extends Activity {private static final String LOG_TAG = "HelloCamera";private static final int CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE = 100;private static final int CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE = 200;public static final int MEDIA_TYPE_IMAGE = 1;public static final int MEDIA_TYPE_VIDEO = 2;private Button takePicBtn = null;private Button takeVideoBtn = null;private Button takePicSoundless = null;private ImageView imageView = null;private Uri fileUri;@Overridepublic void onCreate(Bundle savedInstanceState) {Log.i(LOG_TAG, "onCreate");super.onCreate(savedInstanceState);setContentView(R.layout.activity_main);takePicBtn = (Button) findViewById(R.id.but_takePic);takePicBtn.setOnClickListener(takePiClickListener);takeVideoBtn = (Button) findViewById(R.id.but_takeVedio);takeVideoBtn.setOnClickListener(takeVideoClickListener);takePicSoundless = (Button) findViewById(R.id.but_takePicBackground);takePicSoundless.setOnClickListener(new takePicSoundlessClickListener());imageView = (ImageView) findViewById(R.id.imageview_leo);}/** * 静默拍照 *  * @author Administrator *  */private class takePicSoundlessClickListener implements OnClickListener {public void onClick(View v) {Intent intent = new Intent(MainActivity.this, CameraActivity.class);startActivity(intent);}}private final OnClickListener takePiClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.i(LOG_TAG, "Take Picture Button Click");// 利用系统自带的相机应用:拍照Intent intent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE);// create a file to save the imagefileUri = getOutputMediaFileUri(MEDIA_TYPE_IMAGE);// 此处这句intent的值设置关系到后面的onActivityResult中会进入那个分支,即关系到data是否为null,如果此处指定,则后来的data为null// set the image file nameintent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);// // set the video image quality to high// intent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);startActivityForResult(intent, CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE);}};private final OnClickListener takeVideoClickListener = new View.OnClickListener() {@Overridepublic void onClick(View v) {Log.i(LOG_TAG, "Take Video Button Click");// 摄像Intent intent = new Intent(MediaStore.ACTION_VIDEO_CAPTURE);// create a file to save the videofileUri = getOutputMediaFileUri(MEDIA_TYPE_VIDEO);// set the image file nameintent.putExtra(MediaStore.EXTRA_OUTPUT, fileUri);// set the video image quality to highintent.putExtra(MediaStore.EXTRA_VIDEO_QUALITY, 1);startActivityForResult(intent, CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE);}};/** Create a file Uri for saving an image or video */private static Uri getOutputMediaFileUri(int type) {return Uri.fromFile(getOutputMediaFile(type));}/** Create a File for saving an image or video */private static File getOutputMediaFile(int type) {// To be safe, you should check that the SDCard is mounted// using Environment.getExternalStorageState() before doing this.File mediaStorageDir = null;try {// This location works best if you want the created images to be// shared// between applications and persist after your app has been// uninstalled.mediaStorageDir = new File(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES),"MyCameraApp");Log.i(LOG_TAG, "Successfully created mediaStorageDir: "+ mediaStorageDir);} catch (Exception e) {e.printStackTrace();Log.i(LOG_TAG, "Error in Creating mediaStorageDir: "+ mediaStorageDir);}// Create the storage directory if it does not existif (!mediaStorageDir.exists()) {if (!mediaStorageDir.mkdirs()) {// 在SD卡上创建文件夹需要权限:// <uses-permission// android:name="android.permission.WRITE_EXTERNAL_STORAGE" />Log.i(LOG_TAG,"failed to create directory, check if you have the WRITE_EXTERNAL_STORAGE permission");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;}@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {super.onActivityResult(requestCode, resultCode, data);Log.i(LOG_TAG, "onActivityResult: requestCode: " + requestCode+ ", resultCode: " + requestCode + ", data: " + data);// 如果是拍照if (CAPTURE_IMAGE_ACTIVITY_REQUEST_CODE == requestCode) {Log.i(LOG_TAG, "CAPTURE_IMAGE");if (RESULT_OK == resultCode) {Log.i(LOG_TAG, "RESULT_OK");// Check if the result includes a thumbnail Bitmapif (data != null) {// 没有指定特定存储路径的时候Log.i(LOG_TAG,"data is NOT null, file on default position.");// 指定了存储路径的时候(intent.putExtra(MediaStore.EXTRA_OUTPUT,fileUri);)// Image captured and saved to fileUri specified in the// IntentToast.makeText(this, "Image saved to:\n" + data.getData(),Toast.LENGTH_LONG).show();if (data.hasExtra("data")) {Bitmap thumbnail = data.getParcelableExtra("data");imageView.setImageBitmap(thumbnail);}} else {Log.i(LOG_TAG,"data IS null, file saved on target position.");// If there is no thumbnail image data, the image// will have been stored in the target output URI.// Resize the full image to fit in out image view.int width = imageView.getWidth();int height = imageView.getHeight();BitmapFactory.Options factoryOptions = new BitmapFactory.Options();factoryOptions.inJustDecodeBounds = true;BitmapFactory.decodeFile(fileUri.getPath(), factoryOptions);int imageWidth = factoryOptions.outWidth;int imageHeight = factoryOptions.outHeight;// Determine how much to scale down the imageint scaleFactor = Math.min(imageWidth / width, imageHeight/ height);// Decode the image file into a Bitmap sized to fill the// ViewfactoryOptions.inJustDecodeBounds = false;factoryOptions.inSampleSize = scaleFactor;factoryOptions.inPurgeable = true;Bitmap bitmap = BitmapFactory.decodeFile(fileUri.getPath(),factoryOptions);imageView.setImageBitmap(bitmap);}} else if (resultCode == RESULT_CANCELED) {// User cancelled the image capture} else {// Image capture failed, advise user}}// 如果是录像if (requestCode == CAPTURE_VIDEO_ACTIVITY_REQUEST_CODE) {Log.i(LOG_TAG, "CAPTURE_VIDEO");if (resultCode == RESULT_OK) {} else if (resultCode == RESULT_CANCELED) {// User cancelled the video capture} else {// Video capture failed, advise user}}}}

静默拍照 CameraActivity

package com.kelly.systemcameraandvedio;/** * 用来拍照的Activity *  */import java.io.File;import java.io.FileOutputStream;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import android.annotation.SuppressLint;import android.annotation.TargetApi;import android.app.Activity;import android.content.Context;import android.content.pm.PackageManager;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.hardware.Camera;import android.hardware.Camera.AutoFocusCallback;import android.hardware.Camera.PictureCallback;import android.os.Build;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.Window;import android.view.WindowManager;import android.widget.Toast;@TargetApi(Build.VERSION_CODES.GINGERBREAD)@SuppressLint("NewApi")public class CameraActivity extends Activity {private SurfaceView mySurfaceView;private SurfaceHolder myHolder;private Camera myCamera;private static final String TAG = "CameraActivity";@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);// 无titlerequestWindowFeature(Window.FEATURE_NO_TITLE);// 全屏getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,WindowManager.LayoutParams.FLAG_FULLSCREEN);// 设置布局setContentView(R.layout.activity_camera);Log.i(TAG, "oncreate");// 初始化surfaceinitSurface();// 这里得开线程进行拍照,因为Activity还未完全显示的时候,是无法进行拍照的,SurfaceView必须先显示new Thread(new Runnable() {@Overridepublic void run() {// 初始化camera并对焦拍照initCamera();}}).start();}// 初始化surface@SuppressWarnings("deprecation")private void initSurface() {// 初始化surfaceviewmySurfaceView = (SurfaceView) findViewById(R.id.camera_surfaceview);// 初始化surfaceholdermyHolder = mySurfaceView.getHolder();}// 初始化摄像头private void initCamera() {// 如果存在摄像头if (checkCameraHardware(getApplicationContext())) {// 获取摄像头(首选前置,无前置选后置)if (openFacingFrontCamera()) {Log.i(TAG, "openCameraSuccess");// 进行对焦autoFocus();} else {Log.i(TAG, "openCameraFailed");}}}// 对焦并拍照private void autoFocus() {try {// 因为开启摄像头需要时间,这里让线程睡两秒Thread.sleep(2000);} catch (InterruptedException e) {e.printStackTrace();}// 自动对焦myCamera.autoFocus(myAutoFocus);// 对焦后拍照myCamera.takePicture(null, null, myPicCallback);}// 判断是否存在摄像头private boolean checkCameraHardware(Context context) {if (context.getPackageManager().hasSystemFeature(PackageManager.FEATURE_CAMERA)) {// 设备存在摄像头return true;} else {// 设备不存在摄像头return false;}}// 得到后置摄像头private boolean openFacingFrontCamera() {// 尝试开启前置摄像头Camera.CameraInfo cameraInfo = new Camera.CameraInfo();for (int camIdx = 0, cameraCount = Camera.getNumberOfCameras(); camIdx < cameraCount; camIdx++) {Camera.getCameraInfo(camIdx, cameraInfo);if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {try {Log.i(TAG, "tryToOpenCamera");myCamera = Camera.open(camIdx);} catch (RuntimeException e) {e.printStackTrace();return false;}}}// 如果开启前置失败(无前置)则开启后置if (myCamera == null) {for (int camIdx = 0, cameraCount = Camera.getNumberOfCameras(); camIdx < cameraCount; camIdx++) {Camera.getCameraInfo(camIdx, cameraInfo);if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {try {myCamera = Camera.open(camIdx);} catch (RuntimeException e) {return false;}}}}try {// 这里的myCamera为已经初始化的Camera对象myCamera.setPreviewDisplay(myHolder);} catch (IOException e) {e.printStackTrace();myCamera.stopPreview();myCamera.release();myCamera = null;}myCamera.startPreview();return true;}// 自动对焦回调函数(空实现)private AutoFocusCallback myAutoFocus = new AutoFocusCallback() {@Overridepublic void onAutoFocus(boolean success, Camera camera) {}};// 拍照成功回调函数private PictureCallback myPicCallback = new PictureCallback() {@Overridepublic void onPictureTaken(byte[] data, Camera camera) {// 完成拍照后关闭ActivityCameraActivity.this.finish();// 将得到的照片进行270°旋转,使其竖直Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);Matrix matrix = new Matrix();matrix.preRotate(270);bitmap = Bitmap.createBitmap(bitmap, 0, 0, bitmap.getWidth(),bitmap.getHeight(), matrix, true);String timeStamp = new SimpleDateFormat("yyyyMMdd_HHmmss").format(new Date());// 创建并保存图片文件File pictureFile = new File(getDir(), "IMG_" + timeStamp + ".jpg");try {FileOutputStream fos = new FileOutputStream(pictureFile);bitmap.compress(Bitmap.CompressFormat.PNG, 100, fos);fos.close();} catch (Exception error) {Toast.makeText(CameraActivity.this, "拍照失败", Toast.LENGTH_SHORT).show();;Log.i(TAG, "保存照片失败" + error.toString());error.printStackTrace();myCamera.stopPreview();myCamera.release();myCamera = null;}Log.i(TAG, "获取照片成功");Toast.makeText(CameraActivity.this, "获取照片成功", Toast.LENGTH_SHORT).show();;myCamera.stopPreview();myCamera.release();myCamera = null;}};// 获取文件夹private File getDir() {// 得到SD卡根目录File dir = Environment.getExternalStorageDirectory();if (dir.exists()) {return dir;} else {dir.mkdirs();return dir;}}}


参考:1.http://www.cnblogs.com/mengdd/archive/2013/03/31/2991932.html

  2.http://download.csdn.net/detail/a740169405/6344845

代码下载:http://download.csdn.net/detail/leokelly001/8173715



0 0