博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换
阅读量:5249 次
发布时间:2019-06-14

本文共 17054 字,大约阅读时间需要 56 分钟。

如何调用本地图片,并调用系统拍摄的图像上一博文解释()的功能。

而本博文将通过实例实现自己定义Camera的功效。详细功能例如以下:

1.实现自己定义Camera拍照;

2.实现前后置摄像头的切换。

3.实现Camera拍照后图片缩小显示以及正常预览;

4.实现Camera拍照后图片保存;

在详细实现代码之前,我们先来了解一下Android api对实现自己定义Camera的介绍。

依据api的介绍,对于Camera应用能够简单总结下面几个步骤。

1.检查Camera是否存在。并在AndroidManifest.xml中赋予相关的权限

2.创建一个继承于SurfaceView并实现SurfaceHolder接口的Camera Preview类

3.在2的基础上新建一个Camera Preview布局文件

4.设置一个拍照的监听事件,比如单击button事件等;

5.实现拍照,并保存拍照后的图片到设备;

6.释放Camera,以方便其它应用能够使用。

以下将通过详细代码实现我们给出的三个功能。

一.相关的xml文件

1.AndroidManifest.xml相关配置以及相关权限,实现步骤一其中的权限配置

> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.example.camerasurfacedemo" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="11" android:targetSdkVersion="19" /> <uses-permission android:name="android.permission.CAMERA" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" /> <uses-feature android:name="android.hardware.camera" /> <application android:allowBackup="true" android:icon="@drawable/ic_launcher" android:label="@string/app_name" android:theme="@style/AppTheme" > <activity android:name="com.example.camerasurfacedemo.MainActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <activity android:name="com.example.camerasurfacedemo.CameraActivity" ></activity> <activity android:name="com.example.camerasurfacedemo.PreviewActivity" ></activity> </application> </manifest>

2.activity_main.xml主函数入口。进入自己定义Camera界面入口,实现拍照后图片缩小显示功能

"
3.activity_camera.xml自己定义Camera preview布局,实现步骤2,该界面实现前后置摄像头切换以及自己定义拍照等

4.activity_preview.xml实现拍照后图片放大预览

二.java代码实现

1.帮助类HelpUtil.java

