Android 使Camera預覽清晰,迴圈自動對焦處理
阿新 • • 發佈:2019-02-15
我們經常使用SurfaceView顯示Camera預覽畫面,但畫面基本都不清晰。主要是因為沒有自動對焦,而自動對焦觸發是通過mCamera.autoFocus(autoFocusCallback);這個函式,但是隻會起一次作用,後面畫面清晰度有一直這樣,但是隨著拍攝目標的距離變化,這個畫面不在清晰,需要再次對焦。所以我這裡主要通過迴圈自動對焦來完成。
SurfaceView如何顯示Camera預覽畫面,這個我不多說
SurfaceView如何顯示Camera預覽畫面,這個我不多說
建立一個Handler用來觸發自動對焦
然後我們如果要呼叫autoFocus函式,就需要例項化AutoFocusCallback,然後我們在他自動對焦返回結果的函式裡,新增呼叫handler延遲1.3秒來觸發自動對焦handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.v("zzw",""+msg.what); switch (msg.what){ case MSG_AUTOFUCS: mCamera.autoFocus(autoFocusCallback); break; } } };
final class AutoFocusCallback implements Camera.AutoFocusCallback { private static final String TAG = AutoFocusCallback.class.getName(); private static final long AUTO_FOCUS_INTERVAL_MS = 1300L; //自動對焦時間 private Handler mAutoFocusHandler; private int mAutoFocusMessage; void setHandler(Handler autoFocusHandler, int autoFocusMessage) { this.mAutoFocusHandler = autoFocusHandler; this.mAutoFocusMessage = autoFocusMessage; } @Override public void onAutoFocus(boolean success, Camera camera) { Log.v("zzw", "autof focus "+success); if (mAutoFocusHandler != null) { mAutoFocusHandler.sendEmptyMessageDelayed(mAutoFocusMessage,AUTO_FOCUS_INTERVAL_MS); // mAutoFocusHandler = null; } else { Log.v(TAG, "Got auto-focus callback, but no handler for it"); } } }
所以我們在Activity的onCreate裡還需要將handler和msg.what編號給AutoFocusCallback
autoFocusCallback = new AutoFocusCallback();
autoFocusCallback.setHandler(handler,MSG_AUTOFUCS);
以下是Activity的完整程式碼
public class TwoActivity extends Activity implements SurfaceHolder.Callback{ private static final String TAG = "ChrisAcvitity"; private Camera mCamera; private SurfaceHolder mHolder; private SurfaceView mView; private static final int MSG_AUTOFUCS = 1001; private Handler handler; AutoFocusCallback autoFocusCallback; @Override // 建立Activity時執行的動作 protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_two); mView = (SurfaceView) findViewById(R.id.sv); mHolder = mView.getHolder(); mHolder.addCallback(this); handler = new Handler(){ @Override public void handleMessage(Message msg) { Log.v("zzw",""+msg.what); switch (msg.what){ case MSG_AUTOFUCS: mCamera.autoFocus(autoFocusCallback); break; } } }; autoFocusCallback = new AutoFocusCallback(); autoFocusCallback.setHandler(handler,MSG_AUTOFUCS); } @Override // apk暫停時執行的動作:把相機關閉,避免佔用導致其他應用無法使用相機 protected void onPause() { super.onPause(); handler.removeCallbacksAndMessages(null); mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } @Override // 恢復apk時執行的動作 protected void onResume() { super.onResume(); if (null!=mCamera){ mCamera = getCameraInstance(); try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); } catch(IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } } // SurfaceHolder.Callback必須實現的方法 public void surfaceCreated(SurfaceHolder holder){ mCamera = getCameraInstance(); try { mCamera.setPreviewDisplay(holder); mCamera.startPreview(); } catch(IOException e) { Log.d(TAG, "Error setting camera preview: " + e.getMessage()); } } // SurfaceHolder.Callback必須實現的方法 public void surfaceChanged(SurfaceHolder holder, int format, int width, int height){ refreshCamera(); // 這一步是否多餘?在以後複雜的使用場景下,此步驟是必須的。 int rotation = getDisplayOrientation(); //獲取當前視窗方向 mCamera.setDisplayOrientation(rotation); //設定相機顯示方向 } // SurfaceHolder.Callback必須實現的方法 public void surfaceDestroyed(SurfaceHolder holder){ mHolder.removeCallback(this); if(mCamera != null){ mCamera.setPreviewCallback(null); mCamera.stopPreview(); mCamera.release(); mCamera = null; } } // === 以下是各種輔助函式 === // 獲取camera例項 public static Camera getCameraInstance(){ Camera c = null; try { c = Camera.open(); } catch(Exception e){ Log.d("TAG", "camera is not available"); } return c; } // 獲取當前視窗管理器顯示方向 private int getDisplayOrientation(){ WindowManager windowManager = getWindowManager(); Display display = windowManager.getDefaultDisplay(); int rotation = display.getRotation(); int degrees = 0; switch (rotation){ case Surface.ROTATION_0: degrees = 0; break; case Surface.ROTATION_90: degrees = 90; break; case Surface.ROTATION_180: degrees = 180; break; case Surface.ROTATION_270: degrees = 270; break; } android.hardware.Camera.CameraInfo camInfo = new android.hardware.Camera.CameraInfo(); android.hardware.Camera.getCameraInfo(Camera.CameraInfo.CAMERA_FACING_BACK, camInfo); // 這裡其實還是不太懂:為什麼要獲取camInfo的方向呢?相當於相機標定?? int result = (camInfo.orientation - degrees + 360) % 360; return result; } // 重新整理相機 private void refreshCamera(){ if (mHolder.getSurface() == null){ // preview surface does not exist return; } // stop preview before making changes try { mCamera.stopPreview(); } catch(Exception e){ // ignore: tried to stop a non-existent preview } // set preview size and make any resize, rotate or // reformatting changes here // start preview with new settings try { mCamera.setPreviewDisplay(mHolder); mCamera.startPreview(); mCamera.autoFocus(autoFocusCallback); } catch (Exception e) { } } }
還有許可權
<uses-permission android:name="android.permission.CAMERA" />
<uses-feature android:name="android.hardware.camera" />
<uses-feature android:name="android.hardware.camera.autofocus" />