Android自定义照相机倒计时拍照
程序员文章站
2023-12-17 08:47:22
自定义拍照会用到surfaceview控件显示照片的预览区域,以下是布局文件:
两个textview是用来显示提示信息和倒计时的秒数的
相关教程:android...
自定义拍照会用到surfaceview控件显示照片的预览区域,以下是布局文件:
两个textview是用来显示提示信息和倒计时的秒数的
<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" 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中的具体实现以及详细注释:
package com.dhsr.pujiejia.ui; import java.io.file; import java.io.fileoutputstream; import java.text.simpledateformat; import java.util.date; import android.annotation.suppresslint; import android.app.activity; import android.content.context; import android.content.intent; import android.content.res.configuration; import android.graphics.bitmap; import android.graphics.bitmapfactory; import android.graphics.pixelformat; import android.hardware.camera; import android.hardware.camera.camerainfo; import android.os.bundle; import android.os.environment; import android.os.handler; import android.view.surfaceholder; import android.view.surfaceview; import android.view.window; import android.view.windowmanager; import android.widget.textview; import com.example.pujiejiaapp.r; @suppresslint({ "newapi", "sdcardpath" }) public class cameraactivity extends activity implements runnable { // 预览图片范围 private surfaceview surfaceview; private textview tv_time; // 倒计时拍摄 private int cameratime = 4; private camera camera; private boolean preview = false; // 文件名字 private string filename; // 文件名字的带的时间戳 private string timestring; // 格式化时间 private simpledateformat dateformat; // 日期对象 private date date; // 控制线程 boolean stopthread = false; private file file; string photo; private handler mhandler = new handler() { public void handlemessage(android.os.message msg) { int what = msg.what; switch (what) { case 222: tv_time.settext("" + cameratime); if ("0".equals(tv_time.gettext().tostring())) { tv_time.settext("拍摄成功!"); takephoto(); } break; } }; }; @override protected void oncreate(bundle savedinstancestate) { // todo auto-generated method stub super.oncreate(savedinstancestate); setcontentview(r.layout.activity_test); cameraactivity.this.setfinishontouchoutside(false); // 初始化数据 findview(); surfaceview.getholder().addcallback(new sufacelistener()); /* 下面设置surface不维护自己的缓冲区,而是等待屏幕的渲染引擎将内容推送到用户面前 */ surfaceview.getholder() .settype(surfaceholder.surface_type_push_buffers); surfaceview.getholder().setfixedsize(200, 200); // 设置分辨率 } @override protected void onstart() { // todo auto-generated method stub super.onstart(); // 开启线程 new thread(this).start(); } private final class sufacelistener implements surfaceholder.callback { /** * surface改变 */ @override public void surfacechanged(surfaceholder holder, int format, int width, int height) { } /** * surface创建 */ @override public void surfacecreated(surfaceholder holder) { try { for (int i = 0; i < camera.getnumberofcameras(); i++) { camerainfo info = new camerainfo(); camera.getcamerainfo(i, info); // 调用系统的前置摄像头 if (info.facing == camerainfo.camera_facing_front) { camera = camera.open(i); } } camera.parameters parameters = camera.getparameters(); /* 每秒从摄像头捕获5帧画面, */ parameters.setpreviewframerate(5); /* 设置照片的输出格式:jpg */ parameters.setpictureformat(pixelformat.jpeg); /* 照片质量 */ parameters.set("jpeg-quality", 85); windowmanager wm = (windowmanager) getsystemservice(context.window_service); camera.setparameters(parameters); camera.setpreviewdisplay(surfaceview.getholder());// 通过surfaceview显示取景画面 camera.startpreview(); preview = true; } catch (exception e) { } } /** * surface销毁 */ @override public void surfacedestroyed(surfaceholder holder) { if (camera != null) { if (preview) camera.stoppreview(); camera.release(); camera = null; } } } /** * 拍摄照片 */ private void takephoto() { // 执行拍照效果 camera.takepicture(null, null, new camera.picturecallback() { @override public void onpicturetaken(byte[] data, camera camera) { try { bitmap bitmap = bitmapfactory.decodebytearray(data, 0, data.length); timestring = formatdate(); //保存到data/data目录自定义文件夹下 filename = "/data/data/com.example.pujiejiaapp/images/" + timestring + ".jpg"; file file = new file(filename); boolean createnewfile = file.createnewfile() system.out.println("创建文件夹成功没有" + createnewfile); system.out.println(file); fileoutputstream outstream = new fileoutputstream(file); bitmap.compress(bitmap.compressformat.jpeg, 60, outstream); outstream.flush(); outstream.close(); // 重新浏览 camera.stoppreview(); camera.startpreview(); preview = true; } catch (exception e) { e.printstacktrace(); } finally { } } }); } @override public void run() { while (!stopthread) { try { //按秒数倒计时 thread.sleep(1000); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } cameratime--; mhandler.sendemptymessage(222); if (cameratime <= 0) { break; } } } // 初始化数据 private void findview() { surfaceview = (surfaceview) this.findviewbyid(r.id.surfaceview); tv_time = (textview) findviewbyid(r.id.tv_time); } // 格式化系统的时间 public string formatdate() { date = new date(system.currenttimemillis()); // 日期格式 dateformat = new simpledateformat("'img'_yyyymmddhhmmss"); return dateformat.format(date); } @override protected void ondestroy() { // todo auto-generated method stub // 线程已关闭 super.ondestroy(); stopthread = true; } }
核心代码详解:
1.创建surfaceview时,surfacecreated()方法中
for (int i = 0; i < camera.getnumberofcameras(); i++) { camerainfo info = new camerainfo(); 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()方法中:
bitmap bitmap = bitmapfactory.decodebytearray(data, 0, data.length); timestring = formatdate(); filename = "/data/data/com.example.pujiejiaapp/images/" + timestring + ".jpg"; photo = timestring + ".jpg"; file file = new file(filename); boolean createnewfile = file.createnewfile(); fileoutputstream outstream = new fileoutputstream(file); bitmap.compress(bitmap.compressformat.jpeg, 60, outstream);
此部分代码为将拍摄到的图片保存为以bitmap格式保存在指定的目录下
3.开子线程用于倒计时拍摄
public void run() { while (!stopthread) { try { thread.sleep(1000); } catch (interruptedexception e) { // todo auto-generated catch block e.printstacktrace(); } cameratime--; mhandler.sendemptymessage(222); if (cameratime <= 0) { break; } } }
希望大家理解核心代码的详细注释,欢迎提供意见,希望能给大家带来帮助,谢谢!