Android自定义照相机倒计时拍照
自定义拍照会用到SurfaceView控件显示照片的预览区域,以下是布局文件:
两个TextView是用来显示提示信息和倒计时的秒数的
相关教程:Android开发从相机或相册获取图片裁剪
Android启动相机拍照并返回图片
<RelativeLayoutxmlns: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="#266194" android:orientation="vertical" tools:context=".TestActivity"> <SurfaceView android:id="@+id/surfaceView" android:layout_width="match_parent" android:layout_height="match_parent" android:layout_centerInParent="true"/> <LinearLayout android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_centerInParent="true" android:orientation="vertical"> <TextView android:layout_width="match_parent" android:layout_height="wrap_content" android:text="请调整位置到此区域" android:textColor="#ff0000" android:textSize="32sp"/> <TextView android:id="@+id/tv_time" android:layout_width="match_parent" android:layout_height="wrap_content" android:paddingTop="10dp" android:gravity="center_horizontal" android:textColor="#266194" android:textSize="32sp"/> </LinearLayout> </RelativeLayout>
接下来是mainActivity中的具体实现以及详细注释:
packagecom.dhsr.pujiejia.ui; importjava.io.File; importjava.io.FileOutputStream; importjava.text.SimpleDateFormat; importjava.util.Date; importandroid.annotation.SuppressLint; importandroid.app.Activity; importandroid.content.Context; importandroid.content.Intent; importandroid.content.res.Configuration; importandroid.graphics.Bitmap; importandroid.graphics.BitmapFactory; importandroid.graphics.PixelFormat; importandroid.hardware.Camera; importandroid.hardware.Camera.CameraInfo; importandroid.os.Bundle; importandroid.os.Environment; importandroid.os.Handler; importandroid.view.SurfaceHolder; importandroid.view.SurfaceView; importandroid.view.Window; importandroid.view.WindowManager; importandroid.widget.TextView; importcom.example.pujiejiaapp.R; @SuppressLint({"NewApi","SdCardPath"}) publicclassCameraActivityextendsActivityimplementsRunnable{ //预览图片范围 privateSurfaceViewsurfaceView; privateTextViewtv_time; //倒计时拍摄 privateintcameratime=4; privateCameracamera; privatebooleanpreview=false; //文件名字 privateStringfilename; //文件名字的带的时间戳 privateStringtimeString; //格式化时间 privateSimpleDateFormatdateFormat; //日期对象 privateDatedate; //控制线程 booleanstopThread=false; privateFilefile; Stringphoto; privateHandlermHandler=newHandler(){ publicvoidhandleMessage(android.os.Messagemsg){ intwhat=msg.what; switch(what){ case222: tv_time.setText(""+cameratime); if("0".equals(tv_time.getText().toString())){ tv_time.setText("拍摄成功!"); takePhoto(); } break; } }; }; @Override protectedvoidonCreate(BundlesavedInstanceState){ //TODOAuto-generatedmethodstub super.onCreate(savedInstanceState); setContentView(R.layout.activity_test); CameraActivity.this.setFinishOnTouchOutside(false); //初始化数据 findView(); surfaceView.getHolder().addCallback(newSufaceListener()); /*下面设置Surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前*/ surfaceView.getHolder() .setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS); surfaceView.getHolder().setFixedSize(200,200);//设置分辨率 } @Override protectedvoidonStart(){ //TODOAuto-generatedmethodstub super.onStart(); //开启线程 newThread(this).start(); } privatefinalclassSufaceListenerimplementsSurfaceHolder.Callback{ /** *surface改变 */ @Override publicvoidsurfaceChanged(SurfaceHolderholder,intformat,intwidth, intheight){ } /** *surface创建 */ @Override publicvoidsurfaceCreated(SurfaceHolderholder){ try{ for(inti=0;i<Camera.getNumberOfCameras();i++){ CameraInfoinfo=newCameraInfo(); Camera.getCameraInfo(i,info); //调用系统的前置摄像头 if(info.facing==CameraInfo.CAMERA_FACING_FRONT){ camera=Camera.open(i); } } Camera.Parametersparameters=camera.getParameters(); /*每秒从摄像头捕获5帧画面,*/ parameters.setPreviewFrameRate(5); /*设置照片的输出格式:jpg*/ parameters.setPictureFormat(PixelFormat.JPEG); /*照片质量*/ parameters.set("jpeg-quality",85); WindowManagerwm=(WindowManager)getSystemService(Context.WINDOW_SERVICE); camera.setParameters(parameters); camera.setPreviewDisplay(surfaceView.getHolder());//通过SurfaceView显示取景画面 camera.startPreview(); preview=true; }catch(Exceptione){ } } /** *surface销毁 */ @Override publicvoidsurfaceDestroyed(SurfaceHolderholder){ if(camera!=null){ if(preview) camera.stopPreview(); camera.release(); camera=null; } } } /** *拍摄照片 */ privatevoidtakePhoto(){ //执行拍照效果 camera.takePicture(null,null,newCamera.PictureCallback(){ @Override publicvoidonPictureTaken(byte[]data,Cameracamera){ try{ Bitmapbitmap=BitmapFactory.decodeByteArray(data,0, data.length); timeString=formatDate(); //保存到data/data目录自定义文件夹下 filename="/data/data/com.example.pujiejiaapp/images/" +timeString+".jpg"; Filefile=newFile(filename); booleancreateNewFile=file.createNewFile() System.out.println("创建文件夹成功没有"+createNewFile); System.out.println(file); FileOutputStreamoutStream=newFileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG,60,outStream); outStream.flush(); outStream.close(); //重新浏览 camera.stopPreview(); camera.startPreview(); preview=true; }catch(Exceptione){ e.printStackTrace(); }finally{ } } }); } @Override publicvoidrun(){ while(!stopThread){ try{ //按秒数倒计时 Thread.sleep(1000); }catch(InterruptedExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } cameratime--; mHandler.sendEmptyMessage(222); if(cameratime<=0){ break; } } } //初始化数据 privatevoidfindView(){ surfaceView=(SurfaceView)this.findViewById(R.id.surfaceView); tv_time=(TextView)findViewById(R.id.tv_time); } //格式化系统的时间 publicStringformatDate(){ date=newDate(System.currentTimeMillis()); //日期格式 dateFormat=newSimpleDateFormat("'IMG'_yyyyMMddHHmmss"); returndateFormat.format(date); } @Override protectedvoidonDestroy(){ //TODOAuto-generatedmethodstub //线程已关闭 super.onDestroy(); stopThread=true; } }
核心代码详解:
1.创建SurfaceView时,surfaceCreated()方法中
for(inti=0;i<Camera.getNumberOfCameras();i++){ CameraInfoinfo=newCameraInfo(); Camera.getCameraInfo(i,info); //调用系统的前置摄像头 if(info.facing==CameraInfo.CAMERA_FACING_FRONT){ camera=Camera.open(i); } }
此部分代码为打开相机时默认打开前置摄像头CameraInfo.CAMERA_FACING_BACK为默认打开后置摄像头,CameraInfo.CAMERA_FACING_FRONT前置摄像头
2.照片拍摄takePhoto()方法中:
Bitmapbitmap=BitmapFactory.decodeByteArray(data,0, data.length); timeString=formatDate(); filename="/data/data/com.example.pujiejiaapp/images/" +timeString+".jpg"; photo=timeString+".jpg"; Filefile=newFile(filename); booleancreateNewFile=file.createNewFile(); FileOutputStreamoutStream=newFileOutputStream(file); bitmap.compress(Bitmap.CompressFormat.JPEG,60,outStream);
此部分代码为将拍摄到的图片保存为以bitmap格式保存在指定的目录下
3.开子线程用于倒计时拍摄
publicvoidrun(){ while(!stopThread){ try{ Thread.sleep(1000); }catch(InterruptedExceptione){ //TODOAuto-generatedcatchblock e.printStackTrace(); } cameratime--; mHandler.sendEmptyMessage(222); if(cameratime<=0){ break; } } }
希望大家理解核心代码的详细注释,欢迎提供意见,希望能给大家带来帮助,谢谢!