调用摄像头功能的方法详解

来源:互联网 发布:道亨软件多少钱 编辑:程序博客网 时间:2024/06/08 11:36

第一步必须加入调用摄像头硬件的权限,拍完照后我们要将图片保存在SD卡中,必须加入SD卡读写权限,所以第一步,我们应该在Android清单文件中加入以下代码

摄像头权限:

?
1
<uses-permissionandroid:name="android.permission.CAMERA"/>

SD卡读写权限:

?
1
2
<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

第二步,要将摄像头捕获的图像实时地显示在手机上

我们是用SurfaceView这个视图组件来实现的,因此在main.xml中加入下列代码

?
1
2
3
4
5
<SurfaceView
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:id="@+id/surfaceview"
/>

第三步,设置窗口的显示方式

首先获得当前窗口

?
1
Window window = getWindow();//得到窗口

接着设置没有标题

?
1
requestWindowFeature(Window.FEATURE_NO_TITLE);//没有标题

接着设置全屏

复制代码 代码如下:
window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);//设置全屏

当然,我们在拍照过程中,屏幕必须一致处于高亮状态,因此接着加入下面代码

复制代码 代码如下:
window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//设置高亮

至此,我们将窗口的显示方式规定死了,然后才能设置窗口上显示的组件(顺序非常重要)

?
1
setContentView(R.layout.main);

第四步,设置SurficeView显示控件的属性

找到surficeView

?
1
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);

设置它的像素为800x600

?
1
2
3
surfaceView.getHolder().setFixedSize(800,480);
//下面设置surfaceView不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

第五步,就是为surficeView加入回调方法(callBack)

?
1
surfaceView.getHolder().addCallback(newSurfaceCallback());

上面的回调类是我们自己定义的,代码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
private class SurfaceCallback implementsSurfaceHolder.Callback{
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();//打开硬件摄像头,这里导包得时候一定要注意是android.hardware.Camera
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//得到窗口管理器
Display display = wm.getDefaultDisplay();//得到当前屏幕
Camera.Parameters parameters = camera.getParameters();//得到摄像头的参数
parameters.setPreviewSize(display.getWidth(), display.getHeight());//设置预览照片的大小
parameters.setPreviewFrameRate(3);//设置每秒3帧
parameters.setPictureFormat(PixelFormat.JPEG);//设置照片的格式
parameters.setJpegQuality(85);//设置照片的质量
parameters.setPictureSize(display.getHeight(), display.getWidth());//设置照片的大小,默认是和 屏幕一样大
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceView.getHolder());//通过SurfaceView显示取景画面
camera.startPreview();//开始预览
isPreview = true;//设置是否预览参数为真
} catch(IOException e) {
Log.e(TAG, e.toString());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, intwidth,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera!=null){
if(isPreview){//如果正在预览
camera.stopPreview();
camera.release();
}
}
}
}

第六步,我们必须对按键事件进行监听,如是拍照还是聚焦,代码如下

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
public boolean onKeyDown(intkeyCode, KeyEvent event) {//处理按键事件
if(camera!=null&&event.getRepeatCount()==0)//代表只按了一下
{
switch(keyCode){
case KeyEvent.KEYCODE_BACK://如果是搜索键
camera.autoFocus(null);//自动对焦
break;
caseKeyEvent.KEYCODE_DPAD_CENTER://如果是中间键
camera.takePicture(null,null, newTakePictureCallback());//将拍到的照片给第三个对象中,这里的TakePictureCallback()是自己定义的,在下面的代码中
break;
}
}
return true;//阻止事件往下传递,否则按搜索键会变成系统默认的
}
?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
private final class TakePictureCallbackimplements PictureCallback{
public void onPictureTaken(byte[] data, Camera camera) {
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data,0, data.length);
File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");
FileOutputStream outputStream =new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG,100, outputStream);
outputStream.close();
camera.stopPreview();
camera.startPreview();//处理完数据之后可以预览
} catch(Exception e) {
Log.e(TAG, e.toString());
}
}
}

注意,代码中有两个回调类,一个是SurfaceCallback(),另外一个是TakePictureCallback(),初学者可能一时难以理解,通俗地讲,前者是用来监视surficeView这个暂时存放图片数据的显示控件的,根据它的显示情况调用不同的方法,包括surfaceCreated(),surfaceChanged(),surfaceDestroyed(),也就不难理解为什么会有这三个回调方法了(注意,在surfaceDestroyed()方法中必须释放摄像头,详细代码参见上方)。TakePictureCallback()是为了监视是否拍照而设计的接口,期中也仅有一个方法,camera将拍照得到的数据传入方法,我们便可以对拍照得到的数据进行进一步处理了。

至此,简单的拍照功能介绍完毕!

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
package cn.camera.rxm;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
import org.apache.commons.logging.Log;
import android.text.format.DateFormat;
import android.util.*;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
//import android.widget.Toast;
public class MycamActivity extendsActivity {
privatePreview mPreview;
privateCamera mCamera;
Bitmap CameraBitmap;
SurfaceHolder mHolder;
privatestatic final int OPTION_SNAPSHOT = 0;
privatestatic final int OPTION_STOPCAMERA = 1;
privateView viewStart;
@Override
publicvoid onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater flater =this.getLayoutInflater();
viewStart = flater.inflate(R.layout.main,null);
setContentView(viewStart);
Button btn1 = (Button)findViewById(R.id.button1);
btn1.setOnClickListener(
newOnClickListener(){
publicvoid onClick(View v){
mPreview =new Preview(getBaseContext());
setContentView(mPreview);
};
}
);
}
publicboolean onCreateOptionsMenu(Menu menu){
//
menu.add(0, OPTION_SNAPSHOT,0, R.string.take);
//
menu.add(0, OPTION_STOPCAMERA,1, R.string.back);
//
return true;//super.onCreateOptionsMenu(menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
//
int itemId = item.getItemId();
//
switch(itemId){
case OPTION_SNAPSHOT:
//拍摄照片
mCamera.takePicture(null,null, jpegCallback);
try {
Thread.sleep(4000);
} catch(InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
break;
case OPTION_STOPCAMERA:
mPreview = null;
setContentView(viewStart);
break;
}
return true;
}
privatePictureCallback jpegCallback = newPictureCallback(){
//
public void onPictureTaken(byte[] data, Camera camera) {
try {
String name = new DateFormat().format("yyyyMMdd_hhmmss",
Calendar.getInstance(Locale.CHINA)) +".jpg";
FileOutputStream fileout =new FileOutputStream("/mnt/sdcard/sdcard/DCIM/"+ name);
System.out.println(name);
fileout.write(data,0,data.length);
fileout.flush();
fileout.close();
} catch(IOException e) {
// TODO: handle exception
System.out.println(e);
}
}
};
classPreview extendsSurfaceView implementsSurfaceHolder.Callback
{
Preview(Context context)
{
super(context);
mHolder=getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
publicvoid surfaceCreated(SurfaceHolder holder)
{
mCamera=Camera.open();
try
{
mCamera.setPreviewDisplay(holder);
}
catch(IOException exception)
{
mCamera.release();
mCamera=null;
}
}
publicvoid surfaceDestroyed(SurfaceHolder holder)
{
mCamera.stopPreview();
mCamera.release();
}
@Override
publicvoid surfaceChanged(SurfaceHolder holder,int format, int w, inth) {
// TODO Auto-generated method stub
Camera.Parameters parameters=mCamera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setPreviewSize(1024,1024);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
}
}
原创粉丝点击