Android深入探究-- 实现即时拍照并上传

Nostalgiachild 2011-05-25

使用摄像头拍照

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.代码清单

**stringvalues:strings.xml

viewplaincopytoclipboardprint?

<?xmlversion="1.0"encoding="utf-8"?>

<resources>

<stringname="app_name">手机拍照程序</string>

</resources>

<?xmlversion="1.0"encoding="utf-8"?>

<resources>

<stringname="app_name">手机拍照程序</string>

</resources>

**AndroidManifest.xml

viewplaincopytoclipboardprint?

<?xmlversion="1.0"encoding="utf-8"?>

<manifestxmlns:android="http://schemas.android.com/apk/res/android"

package="wjh.android.takepicture"

android:versionCode="1"

android:versionname="1.0">

<applicationandroid:icon="@drawable/icon"android:label="@string/app_name">

<!--android:screenOrientation="landscape"表示横向界面-->

<activityandroid:name=".MainActicity"android:label="@string/app_name"android:screenOrientation="landscape">

<intent-filter>

<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

</application>

<uses-sdkandroid:minSdkVersion="8"/>

<!--在SDCard中创建与删除文件权限-->

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

<!--往SDCard写入数据权限-->

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

<!--申请使用摄像头的权限-->

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

</manifest>

<?xmlversion="1.0"encoding="utf-8"?>

<manifestxmlns:android="http://schemas.android.com/apk/res/android"

package="wjh.android.takepicture"

android:versionCode="1"

android:versionname="1.0">

<applicationandroid:icon="@drawable/icon"android:label="@string/app_name">

<!--android:screenOrientation="landscape"表示横向界面-->

<activityandroid:name=".MainActicity"android:label="@string/app_name"android:screenOrientation="landscape">

<intent-filter>

<actionandroid:name="android.intent.action.MAIN"/>

<categoryandroid:name="android.intent.category.LAUNCHER"/>

</intent-filter>

</activity>

</application>

<uses-sdkandroid:minSdkVersion="8"/>

<!--在SDCard中创建与删除文件权限-->

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

<!--往SDCard写入数据权限-->

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

<!--申请使用摄像头的权限-->

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

</manifest>

**main.xml

viewplaincopytoclipboardprint?

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<SurfaceViewandroid:id="@+id/surfaceView"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

/>

</LinearLayout>

<?xmlversion="1.0"encoding="utf-8"?>

<LinearLayoutxmlns:android="http://schemas.android.com/apk/res/android"

android:orientation="vertical"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

>

<SurfaceViewandroid:id="@+id/surfaceView"

android:layout_width="fill_parent"

android:layout_height="fill_parent"

/>

</LinearLayout>

**MainActicity

viewplaincopytoclipboardprint?

publicclassMainActicityextendsActivity{

privateCameracamera;

privatebooleanpreview=false;

@Override

publicvoidonCreate(BundlesavedInstanceState){

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);

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

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

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

surfaceView.getHolder().addCallback(newSurfaceViewCallback());

}

privatefinalclassSurfaceViewCallbackimplementsCallback{

/**

*surfaceView被创建成功后调用此方法

*/

@Override

publicvoidsurfaceCreated(SurfaceHolderholder){

/*

*在SurfaceView创建好之后打开摄像头

*注意是android.hardware.Camera

*/

camera=Camera.open();

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);

preview=true;

}

@Override

publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth,

intheight){

}

/**

*SurfaceView被销毁时释放掉摄像头

*/

@Override

publicvoidsurfaceDestroyed(SurfaceHolderholder){

if(camera!=null){

/*若摄像头正在工作,先停止它*/

if(preview){

camera.stopPreview();

preview=false;

}

camera.release();

}

}

}

/**

*手机键盘按键事件

*返回true,将阻止事件继续传递,例如搜索键,他默认会触发和打开系统的搜索引擎。返回true后,将不会触发。

*/

@Override

publicbooleanonKeyDown(intkeyCode,KeyEventevent){

/*

*event.getRepeatCount()为重复按键的次数,例如,快速地对某个键连续按了两次,则此值为一,表示重复了一次。往上可以累推。

*按键只被按了一次,则此值为0。

*这有点类似于鼠标的"单击"和"双击"。

*/

if(camera!=null&&event.getRepeatCount()==0){

switch(keyCode){

caseKeyEvent.KEYCODE_SEARCH://搜索键

/*按下搜索键自动对焦,如果要关注它的事件,

*可以实现AutoFocusCallback接口,并实例化其对象传入*/

camera.autoFocus(null);

break;

caseKeyEvent.KEYCODE_CAMERA://拍照键

caseKeyEvent.KEYCODE_DPAD_CENTER://中间确认键

/*

*@paramshutter:照片被捕获之后的回调对象

*@paramraw:此回调对象可以生产为压缩的图片数据

*@paramjpeg:此回调对象可以产生压缩后的图片数据,其onPictureTaken将被调用

*/

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

/*拍完照后回到预览状态,继续取景--错误的方式*/

//camera.startPreview();必须写在onPictureTaken方法内部,因为takePicture内部是另开了一条线程异步的完成保存照片等操作。

//虽然takePicture方法完成了,但是并不代表其内部的工作全部完成,也不代表摄像头以及从上一次“拍照”任务中工作完毕

break;

default:

break;

}

returntrue;

}

returnsuper.onKeyDown(keyCode,event);

}

/**

*处理照片被拍摄之后的事件

*/

privatefinalclassTakePictureCallbackimplementsPictureCallback{

@Override

publicvoidonPictureTaken(byte[]data,Cameracamera){

Bitmapbitmap=BitmapFactory.decodeByteArray(data,0,data.length);

/*照片将被保存到SD卡跟目录下,文件名为系统时间,后缀名为".jpg"*/

Filefile=newFile(Environment.getExternalStorageState(),System.currentTimeMillis()+".jpg");

try{

FileOutputStreamfos=newFileOutputStream(file);

/*位图格式为JPEG

*参数二位0-100的数值,100为最大值,表示无损压缩

*参数三传入一个输出流对象,将图片数据输出到流中

*/

bitmap.compress(CompressFormat.JPEG,100,fos);

fos.close();

/*拍完照后回到预览状态,继续取景*/

camera.startPreview();

}catch(IOExceptione){

e.printStackTrace();

}

}

}

}

 

本文来自CSDN博客,出处:http://blog.csdn.net/hwl1314/archive/2011/04/16/6327565.aspx

相关推荐