除了手機錄制音/視頻外,手機拍照也已經(jīng)不是什么新鮮事了,Android相應(yīng)地提供了手機拍照功能API。要使用Android系統(tǒng)進行拍照,使用到的類有很多。具體介紹如下。
□ SurfaceView:該類是一個視圖組件,實現(xiàn)了照片的預(yù)覽功能。
□ SurfaceHolder:一個抽象接口,是SurfaceView的支持類,一般通過SurfaceView的getHolder()方法獲得。允許你控制界面的尺寸和格式、編輯界面的像素,以及監(jiān)控界面尺寸的改變。
□ SurfaceHolder.Callback:SurfaceHolder的一個內(nèi)部接口,可以實現(xiàn)該接口獲取界面改變的信息。該接口中有三個方法,surfaceCreated()方法在界面創(chuàng)建時被調(diào)用,一般在該方法中打開照相機并設(shè)置預(yù)覽。surfaceChanged()方法在界面尺寸改變時被調(diào)用,一般在該方法中設(shè)置相機的參數(shù)(大小、格式等)。surfaceDestroyed()方法在界面被銷毀時調(diào)用,在該方法中清除相機實例,釋放資源。
□ Camera:相機類,實現(xiàn)拍照功能。
□ Camera.PictureCallback:Camera的一個內(nèi)部接口,處理照片準(zhǔn)備好后的回調(diào)。
通過上面類的介紹,可以實現(xiàn)一個拍照程序了。下面是程序的實現(xiàn)步驟。
(1)創(chuàng)建一個Android工程“Camera”,在該工程的“com.example”包中,創(chuàng)建一個MainActivity類,在該類的頂部聲明SurfaceView、SurfaceHolder和Camera對象,代碼如代碼清單1所示。
代碼清單1 MainActivity類中聲明對象
package com.example;
import android.app.Activity;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MainActivity extends Activity {
//聲明拍照界面組件SurfaceView
private SurfaceView surfaceView;
//聲明界面控制組件SurfaceHolder
private SurfaceHolder surfaceHolder;
//聲明照相機
private Camera camera;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
//設(shè)置當(dāng)前Activity界面布局
setContentView(R.layout.main);
}
}
(2)在該工程res\layout\目錄下的布局文件main.xml中添加SurfaceView視圖組件。代碼如代碼清單2所示。
代碼清單2 main.xml中添加SurfaceView視圖組件
<?xml version=”1.0” encoding=”utf-8”?>
<SurfaceView xmlns:android=”//schemas.android.com/apk/res/android”
android:id=”@+id/preview”
android:layout_width=”fill_parent”
android:layout_height=”fill_parent”>
</SurfaceView>
(3)在onCreate()方法中獲得SurfaceView和SurfaceHolder實例對象。代碼如代碼清單3所示。
代碼清單3 onCreate()獲取SurfaceView、SurfaceHolder實例對象
//實例化拍照界面組件
surfaceView = (SurfaceView) findViewById(R.id.preview);
//從SurfaceView中獲得SurfaceHolder
surfaceHolder=surfaceView.getHolder();
(4)實現(xiàn)SurfaceHolder.Callback回調(diào)接口,實現(xiàn)該接口中的3個方法。代碼如代碼清單4所示。
代碼清單4 實現(xiàn)SurfaceHolder.Callback回調(diào)接口
SurfaceHolder.Callback surfaceCallback = new SurfaceHolder.Callback() {
@Override
public void surfaceDestroyed(SurfaceHolder holder) {
//停止預(yù)覽
camera.stopPreview();
//釋放相機資源
camera.release();
camera=null;
}
@Override
public void surfaceCreated(SurfaceHolder holder) {
//打開相機
camera = Camera.open();
try{
//設(shè)置預(yù)覽
camera.setPreviewDisplay(holder);
}catch(IOException e){
e.printStackTrace();
}
}
@Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
//獲得相機參數(shù)
Camera.Parameters parameters = camera.getParameters();
//設(shè)置相片大小
parameters.setPictureSize(width, height);
//設(shè)置照片格式
parameters.setPictureFormat(PixelFormat.JPEG);
//開始預(yù)覽
camera.startPreview();
}
};
(5)為SurfaceHolder添加回調(diào),并設(shè)置其類型。代碼如代碼清單5所示。
代碼清單5 為SurfaceHolder添加回調(diào)
surfaceHolder.addCallback(surfaceCallback);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
(6)創(chuàng)建一個保存照片任務(wù)類,該類的主要功能是將從硬件獲得的字節(jié)流保存到設(shè)備中。代碼如代碼清單6所示。
代碼清單6 創(chuàng)建保存照片任務(wù)類
public class SavePictureTask extends AsyncTask<byte[], String, String> {
@Override
protected String doInBackground(byte[]... params) {
// TODO Auto-generated method stub
//創(chuàng)建文件
File picture = new File(Environment.getExternalStorageDirectory(),
"picture.jpg");
//如果文件存在,刪除現(xiàn)存文件
if(picture.exists())
picture.delete();
try{
//獲取文件輸出流
FileOutputStream fos = new
FileOutputStream(picture.getParent());
//寫到該文件
fos.write(params[0]);
//關(guān)閉文件流
fos.close();
}catch(Exception e){
e.printStackTrace();
}
return null;
}
}
(7)實現(xiàn)Camera.PictureCallBack回調(diào)方法,執(zhí)行保存照片任務(wù)。代碼如代碼清單7所示。
代碼清單7 實現(xiàn)Camera.PictureCallBack回調(diào)方法
//照片回調(diào)
Camera.PictureCallback pictureCallback = new Camera.PictureCallback() {
@Override
(8)創(chuàng)建保存照片方法。代碼如代碼清單8所示。
代碼清單8 創(chuàng)建保存照片方法
public void onPictureTaken(byte[] data, Camera camera) {
new SavePictureTask().execute(data);
camera.startPreview();
}
};
(9)相應(yīng)按鍵事件,當(dāng)拍照鍵或搜索鍵被按下時進行拍照。代碼如代碼清單9所示。
代碼清單9 相應(yīng)按鍵事件
//相應(yīng)按鍵事件
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if(keyCode==KeyEvent.KEYCODE_CAMERA||
keyCode==KeyEvent.KEYCODE_SEARCH){
takePic();
return true;
}
return super.onKeyDown(keyCode, event);
}