Android—实现自定义相机倒计时拍照
这篇博客为大家介绍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;
}
}
}
希望大家理解核心代码的详细注释,欢迎提供意见,希望能给大家带来帮助,谢谢!
源码:http://pan.baidu.com/s/1kVSBEK3
Android—实现自定义相机倒计时拍照的更多相关文章
- 如何用uniapp+vue开发自定义相机插件——拍照+录像功能
调用手机的相机功能并实现拍照和录像是很多APP与插件都必不可少的一个功能,今天智密科技就来分享一下如何基于uniapp + vue实现自定义相机界面,并且实现: 1: 自定义拍照 2: 自定义录像 3 ...
- Android相机使用(系统相机、自定义相机、大图片处理)
本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理(避免OOM),还有简要提一下有些人Surf ...
- Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显示出来,该例子也会涉及到Android加载大图片时候的处理 ...
- Android调用系统相机、自己定义相机、处理大图片
Android调用系统相机和自己定义相机实例 本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,而且因为涉及到要把拍到的照片显示出来,该样例也会涉及到Android载入大图片时候的处 ...
- Android自定义相机拍照、图片裁剪的实现
最近项目里面又要加一个拍照搜题的功能,也就是用户对着不会做的题目拍一张照片,将照片的文字使用ocr识别出来,再调用题库搜索接口搜索出来展示给用户,类似于小猿搜题.学霸君等app. 其实Android提 ...
- Android Multimedia框架总结(十四)Camera框架初识及自定义相机案例
转载请把头部出处链接和尾部二维码一起转载,本文出自逆流的鱼yuiop:http://blog.csdn.net/hejjunlin/article/details/52738492 前言:国庆节告一段 ...
- Android实现自定义的相机
使用系统相机 android中使用系统相机是很方便的,单这仅仅是简单的使用而已,并不能获得什么特殊的效果. 要想让应用有相机的action,咱们就必须在清单文件中做一些声明,好让系统知道,如下 < ...
- Android Camera开发系列(下)——自定义Camera实现拍照查看图片等功能
Android Camera开发系列(下)--自定义Camera实现拍照查看图片等功能 Android Camera开发系列(上)--Camera的基本调用与实现拍照功能以及获取拍照图片加载大图片 上 ...
- android 自定义相机
老规矩,先上一下项目地址:GitHub:https://github.com/xiangzhihong/CameraDemo 方式: 调用Camera API 自定义相机 调用系统相机 由于需求不同, ...
随机推荐
- 数据结构与算法JavaScript (五) 串(经典KMP算法)
KMP算法和BM算法 KMP是前缀匹配和BM后缀匹配的经典算法,看得出来前缀匹配和后缀匹配的区别就仅仅在于比较的顺序不同 前缀匹配是指:模式串和母串的比较从左到右,模式串的移动也是从 左到右 后缀匹配 ...
- Android入门(二十一)解析XML
原文链接:http://www.orlion.ga/685/ 解析XML常用的方式有两种,一种是PULL解析一种是SAX解析. 假设解析数据为: <apps> <app> ...
- Hibernate4.0之HibernateSessionFactory源码详解
import org.hibernate.HibernateException; import org.hibernate.Session; import org.hibernate.cfg.Conf ...
- 分享几个.NET WinForm开源组件,纪念逐渐远去的WinForm。。。
前面3个月的时间内,这些.NET开源项目你知道吗?系列文章已经发表了3篇,共计45个平时接触比较少,曾经默默无闻的.NET开源项目,展示给大家,当然不是每个人都能用得上,但也的确是有些人用了,反响还不 ...
- 感恩回馈,新鲜出炉的《ASP.NET MVC 5框架揭秘》免费赠送
上次针对<ASP.NET Web API 2框架揭秘>举办了一次评论赠书活动,很多人问我相同的活动要不要针对<ASP.NET MVC 5框架揭秘>(阅读样章)再来一次,为此我向 ...
- jQuery.unique引发一个血案
项目开发过程中,PM说系统只要在一个特定的浏览器中运行就好,但是在其他的浏览器中不能出现逻辑的错误,所以在开发过程中,前端和后台选择是Chrome浏览器,没有仔细测试Firefox和IE.但是昨天PM ...
- iOS开发之窥探UICollectionViewController(三) --使用UICollectionView自定义瀑布流
上篇博客的实例是自带的UICollectionViewDelegateFlowLayout布局基础上来做的Demo, 详情请看<iOS开发之窥探UICollectionViewControlle ...
- golang 字符串操作实例
package main import s "strings" import "fmt" var p = fmt.Println func main() { p ...
- Windows 10 技术预览版9926 “未知源”引起系统休眠后自启的解决办法
问题的由来: 自从安装上了最新发布的Windows 10 ,使用起来有诸多的改进:无论是重绘的图标还是通知消息中心的整合还是更智能的OneDrive客户端都使得工作起来非常愉悦. 不过笔者这两天频繁遇 ...
- 当Azure里的虚拟机网卡被禁用了之后……
这样的想法来自于一个假设,如果网卡被禁用之后,用户该如何处理,Azure又该如何处理,对于设置在虚拟机中的禁用网卡选项是否还有存在的意义?通常情况下,点选了禁用网卡对于你和虚拟机来说就一下之抓瞎了,瞬 ...