package com.example.camerasurfacedemo;import java.io.FileInputStream;import java.io.FileNotFoundException;import java.io.IOException;import java.text.SimpleDateFormat;import java.util.Date;import android.annotation.SuppressLint;import android.content.ContentResolver;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Matrix;import android.net.Uri;public class HelpUtil {	/**	 * 依据图片路径获取本地图片的Bitmap	 * 	 * @param url	 * @return	 */	public static Bitmap getBitmapByUrl(String url) {		FileInputStream fis = null;		Bitmap bitmap = null;		try {			fis = new FileInputStream(url);			bitmap = BitmapFactory.decodeStream(fis);		} catch (FileNotFoundException e) {			// TODO Auto-generated catch block			e.printStackTrace();			bitmap = null;		} finally {			if (fis != null) {				try {					fis.close();				} catch (IOException e) {					// TODO Auto-generated catch block					e.printStackTrace();				}				fis = null;			}		}		return bitmap;	}	/**	 * bitmap旋转90度	 * 	 * @param bitmap	 * @return	 */	public static Bitmap createRotateBitmap(Bitmap bitmap) {		if (bitmap != null) {			Matrix m = new Matrix();			try {				m.setRotate(90, bitmap.getWidth() / 2, bitmap.getHeight() / 2);// 90就是我们须要选择的90度				Bitmap bmp2 = Bitmap.createBitmap(bitmap, 0, 0,						bitmap.getWidth(), bitmap.getHeight(), m, true);				bitmap.recycle();				bitmap = bmp2;			} catch (Exception ex) {				System.out.print("创建图片失败。" + ex);			}		}		return bitmap;	}		public static Bitmap getBitmapByUri(Uri uri,ContentResolver cr){		Bitmap bitmap = null;		try {			bitmap = BitmapFactory.decodeStream(cr					 .openInputStream(uri));		} catch (FileNotFoundException e) {			// TODO Auto-generated catch block			e.printStackTrace();			bitmap = null;		}		return bitmap;	}	/**	 * 获取格式化日期字符串	 * @param date	 * @return	 */	@SuppressLint("SimpleDateFormat")	public static String getDateFormatString(Date date) {		if (date == null)			date = new Date();		String formatStr = new String();		SimpleDateFormat matter = new SimpleDateFormat("yyyyMMdd_HHmmss");		formatStr = matter.format(date);		return formatStr;	}}
2.主函数类MainActivity.java

package com.example.camerasurfacedemo;import android.app.Activity;import android.content.Intent;import android.net.Uri;import android.os.Bundle;import android.text.TextUtils;import android.view.View;import android.view.View.OnClickListener;import android.widget.Button;import android.widget.ImageView;public class MainActivity extends Activity {	private Button goCameraBtn;	private ImageView showCameraIv;	private static final int CAMERA_CODE = 1;	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		setContentView(R.layout.activity_main);		goCameraBtn = (Button)this.findViewById(R.id.id_go_camera_btn);		goCameraBtn.setOnClickListener(new OnClickListener(){			@Override			public void onClick(View v) {				processGoCamera();			}					});				showCameraIv = (ImageView)this.findViewById(R.id.id_show_camera_iv);		showCameraIv.setOnClickListener(new OnClickListener(){			@Override			public void onClick(View v) {				processShowCamera(v);			}					});	}		/**	 * 处理进入camera事件	 */	private void processGoCamera(){		Intent intent = new Intent();		intent.setClass(this, CameraActivity.class);		startActivityForResult(intent,CAMERA_CODE);	}		/**	 * 处理图片跳转进入预览界面	 */	private void processShowCamera(View v){		Intent intent = new Intent();		intent.setClass(this, PreviewActivity.class);		/**		 * 将图片url传给PreviewActivity		 */		intent.putExtra("cameraUrl", v.getContentDescription().toString());		startActivity(intent);	}		@Override	public void onActivityResult(int requestCode,int resultCode,Intent data){		super.onActivityResult(requestCode, resultCode, data);				if(RESULT_OK == resultCode){			if(CAMERA_CODE == requestCode){				/**				 * 获取activity返回的url				 */				Uri uri = data.getData();				String url = uri.toString().substring(uri.toString().indexOf("///")+2);				if(url != null && !TextUtils.isEmpty(url)){					showCameraIv.setContentDescription(url);					showCameraIv.setImageBitmap(HelpUtil.getBitmapByUrl(url));				}			}		}			}}

注意:这里通过startActivityForResult(intent,CAMERA_CODE)跳转和 onActivityResult(int requestCode,int resultCode,Intent data)返回拍照后的图片路径信息

3.自己定义Camera preview类CameraActivity.java

package com.example.camerasurfacedemo;import java.io.File;import java.io.FileNotFoundException;import java.io.FileOutputStream;import java.io.IOException;import java.util.Date;import android.annotation.SuppressLint;import android.app.Activity;import android.content.Context;import android.content.Intent;import android.content.pm.PackageManager;import android.graphics.ImageFormat;import android.hardware.Camera;import android.hardware.Camera.CameraInfo;import android.hardware.Camera.Parameters;import android.hardware.Camera.PictureCallback;import android.net.Uri;import android.os.Bundle;import android.os.Environment;import android.util.Log;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.View;import android.view.View.OnClickListener;import android.view.Window;import android.widget.Button;public class CameraActivity extends Activity implements OnClickListener,		SurfaceHolder.Callback {	private static final String TAG = CameraActivity.class.getSimpleName();	private static final int MEDIA_TYPE_IMAGE = 1;	private Button switchCameraBtn, captureBtn;	private SurfaceView surfaceSv;	private SurfaceHolder mHolder;	private Camera mCamera;	// 0表示后置,1表示前置	private int cameraPosition = 1;	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		// 不显示标题		this.requestWindowFeature(Window.FEATURE_NO_TITLE);		setContentView(R.layout.activity_camera);		findById();		initData();	}	/**	 * 初始化view	 */	private void findById() {		switchCameraBtn = (Button) this.findViewById(R.id.id_switch_camera_btn);		captureBtn = (Button) this.findViewById(R.id.id_capture_btn);		surfaceSv = (SurfaceView) this.findViewById(R.id.id_area_sv);		switchCameraBtn.setOnClickListener(this);		captureBtn.setOnClickListener(this);	}	/**	 * 初始化相关data	 */	private void initData() {		// 获得句柄		mHolder = surfaceSv.getHolder();		// 加入回调		mHolder.addCallback(this);	}	@Override	public void onStart() {		super.onStart();		if (this.checkCameraHardware(this) && (mCamera == null)) {			// 打开camera			mCamera = getCamera();			if (mHolder != null) {				setStartPreview(mCamera,mHolder);			}		}	}	private Camera getCamera() {		Camera camera = null;		try {			camera = Camera.open();		} catch (Exception e) {			// Camera is not available (in use or does not exist)			camera = null;			Log.e(TAG, "Camera is not available (in use or does not exist)");		}		return camera;	}	@Override	public void onPause() {		super.onPause();		/**		 * 记得释放camera。方便其它应用调用		 */		releaseCamera();	}	@Override	public void onDestroy() {		super.onDestroy();	}	/**	 * 释放mCamera	 */	private void releaseCamera() {		if (mCamera != null) {			mCamera.setPreviewCallback(null);			mCamera.stopPreview();// 停掉原来摄像头的预览			mCamera.release();			mCamera = null;		}	}	@Override	public void onClick(View v) {		switch (v.getId()) {		case R.id.id_switch_camera_btn:			// 切换前后摄像头			int cameraCount = 0;			CameraInfo cameraInfo = new CameraInfo();			cameraCount = Camera.getNumberOfCameras();// 得到摄像头的个数			for (int i = 0; i < cameraCount; i++) {				Camera.getCameraInfo(i, cameraInfo);// 得到每个摄像头的信息				if (cameraPosition == 1) {					// 如今是后置,变更为前置					if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_FRONT) {						/**						 * 记得释放camera。方便其它应用调用						 */						releaseCamera();						// 打开当前选中的摄像头						mCamera = Camera.open(i);						// 通过surfaceview显示取景画面						setStartPreview(mCamera,mHolder);						cameraPosition = 0;						break;					}				} else {					// 如今是前置。 变更为后置					if (cameraInfo.facing == Camera.CameraInfo.CAMERA_FACING_BACK) {						/**						 * 记得释放camera,方便其它应用调用						 */						releaseCamera();						mCamera = Camera.open(i);						setStartPreview(mCamera,mHolder);						cameraPosition = 1;						break;					}				}			}			break;		case R.id.id_capture_btn:			// 拍照,设置相关參数			Camera.Parameters params = mCamera.getParameters();			params.setPictureFormat(ImageFormat.JPEG);			params.setPreviewSize(800, 400);			// 自己主动对焦			params.setFocusMode(Parameters.FOCUS_MODE_AUTO);			mCamera.setParameters(params);			mCamera.takePicture(null, null, picture);			break;		}	}	@Override	public void surfaceCreated(SurfaceHolder holder) {		setStartPreview(mCamera,mHolder);	}	@Override	public void surfaceChanged(SurfaceHolder holder, int format, int width,			int height) {		// 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		setStartPreview(mCamera,mHolder);	}	@Override	public void surfaceDestroyed(SurfaceHolder holder) {		// 当surfaceview关闭时,关闭预览并释放资源		/**		 * 记得释放camera,方便其它应用调用		 */		releaseCamera();		holder = null;		surfaceSv = null;	}	/**	 * 创建png图片回调数据对象	 */	PictureCallback picture = 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: ");				return;			}			try {				FileOutputStream fos = new FileOutputStream(pictureFile);				fos.write(data);				fos.close();				returnResult(pictureFile);			} catch (FileNotFoundException e) {				Log.d(TAG, "File not found: " + e.getMessage());			} catch (IOException e) {				Log.d(TAG, "Error accessing file: " + e.getMessage());			}		}	};	/**	 * 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 = 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		String timeStamp = HelpUtil.getDateFormatString(new Date());		File mediaFile;		if (type == MEDIA_TYPE_IMAGE) {			mediaFile = new File(mediaStorageDir.getPath() + File.separator					+ "IMG_" + timeStamp + ".png");		} else {			return null;		}		return mediaFile;	}	/** 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;		}	}	/**	 * activity返回式返回拍照图片路径	 * @param mediaFile	 */	private void returnResult(File mediaFile) {		Intent intent = new Intent();		intent.setData(Uri.fromFile(mediaFile));		this.setResult(RESULT_OK, intent);		this.finish();	}		/**	 * 设置camera显示取景画面,并预览	 * @param camera	 */	private void setStartPreview(Camera camera,SurfaceHolder holder){		try {			camera.setPreviewDisplay(holder);			camera.startPreview();		} catch (IOException e) {			Log.d(TAG, "Error starting camera preview: " + e.getMessage());		}	}}
注意:

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;		}	}
2.创建png格式的回调接口

/**	 * 创建png图片回调数据对象	 */	PictureCallback picture = 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: ");				return;			}			try {				FileOutputStream fos = new FileOutputStream(pictureFile);				fos.write(data);				fos.close();				returnResult(pictureFile);			} catch (FileNotFoundException e) {				Log.d(TAG, "File not found: " + e.getMessage());			} catch (IOException e) {				Log.d(TAG, "Error accessing file: " + e.getMessage());			}		}	};
3.生成图片文件并保存

/**	 * 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 = 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		String timeStamp = HelpUtil.getDateFormatString(new Date());		File mediaFile;		if (type == MEDIA_TYPE_IMAGE) {			mediaFile = new File(mediaStorageDir.getPath() + File.separator					+ "IMG_" + timeStamp + ".png");		} else {			return null;		}		return mediaFile;	}
4.Camera一定要release

/**	 * 释放mCamera	 */	private void releaseCamera() {		if (mCamera != null) {			mCamera.setPreviewCallback(null);			mCamera.stopPreview();// 停掉原来摄像头的预览			mCamera.release();			mCamera = null;		}	}
5.Activity结果返回

/**	 * activity返回式返回拍照图片路径	 * @param mediaFile	 */	private void returnResult(File mediaFile) {		Intent intent = new Intent();		intent.setData(Uri.fromFile(mediaFile));		this.setResult(RESULT_OK, intent);		this.finish();	}
4.图片正常预览PreviewActivity.java

package com.example.camerasurfacedemo;import android.app.Activity;import android.content.Intent;import android.os.Bundle;import android.text.TextUtils;import android.view.Window;import android.widget.ImageView;import android.widget.Toast;public class PreviewActivity extends Activity {	private ImageView previewCameraIv;	@Override	protected void onCreate(Bundle savedInstanceState) {		super.onCreate(savedInstanceState);		this.requestWindowFeature(Window.FEATURE_NO_TITLE);		setContentView(R.layout.activity_preview);				previewCameraIv = (ImageView)this.findViewById(R.id.id_preview_camera_iv);				Intent intent = this.getIntent();		String cameraUrl = intent.getStringExtra("cameraUrl").toString();		if(cameraUrl != null && !TextUtils.isEmpty(cameraUrl)){			previewCameraIv.setImageBitmap(HelpUtil.getBitmapByUrl(cameraUrl));		}else{			Toast.makeText(this, "图片路径错误", Toast.LENGTH_SHORT).show();		}	}	}
以上就是本博文的全部内容。谢谢品读。

源代码路径:

版权声明:本文博主原创文章,博客,未经同意不得转载。

转载于:https://www.cnblogs.com/hrhguanli/p/4908283.html

你可能感兴趣的文章
ZipArchive框架的文件压缩和解压
查看>>
兼容IE8浏览器移除class样式的方法
查看>>
HTTP Content-type 对照表
查看>>
软件测试HW01------曾几何时邂逅的小问题
查看>>
Perl语言入门笔记 第七章 漫游正则表达式王国
查看>>
R12 How to Match a Credit Memo to an Invoice for Correction?
查看>>
WebKitErrorDomain error 101
查看>>
正则表达式(一)引子、历史
查看>>
方格取数
查看>>
【基于WPF+OneNote+Oracle的中文图片识别系统阶段总结】之篇四:关于OneNote入库处理以及审核...
查看>>
Nginx配置文件nginx.conf中文详解
查看>>
iOS 多线程编程之Grand Central Dispatch(GCD)
查看>>
AndroidUI的组成部分GridView
查看>>
使用axis公布weblogic(一个)
查看>>
使用nodeitk进行对象识别
查看>>
POJ1719- Shooting Contest(二分图最大匹配)
查看>>
Mediator - 中介者模式
查看>>
epoll使用具体解释(精髓)
查看>>
H.265/HEVC Codec 编解码 (MP4 和 TS)
查看>>
学习开淘宝网店
查看>>