前言
感謝來自世界各地的朋友分享的技術(shù)經(jīng)驗(yàn)括授。本文主要講述一下在開發(fā)中針對camera所遇到的坑和重點(diǎn)坞笙,在這里和大家分享一下,希望不對的地方大家能夠指出荚虚。
本文闡述的順序是以本人封裝的類進(jìn)行說明以方法為單位薛夜。
傳入SurfaceView
由于SurfaceView
在創(chuàng)建預(yù)覽的時候 存在異步。所以我們將初始化相機(jī)的這個步驟放在這個回調(diào)中來
當(dāng)然版述,初始化相機(jī)的這個方式可以根據(jù)你的業(yè)務(wù)場景梯澜。核心就是避免在沒有畫面的問題。
有一點(diǎn)要注意:你要在你獲取了相機(jī)權(quán)限之后渴析,再初始化相機(jī)晚伙,否則會造成首次開始時無法獲取預(yù)覽畫面的問題吮龄。預(yù)覽被創(chuàng)建了,但是你的相機(jī)還沒有開啟咆疗。
這個方法中的重寫的三個方法的時機(jī)分別是:
public void setCameraSetting(SurfaceView surfaceView) {
surfaceView.getHolder().addCallback(new SurfaceHolder.Callback() {
@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
/**
* 預(yù)覽畫面可見時調(diào)用
* 初始化相機(jī)
*/
initCamera(surfaceHolder);
}
@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int format, int width, int height) {
/*
* 預(yù)覽畫面改變時時調(diào)用
*
*/
}
@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
/**
* 預(yù)覽畫面不可見時調(diào)用
* 釋放相機(jī)
* 如果在這個位置進(jìn)行相機(jī)的釋放漓帚,那么伴隨著你切換后臺,頁面被殺死等等午磁。都會將相機(jī)釋放
*/
releaseCamera();
}
});
}
初始化相機(jī)
private void initCamera() {
try {
if (mCamera != null) {
releaseCamera();
}
//該方法 通常等同于 Camera.open(0) , 不過在某些特殊的設(shè)備上,此說法并不成立
//相機(jī)要在這個中直接初始化,如果你采用了一些其它的寫法,比如將相機(jī)作為參數(shù)在外界初始化好了之后傳進(jìn)來,就會出現(xiàn)問題.
mCamera = Camera.open();
if (mCamera == null) {
//這說明 沒有可以被打開的相機(jī)
Log.d(TAG, "Error not camera");
return;
}
//配置CameraParams
Camera.Parameters params = mCamera.getParameters();
//獲取預(yù)覽尺寸集合(部分機(jī)型該集合為空)尝抖,升序
List<Camera.Size> supportedPreviewSizes = params.getSupportedPreviewSizes();
//獲取視頻分辨率集合 (部分機(jī)型該參數(shù)會為空)
List<Camera.Size> supportedVideoSizes = params.getSupportedVideoSizes();
/**
* 設(shè)置相機(jī)的橫豎屏(豎屏需要旋轉(zhuǎn)90°)
* mCamera.setDisplayOrientation(90) 這個參數(shù)要靈活使用,根據(jù)真機(jī)來進(jìn)行對相機(jī)畫面的旋轉(zhuǎn)迅皇。
* 有部分真機(jī)可能是 270 或者是 無需旋轉(zhuǎn)的
*/
if (context.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE) {
params.set("orientation", "portrait");
mCamera.setDisplayOrientation(90);
} else {
params.set("orientation", "landscape");
mCamera.setDisplayOrientation(0);
}
/**
* 設(shè)置對焦模式
* 注意:如果你開啟的是 非默認(rèn)相機(jī) 也就是說 Camera.open(0+) 要小心使用
* 如果你開啟的相機(jī)不支持對焦功能昧辽!那么將會報錯!
*
*/
params.setFocusMode(Camera.Parameters.FOCUS_MODE_CONTINUOUS_VIDEO);
mCamera.setParameters(params);
} catch (Exception e) {
//有的手機(jī)會因?yàn)榧嫒輪栴}報錯登颓,這就需要開發(fā)者針對特定機(jī)型去做適配了
Log.d(TAG, "Error starting camera preview: " + e.getMessage());
}
}
這里要重點(diǎn)說明一方法 params.setPreviewSize()
這個方法有個坑搅荞!這個方法中所需要的的參數(shù)是上述 supportedPreviewSizes
集合中的參數(shù)
如果不設(shè)置默認(rèn)會取上述集合中的最大值
但是如果你設(shè)置了!你一定要考慮適配方面的問題框咙,因?yàn)槟闼O(shè)置的參數(shù)一定要是相機(jī)支持的取具,換而言之,你設(shè)置的參數(shù)必須是上述 集合中的其中一條扁耐。如果是不支持的暇检,將會沒有預(yù)覽畫面
釋放相機(jī)
釋放攝像頭資源
重點(diǎn)說明:如果項(xiàng)目中涉及到反復(fù)開啟攝像機(jī)的操作,一定要在釋放相機(jī)是進(jìn)行鎖定
我們租用了一塊場地婉称,場館人員將門打開讓你布置場地块仆,我們使用完的場地要手動將人家的門關(guān)上!(部分真機(jī)測試王暗,可以忽略lock()這行代碼悔据。PS:自動門。俗壹。科汗。)
public void releaseCamera() {
if (mCamera != null) {
// mCamera.unlock(); //致命傷:錯誤的釋放方式 不可以在這里添加這行代碼
mCamera.lock();
mCamera.setPreviewCallback(null);
mCamera.stopPreview();
mCamera.release();
mCamera = null;
}
}