Android自定義照相機(jī)倒計時拍照
自定義拍照會用到SurfaceView控件顯示照片的預(yù)覽區(qū)域,以下是布局文件:
兩個TextView是用來顯示提示信息和倒計時的秒數(shù)的
相關(guān)教程:Android開發(fā)從相機(jī)或相冊獲取圖片裁剪
<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="請調(diào)整位置到此區(qū)域" 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中的具體實現(xiàn)以及詳細(xì)注釋:
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 {
// 預(yù)覽圖片范圍
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);
// 初始化數(shù)據(jù)
findView();
surfaceView.getHolder().addCallback(new SufaceListener());
/* 下面設(shè)置Surface不維護(hù)自己的緩沖區(qū),而是等待屏幕的渲染引擎將內(nèi)容推送到用戶面前 */
surfaceView.getHolder()
.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
surfaceView.getHolder().setFixedSize(200, 200); // 設(shè)置分辨率
}
@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創(chuàng)建
*/
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
// 調(diào)用系統(tǒng)的前置攝像頭
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
camera = Camera.open(i);
}
}
Camera.Parameters parameters = camera.getParameters();
/* 每秒從攝像頭捕獲5幀畫面, */
parameters.setPreviewFrameRate(5);
/* 設(shè)置照片的輸出格式:jpg */
parameters.setPictureFormat(PixelFormat.JPEG);
/* 照片質(zhì)量 */
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() {
// 執(zhí)行拍照效果
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("創(chuàng)建文件夾成功沒有" + 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 {
//按秒數(shù)倒計時
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
cameratime--;
mHandler.sendEmptyMessage(222);
if (cameratime <= 0) {
break;
}
}
}
// 初始化數(shù)據(jù)
private void findView() {
surfaceView = (SurfaceView) this.findViewById(R.id.surfaceView);
tv_time = (TextView) findViewById(R.id.tv_time);
}
// 格式化系統(tǒng)的時間
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
// 線程已關(guān)閉
super.onDestroy();
stopThread = true;
}
}
核心代碼詳解:
1.創(chuàng)建SurfaceView時,surfaceCreated()方法中
for (int i = 0; i < Camera.getNumberOfCameras(); i++) {
CameraInfo info = new CameraInfo();
Camera.getCameraInfo(i, info);
// 調(diào)用系統(tǒng)的前置攝像頭
if (info.facing == CameraInfo.CAMERA_FACING_FRONT) {
camera = Camera.open(i);
}
}
此部分代碼為打開相機(jī)時默認(rèn)打開前置攝像頭CameraInfo.CAMERA_FACING_BACK為默認(rèn)打開后置攝像頭,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;
}
}
}
希望大家理解核心代碼的詳細(xì)注釋,歡迎提供意見,希望能給大家?guī)韼椭x謝!
- android 7自定義相機(jī)預(yù)覽及拍照功能
- Android調(diào)用系統(tǒng)照相機(jī)拍照與攝像的方法
- Android如何調(diào)用系統(tǒng)相機(jī)拍照
- Android編程實現(xiàn)調(diào)用相冊、相機(jī)及拍照后直接裁剪的方法
- Android自定義相機(jī)實現(xiàn)定時拍照功能
- Android自定義組件獲取本地圖片和相機(jī)拍照圖片
- Android使用系統(tǒng)自帶的相機(jī)實現(xiàn)一鍵拍照功能
- Android 系統(tǒng)相機(jī)拍照后相片無法在相冊中顯示解決辦法
- Android 實現(xiàn)調(diào)用系統(tǒng)照相機(jī)拍照和錄像的功能
- Android 調(diào)用系統(tǒng)照相機(jī)拍照和錄像
- Android實現(xiàn)從本地圖庫/相機(jī)拍照后裁剪圖片并設(shè)置頭像
- Android啟動相機(jī)拍照并返回圖片
- Android打開系統(tǒng)相機(jī)并拍照的2種顯示方法
相關(guān)文章
Android中src和background的區(qū)別詳解
這篇文章主要介紹了Android中src和background的區(qū)別詳解的相關(guān)資料,需要的朋友可以參考下2016-09-09
Android用TextView實現(xiàn)跑馬燈效果代碼
大家好,本篇文章主要講的是Android?TextView實現(xiàn)跑馬燈效果代碼,感興趣的同學(xué)趕快來看一看吧,對你有幫助的話記得收藏一下2022-01-01
Android中EditText+Button組合導(dǎo)致輸入板無法收起的原因分析及解決辦法
這篇文章主要介紹了Android中EditText+Button組合導(dǎo)致輸入板無法收起的原因分析及解決辦法的相關(guān)資料,需要的朋友可以參考下2016-01-01
淺談Android為RecyclerView增加監(jiān)聽以及數(shù)據(jù)混亂的小坑
下面小編就為大家?guī)硪黄獪\談Android為RecyclerView增加監(jiān)聽以及數(shù)據(jù)混亂的小坑。小編覺得挺不錯的,現(xiàn)在就分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2017-04-04

