Android開發(fā)教程之調(diào)用攝像頭功能的方法詳解
本文實例講述了Android調(diào)用攝像頭功能的方法。分享給大家供大家參考,具體如下:
我們要調(diào)用攝像頭的拍照功能,顯然
第一步必須加入調(diào)用攝像頭硬件的權(quán)限,拍完照后我們要將圖片保存在SD卡中,必須加入SD卡讀寫權(quán)限,所以第一步,我們應(yīng)該在Android清單文件中加入以下代碼
攝像頭權(quán)限:
<uses-permission android:name="android.permission.CAMERA"/>
SD卡讀寫權(quán)限:
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
第二步,要將攝像頭捕獲的圖像實時地顯示在手機上。
我們是用SurfaceView這個視圖組件來實現(xiàn)的,因此在main.xml中加入下列代碼
<SurfaceView android:layout_width="fill_parent" android:layout_height="fill_parent" android:id="@+id/surfaceview" />
第三步,設(shè)置窗口的顯示方式
首先獲得當前窗口
Window window = getWindow();//得到窗口
接著設(shè)置沒有標題
requestWindowFeature(Window.FEATURE_NO_TITLE);//沒有標題
接著設(shè)置全屏
當然,我們在拍照過程中,屏幕必須一致處于高亮狀態(tài),因此接著加入下面代碼
至此,我們將窗口的顯示方式規(guī)定死了,然后才能設(shè)置窗口上顯示的組件(順序非常重要)
setContentView(R.layout.main);
第四步,設(shè)置SurficeView顯示控件的屬性
找到surficeView
surfaceView = (SurfaceView) findViewById(R.id.surfaceview);
設(shè)置它的像素為800x600
surfaceView.getHolder().setFixedSize(800, 480); //下面設(shè)置surfaceView不維護自己的緩沖區(qū),而是等待屏幕的渲染引擎將內(nèi)容推送到用戶面前 surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
第五步,就是為surficeView加入回調(diào)方法(callBack)
surfaceView.getHolder().addCallback(new SurfaceCallback());
上面的回調(diào)類是我們自己定義的,代碼如下
private class SurfaceCallback implements SurfaceHolder.Callback{
@Override
public void surfaceCreated(SurfaceHolder holder) {
try {
camera = Camera.open();//打開硬件攝像頭,這里導包得時候一定要注意是android.hardware.Camera
WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);//得到窗口管理器
Display display = wm.getDefaultDisplay();//得到當前屏幕
Camera.Parameters parameters = camera.getParameters();//得到攝像頭的參數(shù)
parameters.setPreviewSize(display.getWidth(), display.getHeight());//設(shè)置預(yù)覽照片的大小
parameters.setPreviewFrameRate(3);//設(shè)置每秒3幀
parameters.setPictureFormat(PixelFormat.JPEG);//設(shè)置照片的格式
parameters.setJpegQuality(85);//設(shè)置照片的質(zhì)量
parameters.setPictureSize(display.getHeight(), display.getWidth());//設(shè)置照片的大小,默認是和 屏幕一樣大
camera.setParameters(parameters);
camera.setPreviewDisplay(surfaceView.getHolder());//通過SurfaceView顯示取景畫面
camera.startPreview();//開始預(yù)覽
isPreview = true;//設(shè)置是否預(yù)覽參數(shù)為真
} catch (IOException e) {
Log.e(TAG, e.toString());
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
if(camera!=null){
if(isPreview){//如果正在預(yù)覽
camera.stopPreview();
camera.release();
}
}
}
}
第六步,我們必須對按鍵事件進行監(jiān)聽,如是拍照還是聚焦,代碼如下
public boolean onKeyDown(int keyCode, KeyEvent event) {//處理按鍵事件
if(camera!=null&&event.getRepeatCount()==0)//代表只按了一下
{
switch(keyCode){
case KeyEvent.KEYCODE_BACK://如果是搜索鍵
camera.autoFocus(null);//自動對焦
break;
case KeyEvent.KEYCODE_DPAD_CENTER://如果是中間鍵
camera.takePicture(null, null, new TakePictureCallback());//將拍到的照片給第三個對象中,這里的TakePictureCallback()是自己定義的,在下面的代碼中
break;
}
}
return true;//阻止事件往下傳遞,否則按搜索鍵會變成系統(tǒng)默認的
}
private final class TakePictureCallback implements PictureCallback{
public void onPictureTaken(byte[] data, Camera camera) {
try {
Bitmap bitmap = BitmapFactory.decodeByteArray(data, 0, data.length);
File file = new File(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");
FileOutputStream outputStream = new FileOutputStream(file);
bitmap.compress(CompressFormat.JPEG, 100, outputStream);
outputStream.close();
camera.stopPreview();
camera.startPreview();//處理完數(shù)據(jù)之后可以預(yù)覽
} catch (Exception e) {
Log.e(TAG, e.toString());
}
}
}
注意,代碼中有兩個回調(diào)類,一個是SurfaceCallback(),另外一個是TakePictureCallback(),初學者可能一時難以理解,通俗地講,前者是用來監(jiān)視surficeView這個暫時存放圖片數(shù)據(jù)的顯示控件的,根據(jù)它的顯示情況調(diào)用不同的方法,包括surfaceCreated(),surfaceChanged(),surfaceDestroyed(),也就不難理解為什么會有這三個回調(diào)方法了(注意,在surfaceDestroyed()方法中必須釋放攝像頭,詳細代碼參見上方)。TakePictureCallback()是為了監(jiān)視是否拍照而設(shè)計的接口,期中也僅有一個方法,camera將拍照得到的數(shù)據(jù)傳入方法,我們便可以對拍照得到的數(shù)據(jù)進行進一步處理了。
至此,簡單的拍照功能介紹完畢!
package cn.camera.rxm;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Calendar;
import java.util.Locale;
import org.apache.commons.logging.Log;
import android.text.format.DateFormat;
import android.util.*;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Bitmap.CompressFormat;
import android.graphics.BitmapFactory;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.hardware.Camera.PictureCallback;
import android.os.Bundle;
import android.os.Environment;
import android.view.LayoutInflater;
import android.view.Menu;
import android.view.MenuItem;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
//import android.widget.Toast;
public class MycamActivity extends Activity {
private Preview mPreview;
private Camera mCamera;
Bitmap CameraBitmap;
SurfaceHolder mHolder;
private static final int OPTION_SNAPSHOT = 0;
private static final int OPTION_STOPCAMERA = 1;
private View viewStart;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LayoutInflater flater = this.getLayoutInflater();
viewStart = flater.inflate(R.layout.main, null);
setContentView(viewStart);
Button btn1 = (Button)findViewById(R.id.button1);
btn1.setOnClickListener(
new OnClickListener(){
public void onClick(View v){
mPreview = new Preview(getBaseContext());
setContentView(mPreview);
};
}
);
}
public boolean onCreateOptionsMenu(Menu menu){
//
menu.add(0, OPTION_SNAPSHOT, 0, R.string.take);
//
menu.add(0, OPTION_STOPCAMERA, 1, R.string.back);
//
return true;//super.onCreateOptionsMenu(menu);
}
public boolean onOptionsItemSelected(MenuItem item) {
//
int itemId = item.getItemId();
//
switch(itemId){
case OPTION_SNAPSHOT:
//拍攝照片
mCamera.takePicture(null, null, jpegCallback);
try {
Thread.sleep(4000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
mCamera.startPreview();
break;
case OPTION_STOPCAMERA:
mPreview = null;
setContentView(viewStart);
break;
}
return true;
}
private PictureCallback jpegCallback = new PictureCallback(){
//
public void onPictureTaken(byte[] data, Camera camera) {
try {
String name = new DateFormat().format("yyyyMMdd_hhmmss",
Calendar.getInstance(Locale.CHINA)) + ".jpg";
FileOutputStream fileout = new FileOutputStream("/mnt/sdcard/sdcard/DCIM/"+ name);
System.out.println(name);
fileout.write(data,0,data.length);
fileout.flush();
fileout.close();
} catch (IOException e) {
// TODO: handle exception
System.out.println(e);
}
}
};
class Preview extends SurfaceView implements SurfaceHolder.Callback
{
Preview(Context context)
{
super(context);
mHolder=getHolder();
mHolder.addCallback(this);
mHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
public void surfaceCreated(SurfaceHolder holder)
{
mCamera=Camera.open();
try
{
mCamera.setPreviewDisplay(holder);
}
catch(IOException exception)
{
mCamera.release();
mCamera=null;
}
}
public void surfaceDestroyed(SurfaceHolder holder)
{
mCamera.stopPreview();
mCamera.release();
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int w, int h) {
// TODO Auto-generated method stub
Camera.Parameters parameters=mCamera.getParameters();
parameters.setPictureFormat(PixelFormat.JPEG);
parameters.setPreviewSize(1024, 1024);
mCamera.setParameters(parameters);
mCamera.setDisplayOrientation(90);
mCamera.startPreview();
}
}
}
更多關(guān)于Android相關(guān)內(nèi)容感興趣的讀者可查看本站專題:《Android文件操作技巧匯總》、《Android編程開發(fā)之SD卡操作方法匯總》、《Android開發(fā)入門與進階教程》、《Android資源操作技巧匯總》、《Android視圖View技巧總結(jié)》及《Android控件用法總結(jié)》
希望本文所述對大家Android程序設(shè)計有所幫助。
相關(guān)文章
Android App端與PHP Web端的簡單數(shù)據(jù)交互實現(xiàn)示例
本篇文章主要介紹了Android App端與PHP Web端的簡單數(shù)據(jù)交互實現(xiàn)示例,詳細的介紹了交互的代碼,非常具有實用價值,有興趣的可以了解一下2017-10-10
Android顏色處理SweepGradient掃描及梯度渲染示例
這篇文章主要為大家介紹了Android顏色處理SweepGradient掃描渲染及梯度渲染示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2022-06-06
android開發(fā)基礎(chǔ)教程—文件存儲功能實現(xiàn)
文件存儲功能在實現(xiàn)數(shù)據(jù)讀寫時會頻繁使用到,接下來介紹文件存儲功能的實現(xiàn),感興趣的朋友可以了解下2013-01-01
Android如何使用GestureDetector進行手勢檢測詳解
GestureDetector使用很方便,提供了單擊,雙擊,長按等操作的處理,但是一般的定義界面都比較復雜,還用很多需要注意的地方,這篇文章主要給大家介紹了關(guān)于Android如何使用GestureDetector進行手勢檢測的相關(guān)資料,需要的朋友可以參考下2022-01-01
Android動態(tài)修改應(yīng)用圖標與名稱的方法實例
這篇文章主要給大家介紹了關(guān)于Android動態(tài)修改應(yīng)用圖標與名稱的相關(guān)資料,文中通過示例代碼介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2019-01-01

