Android如何呼叫攝像頭

夢_之_旅發表於2013-04-15

我們要呼叫攝像頭的拍照功能,顯然

第一步必須加入呼叫攝像頭硬體的許可權,拍完照後我們要將圖片儲存在SD卡中,必須加入SD卡讀寫許可權,所以第一步,我們應該在Android清單檔案中加入以下程式碼

<uses-permission android:name="android.permission.CAMERA"/>//攝像頭許可權

SD卡讀寫許可權

<uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

<uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

第二步,要將攝像頭捕獲的影像實時地顯示在手機上。

我們是用SurfaceView這個檢視元件來實現的,因此在main.xml中加入下列程式碼

<SurfaceView

android:layout_width="fill_parent"

android:layout_height="fill_parent"

android:id="@+id/surfaceview"

/>

第三步,設定視窗的顯示方式

首先獲得當前視窗Windowwindow = getWindow();//得到視窗

接著設定沒有標題requestWindowFeature(Window.FEATURE_NO_TITLE);//沒有標題

接著設定全屏 window.setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

WindowManager.LayoutParams.FLAG_FULLSCREEN);//設定全屏

當然,我們在拍照過程中,螢幕必須一致處於高亮狀態,因此接著加入下面程式碼

window.addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);//設定高亮

至此,我們將視窗的顯示方式規定死了,然後才能設定視窗上顯示的元件(順序非常重要)

setContentView(R.layout.main);

第四步,設定SurficeView顯示控制元件的屬性

找到surficeView

surfaceView = (SurfaceView)findViewById(R.id.surfaceview);

設定它的畫素為800x600

surfaceView.getHolder().setFixedSize(800,480);

//下面設定surfaceView不維護自己的緩衝區,而是等待螢幕的渲染引擎將內容推送到使用者面前

surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

第五步,就是為surficeView加入回撥方法(callBack)

surfaceView.getHolder().addCallback(newSurfaceCallback());

上面的回撥類是我們自己定義的,程式碼如下

private class SurfaceCallback implementsSurfaceHolder.Callback{

@Override

public void surfaceCreated(SurfaceHolderholder) {

try {

camera = Camera.open();//開啟硬體攝像頭,這裡導包得時候一定要注意是android.hardware.Camera

WindowManager wm = (WindowManager)getSystemService(Context.WINDOW_SERVICE);//得到視窗管理器

Display display = wm.getDefaultDisplay();//得到當前螢幕

Camera.Parameters parameters =camera.getParameters();//得到攝像頭的引數

parameters.setPreviewSize(display.getWidth(),display.getHeight());//設定預覽照片的大小

parameters.setPreviewFrameRate(3);//設定每秒3

parameters.setPictureFormat(PixelFormat.JPEG);//設定照片的格式

parameters.setJpegQuality(85);//設定照片的質量

parameters.setPictureSize(display.getHeight(),display.getWidth());//設定照片的大小,預設是和螢幕一樣大

camera.setParameters(parameters);

camera.setPreviewDisplay(surfaceView.getHolder());//通過SurfaceView顯示取景畫面

camera.startPreview();//開始預覽

isPreview = true;//設定是否預覽引數為真

} catch (IOException e) {

Log.e(TAG, e.toString());

}

}

 

@Override

public void surfaceChanged(SurfaceHolderholder, int format, int width,

int height) {

// TODO Auto-generated method stub

}

@Override

public void surfaceDestroyed(SurfaceHolderholder) {

if(camera!=null){

if(isPreview){//如果正在預覽

camera.stopPreview();

camera.release();

}

}

}

}

第六步,我們必須對按鍵事件進行監聽,如是拍照還是聚焦,程式碼如下

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;//阻止事件往下傳遞,否則按搜尋鍵會變成系統預設的

}

------------------------------------------------------------------------------------------

private final class TakePictureCallbackimplements PictureCallback{

public void onPictureTaken(byte[] data,Camera camera) {

try {

Bitmap bitmap =BitmapFactory.decodeByteArray(data, 0, data.length);

File file = newFile(Environment.getExternalStorageDirectory(),System.currentTimeMillis()+".jpg");

FileOutputStream outputStream = newFileOutputStream(file);

bitmap.compress(CompressFormat.JPEG, 100,outputStream);

outputStream.close();

camera.stopPreview();

camera.startPreview();//處理完資料之後可以預覽

} catch (Exception e) {

Log.e(TAG, e.toString());

}

}

}

注意,程式碼中有兩個回撥類,一個是SurfaceCallback(),另外一個是TakePictureCallback(),初學者可能一時難以理解,通俗地講,前者是用來監視surficeView這個暫時存放圖片資料的顯示控制元件的,根據它的顯示情況呼叫不同的方法,包括surfaceCreated(),surfaceChanged(),surfaceDestroyed(),也就不難理解為什麼會有這三個回撥方法了(注意,在surfaceDestroyed()方法中必須釋放攝像頭,詳細程式碼參見上方)TakePictureCallback()是為了監視是否拍照而設計的介面,期中也僅有一個方法,camera將拍照得到的資料傳入方法,我們便可以對拍照得到的資料進行進一步處理了。

相關文章