Android實時監控專案第三篇:通過攝像頭實時預覽幀視訊
在第二個Activity中,我們要顯示攝像頭預覽的視訊,佈局檔案很簡單,就一個SurfaceView元件,設定為佔滿整個父元件(這裡不再給出),用來顯示預覽的視訊。
在對應的Activity檔案中,要獲取SurfaceView的SurfaceHolder,併為其新增一個回撥監聽器,該監聽器傳入一個Callback例項,這裡需要覆寫Callback例項中的三個方法,分別是:
public void surfaceCreated(SurfaceHolder holder)方法,當開啟攝像頭時,該方法被回撥;
public void surfaceChanged(SurfaceHolder holder)方法,當SurfaceView預覽介面的格式或大小發生改變時,該方法被回撥;
public void surfaceDestroyed(SurfaceHolder holder)方法,當SurfaceView被銷燬時,該方法被回撥;
在surfaceCreated方法中通過私有方法initCreama()對攝像頭各項引數進行初始化,主要是設定預覽視訊的尺寸,每秒顯示的幀數等,設定完引數後,通過setParameters(Camera.Parameters parameters)方法顯示取景畫面,即預覽視訊。在開始預覽前,呼叫setPreviewCallback(PreviewCallback cb)方法來獲取採集到的預覽視訊流資料,從而可以對其進行處理,這一點將在下篇中詳細講解。在開始預覽之後,還要設定自動對焦,不然攝像頭採集到的影象不清晰。
另外,這裡有兩點需要注意:
1、每臺手機的攝像頭所支援的影象預覽或拍攝尺寸不盡相同,如果設定的影象尺寸,攝像頭不支援,則會出錯,因此在真機上測試前,先要確定攝像頭支援哪些尺寸,具體的方法很簡單,這裡不再給出,需要了解的可以參考這篇文章:http://blog.csdn.net/yanzi1225627/article/details/7738736;
2、要編寫橫豎屏鏡頭自動調整的程式碼,否則預覽的影象將是左右顛倒的。
該檔案詳細程式碼如下:
- package zyb.org.camera;
- import java.io.IOException;
-
import android.app.Activity;
- import android.content.Intent;
- import android.content.res.Configuration;
- import android.hardware.Camera;
- import android.os.Bundle;
- import android.util.DisplayMetrics;
- import android.view.SurfaceHolder;
- import android.view.SurfaceHolder.Callback;
- import android.view.SurfaceView;
- publicclass CameraActivity extends Activity {
- private SurfaceView sView = null;
- private String ipName = null;
- private SurfaceHolder sHolder = null;
- privateint screenWidth;
- privateint screenHeight;
- private Camera camera = null;
- privateboolean isPreview = false;
- public Camera getCamera() {
- return camera;
- }
- @Override
- protectedvoid onCreate(Bundle savedInstanceState) {
- super.onCreate(savedInstanceState);
- setContentView(R.layout.activity_camera);
- //從上個Activity中獲取傳遞過來的資料
- Intent intent = getIntent();
- ipName = intent.getStringExtra("ipname");
- //獲取螢幕的寬和高
- DisplayMetrics dm = new DisplayMetrics();
- getWindowManager().getDefaultDisplay().getMetrics(dm);
- screenWidth = dm.widthPixels;
- screenHeight = dm.heightPixels;
- sView = (SurfaceView)findViewById(R.id.sView);
- sHolder = sView.getHolder();
- sHolder.addCallback(new Callback() {
- //釋放camera時,回撥該方法
- @Override
- publicvoid surfaceDestroyed(SurfaceHolder holder) {
- if(camera != null){
- camera.setPreviewCallback(null);
- if(isPreview)
- camera.stopPreview();
- camera.release();
- camera = null;
- }
- }
- //開啟攝像頭時,回撥該方法
- @Override
- publicvoid surfaceCreated(SurfaceHolder holder) {
- initCamera();
- }
- @Override
- publicvoid surfaceChanged(SurfaceHolder holder, int format, int width,
- int height) {
- // TODO Auto-generated method stub
- }
- });
- }
- /**
- * 初始化攝像頭各引數
- * */
- privatevoid initCamera(){
- if(!isPreview)
- camera = Camera.open();
- if(camera!=null && !isPreview){
- try {
- Camera.Parameters parameters = camera.getParameters();
- //每臺手機的攝像頭所支援的影象預覽或拍攝尺寸不盡相同,
- //如果設定的影象尺寸,攝像頭不支援,則會出錯,
- //因此在真機上測試前,先要確定攝像頭支援哪些尺寸
- parameters.setPreviewSize(screenWidth, screenHeight); //設定預覽影象的尺寸大小
- parameters.setPreviewFpsRange(10, 20); //設定每秒顯示10-20幀
- // 橫豎屏鏡頭自動調整
- if (this.getResources().getConfiguration().orientation != Configuration.ORIENTATION_LANDSCAPE){
- parameters.set("orientation", "portrait");
- parameters.set("rotation", 90); // 鏡頭角度轉90度(預設攝像頭是橫拍)
- camera.setDisplayOrientation(90); // 在2.2以上可以使用
- } else{
- // 如果是橫屏
- parameters.set("orientation", "landscape");
- camera.setDisplayOrientation(0); // 在2.2以上可以使用
- }
- camera.setPreviewDisplay(sHolder); //通過SurfaceView顯示取景畫面
- //回撥處理預覽視訊流類中的onPreviewFrame方法
- //在onPreviewFrame方法中,啟動傳送視訊流的執行緒
- camera.setPreviewCallback(new ViedoStream(ipName,CameraActivity.this));
- camera.startPreview(); //開始預覽
- camera.autoFocus(null); //自動對焦
- } catch (IOException e) {
- e.printStackTrace();
- }
- isPreview = true;
- }
- }
- }
下篇將講述後臺執行緒傳送預覽幀視訊的操作