1. 使用 SurfaceView 控件来显示摄像头捕捉到的画面

<SurfaceViewandroid:layout_width="fill_parent"android:layout_height="240dip"android:id="@+id/surfaceView" />

2. 具体细节

/*获取 SurfaceView控件 */

SurfaceViewsurfaceView = (SurfaceView)this.findViewById(R.id.surfaceView);

/*设置分辨率 */

surfaceView.getHolder().setFixedSize(176,144);

/*下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前*/

surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

/*打开摄像头,注意这里是android.hardware.Camera */

Cameracamera = Camera.open();

/* Camera 设置摄像参数 */

Camera.Parametersparameters = camera.getParameters();

/*设置预览照片的大小,此处设置为全屏 */

WindowManagerwm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 获取当前屏幕管理器对象

Displaydisplay = wm.getDefaultDisplay(); // 获取屏幕信息的描述类

parameters.setPreviewSize(display.getWidth(),display.getHeight()); // 设置

/*每秒从摄像头捕获5帧画面, */

parameters.setPreviewFrameRate(5);

/*设置照片的输出格式:jpg*/

parameters.setPictureFormat(PixelFormat.JPEG);

/*照片质量 */

parameters.set("jpeg-quality",85);

/*设置照片的大小:此处照片大小等于屏幕大小 */

parameters.setPictureSize(display.getWidth(),display.getHeight());

/*将参数对象赋予到camera 对象上 */

camera.setParameters(parameters);

/*设置用SurfaceView 作为承载镜头取景画面的显示*/

camera.setPreviewDisplay(surfaceView.getHolder());

/*开始预览 */

camera.startPreview();

/*自动对焦 */

camera.autoFocus(null);

/*拍照片 */

camera.takePicture(null,null, null, jpegCallback);

/*停止预览 */

camera.stopPreview();

/*释放摄像头 */

camera.release();

3. 添加使用摄像头的权限

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

4. 测试: 目前模拟器不支持拍照环境的模拟,必须使用真实手机测试。

5. 代码清单

**string values : strings.xml


<?xml version="1.0" encoding="utf-8"?>
<resources>
<string name="app_name">手机拍照程序</string>
</resources>

**AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="wjh.android.takepicture"
android:versionCode="1"
android:versionName="1.0">
<application android:icon="@drawable/icon" android:label="@string/app_name">
<!-- android:screenOrientation="landscape" 表示横向界面 -->
<activity android:name=".MainActicity" android:label="@string/app_name" android:screenOrientation="landscape">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="8" />
<!-- 在SDCard中创建与删除文件权限 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
<!-- 往SDCard写入数据权限 -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<!-- 申请使用摄像头的权限 -->
<uses-permission android:name="android.permission.CAMERA"/>
</manifest>


**main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<SurfaceView android:id="@+id/surfaceView"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
/>

</LinearLayout>

**MainActicity

public class MainActicity extends Activity {
private Camera camera;
private boolean preview = false ;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);

/*
*设置窗口属性:一定要在 setContentView(R.layout.main) 之前
*/
// 窗口标题
requestWindowFeature(Window.FEATURE_NO_TITLE);
// 全屏
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);

setContentView(R.layout.main);

SurfaceView surfaceView = (SurfaceView) findViewById(R.id.surfaceView);
surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.getHolder().setFixedSize(176, 164);

surfaceView.getHolder().addCallback(new SurfaceViewCallback());
}

private final class SurfaceViewCallback implements Callback {
/**
* surfaceView 被创建成功后调用此方法
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
/*
* 在SurfaceView创建好之后 打开摄像头
* 注意是 android.hardware.Camera
*/
camera = Camera.open();
Camera.Parameters parameters = camera.getParameters();
/* 设置预览照片的大小,此处设置为全屏 */
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 获取当前屏幕管理器对象
Display display = wm.getDefaultDisplay(); // 获取屏幕信息的描述类
parameters.setPreviewSize(display.getWidth(), display.getHeight()); // 设置

/* 每秒从摄像头捕获5帧画面, */
parameters.setPreviewFrameRate(5);
/* 设置照片的输出格式:jpg */
parameters.setPictureFormat(PixelFormat.JPEG);
/* 照片质量 */
parameters.set("jpeg-quality", 85);
/* 设置照片的大小:此处照片大小等于屏幕大小 */
parameters.setPictureSize(display.getWidth(), display.getHeight());
/* 将参数对象赋予到 camera 对象上 */
camera.setParameters(parameters);
preview = true;
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
/**
* SurfaceView 被销毁时释放掉 摄像头
*/
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera != null) {
/* 若摄像头正在工作,先停止它 */
if(preview) {
camera.stopPreview();
preview = false;
}
camera.release();
}
}

}


