Android 举例说明自己的定义Camera图片和预览,以及前后摄像头切换

如何调用本地图片,并调用系统拍摄的图像上一博文解释(http://blog.****.net/a123demi/article/details/40003695)的功能。

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

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

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

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

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

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

Android 举例说明自己的定义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相关配置以及相关权限,实现步骤一其中的权限配置

<?xml version="1.0" encoding="utf-8"?

>
<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界面入口,实现拍照后图片缩小显示功能

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center_horizontal"
android:orientation="vertical" >
" <Button
android:id="@+id/id_go_camera_btn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="进入拍照界面" /> <ImageView
android:id="@+id/id_show_camera_iv"
android:layout_width="150dp"
android:layout_height="200dp"
android:gravity="center" /> <TextView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:gravity="center"
android:text="拍照图片显示区域"
android:textColor="#FF0000"
android:textSize="20sp" /> </LinearLayout>

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

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
>
<LinearLayout
android:id="@+id/id_process_btns_ll"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="horizontal"
android:layout_alignParentTop="true"
>
<Button
android:id="@+id/id_switch_camera_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="切换前后摄像头"
/>
<Button
android:id="@+id/id_capture_btn"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:gravity="center"
android:text="拍照"
/>
</LinearLayout>
<SurfaceView
android:id="@+id/id_area_sv"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_below="@id/id_process_btns_ll"
android:text="拍照区域" /> </RelativeLayout>

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

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#000000"
android:orientation="vertical" > <TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:gravity="center"
android:text="拍照图片预览"
android:textColor="#FF0000"
android:textSize="20sp"
/> <ImageView
android:id="@+id/id_preview_camera_iv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:gravity="center" /> </LinearLayout>

二.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();
}
} }

以上就是本博文的全部内容。谢谢品读。

源代码路径:http://download.****.net/detail/a123demi/8029265

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

上一篇:初学jQuery之jQuery选择器


下一篇:WinForm给控件加入hint文字