/**
* 手机键盘按键事件
* 返回 true, 将阻止事件继续传递,例如搜索键,他默认会触发和打开系统的搜索引擎。返回true后,将不会触发。
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
/*
* event.getRepeatCount() 为重复按键的次数,例如,快速地对某个键连续按了两次,则此值为一,表示重复了一次。往上可以累推。
* 按键只被按了一次,则此值为 0。
* 这有点类似于鼠标的 "单击" 和 "双击"。
*/
if(camera != null && event.getRepeatCount() == 0 ) {
switch (keyCode) {
case KeyEvent.KEYCODE_SEARCH: // 搜索键
/* 按下搜索键自动对焦 , 如果要关注它的事件,
* 可以实现 AutoFocusCallback 接口,并实例化其对象传入 */
camera.autoFocus(null);
break;
case KeyEvent.KEYCODE_CAMERA: // 拍照键
case KeyEvent.KEYCODE_DPAD_CENTER: // 中间确认键
/*
* @param shutter : 照片被捕获之后的回调对象
* @param raw : 此回调对象可以生产为压缩的图片数据
* @param jpeg : 此回调对象可以产生压缩后的图片数据,其onPictureTaken将被调用
*/
camera.takePicture(null, null, new TakePictureCallback());

/* 拍完照后回到预览状态,继续取景 -- 错误的方式 */
// camera.startPreview();必须写在 onPictureTaken 方法内部,因为 takePicture 内部是另开了一条线程异步的完成保存照片等操作。
// 虽然 takePicture 方法完成了,但是并不代表其内部的工作全部完成,也不代表摄像头以及从上一次“拍照”任务中工作完毕
break;
default:
break;
}
return true;
}

return super.onKeyDown(keyCode, event);
}

/**
* 处理照片被拍摄之后的事件
*/
private final class TakePictureCallback implements PictureCallback {
@Override
public void onPictureTaken(byte[] data, Camera camera) {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);

/* 照片将被保存到 SD 卡跟目录下,文件名为系统时间,后缀名为".jpg" */
File file = new File(Environment.getExternalStorageState(), System.currentTimeMillis() + ".jpg");
try {
FileOutputStream fos = new FileOutputStream(file);

/* 位图格式为JPEG
* 参数二位 0-100 的数值,100为最大值,表示无损压缩
* 参数三传入一个输出流对象,将图片数据输出到流中
*/
bitmap.compress(CompressFormat.JPEG, 100, fos);
fos.close();

/* 拍完照后回到预览状态,继续取景 */
camera.startPreview();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}

转自:

http://blog.csdn.net/wenlin56/archive/2010/12/16/6080984.aspx


更多相关文章

  1. Android(安卓)java和javascript之间的相互调用
  2. Android中的Typeface
  3. 中:Android(安卓)startActivity原理分析(基于Android(安卓)8.1 AO
  4. Android(安卓)之 自定义控件用法介绍
  5. Android(安卓)---js与java的相互调用
  6. 使用ContentProvider管理照片
  7. android 用ExpandableListView实现的文件目录树框架
  8. Android(安卓)Activity之间跳转
  9. Android之反射机制与JSON解析

随机推荐

  1. 我的第26个代码
  2. 用long类型让我出了次生产事故,写代码还是
  3. 还不明白可空类型原理? 我可要挖到底了
  4. 追了多年的开发框架,你还认识指针吗?
  5. Sql Server之旅——第一站 那些给我们带
  6. Sql Server之旅——第二站 理解讨厌的表
  7. Sql Server之旅——第三站 解惑那些背了
  8. 命名空间引用类的三种方式 和 命名冲突解
  9. 数据库CURD常用操作-select查询-预处理
  10. 12c pdb ora-01033