SurfaceView顯示Camera拍攝的畫面

一般情況下,可以使用MediaRecorder來錄製視頻,視頻數據也可在SurfaceView上顯示,但是那要寫數據到存儲設備上。而且我們項目是視頻聊天,就不能使用Media了。

網上找了找資料,自己給改了下:


public class CameravedioActivity extends Activity{
	
	private static final String TAG = "CameravedioActivity";
	private Camera camera; 
    private boolean preview  = false ;
    private SeekBar mSeekBar;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        
       /*
        *設置窗口屬性:一定要在 setContentView(R.layout.main) 之前
        */
// 窗口標題,其實可以在manifes文件裏面註冊
//     requestWindowFeature(Window.FEATURE_NO_TITLE);
// 全屏 
       getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);
       setContentView(R.layout.main);
       SurfaceView surfaceView =  (SurfaceView) findViewById(R.id.surfaceView);
       surfaceView.getHolder().setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
       surfaceView.getHolder().setFixedSize(200, 200);
       surfaceView.getHolder().addCallback(new SurfaceViewCallback());
       
       /**
        * seekbar 用來實現變焦邏輯
        */
       mSeekBar = (SeekBar)findViewById(R.id.seekbar);
       mSeekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener(){

		@Override
		public void onProgressChanged(SeekBar seekBar, int progress,
				boolean fromUser) {
			// TODO Auto-generated method stub
			Log.d(TAG, "progress:"+progress);
		}

		@Override
		public void onStartTrackingTouch(SeekBar seekBar) {
			// TODO Auto-generated method stub
			Log.d(TAG, "onStartTrackingTouch");
		}

		@Override
		public void onStopTrackingTouch(SeekBar seekBar) {
			// TODO Auto-generated method stub
			Log.d(TAG, "onStartTrackingTouch");
		}
    	   
       });
    }
	
	private final class SurfaceViewCallback implements Callback {
		/**
		 * surfaceView 被創建成功後調用此方法
		 */
		@Override
		public void surfaceCreated(SurfaceHolder holder) {
			Log.d(TAG,"surfaceCreated");
			/* 
			 * 在SurfaceView創建好之後 打開攝像頭
			 * 注意是 android.hardware.Camera
			 */
			camera = Camera.open();
			/*
			 * This method must be called before startPreview(). otherwise surfaceview沒有圖像
			 */
			try {
				camera.setPreviewDisplay(holder);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
			
			Camera.Parameters parameters = camera.getParameters();
			/* 設置預覽照片的大小,此處設置爲全屏 */
//			WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE); // 獲取當前屏幕管理器對象
//			Display display = wm.getDefaultDisplay();      				     // 獲取屏幕信息的描述類
//			parameters.setPreviewSize(display.getWidth(), display.getHeight());          // 設置
			parameters.setPreviewSize(200, 200); 
			/* 每秒從攝像頭捕獲5幀畫面, */
			parameters.setPreviewFrameRate(5);
			/* 設置照片的輸出格式:jpg */
			parameters.setPictureFormat(PixelFormat.JPEG);
			/* 照片質量 */
			parameters.set("jpeg-quality", 85);
			/* 設置照片的大小:此處照片大小等於屏幕大小 */
//			parameters.setPictureSize(display.getWidth(), display.getHeight());
			parameters.setPictureSize(200, 200);
			/* 將參數對象賦予到 camera 對象上 */
//			camera.setParameters(parameters);
			mSeekBar.setMax(100);
			camera.startPreview();
			/**
			 * Installs a callback to be invoked for every preview frame in addition to displaying them on the screen. 
			 * The callback will be repeatedly called for as long as preview is active. This method can be called at 
			 * any time, even while preview is live. Any other preview callbacks are overridden.
			 * a callback object that receives a copy of each preview frame, or null to stop receiving 
			 */
			camera.setPreviewCallback(new Camera.PreviewCallback(){

				@Override
				public void onPreviewFrame(byte[] data, Camera camera) {
					// TODO Auto-generated method stub
				    //在視頻聊天中,這裏傳送本地frame數據給remote端
					Log.d(TAG, "camera:"+camera);
					Log.d(TAG, "byte:"+data);
				}
				
			});
			preview = true;
		}
		@Override
		public void surfaceChanged(SurfaceHolder holder, int format, int width,
				int height) {
			Log.d(TAG,"surfaceChanged");
		}
		/**
		 * SurfaceView 被銷燬時釋放掉 攝像頭
		 */
		@Override
		public void surfaceDestroyed(SurfaceHolder holder) {
			if(camera != null) {
				/* 若攝像頭正在工作,先停止它 */
				if(preview) {
					camera.stopPreview();
					preview = false;
				}
				//如果註冊了此回調,在release之前調用,否則release之後還回調,crash
				camera.setPreviewCallback(null);
				camera.release();
			}
		}
		
	}
	
	
	/**
	 * 處理照片被拍攝之後的事件
	 */
	private final class TakePictureCallback implements PictureCallback {
		@Override
		public void onPictureTaken(byte[] data, Camera camera) {
		}
	}
}


main.xml:

<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    >
    <LinearLayout
    	android:layout_width="fill_parent"
    	android:layout_height="fill_parent"
    	android:orientation="vertical"
    >
		<SurfaceView 
			android:id="@+id/surfaceView"
		    android:layout_width="300dip" 
		    android:layout_height="300dip" 
		    android:visibility="visible"
	    />
	    <LinearLayout
	    	android:layout_width="fill_parent"
	    	android:layout_height="wrap_content"
    	>
    		<SeekBar
    			android:id="@+id/seekbar"
    			android:layout_width="fill_parent"
	    		android:layout_height="wrap_content"
    		/>
    	</LinearLayout>
    </LinearLayout>
</FrameLayout>
我在自己機器上測試surfaceview必須包含在FrameLayout中

manifest文件:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="cn.edu.wtu"
      android:versionCode="1"
      android:versionName="1.0">
    <application android:icon="@drawable/icon" android:label="@string/app_name">
    	<!-- android:screenOrientation="landscape" 表示橫向界面 -->
        <activity android:name=".CameravedioActivity" android:label="@string/app_name"  android:screenOrientation="portrait">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>
    <uses-sdk android:minSdkVersion="7" />
    <!-- 在SDCard中創建與刪除文件權限 -->
	<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
	<!-- 往SDCard寫入數據權限 -->
	<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
    <!-- 申請使用攝像頭的權限 -->
	<uses-permission android:name="android.permission.CAMERA"/>
</manifest>
注意哦,有些手機是不支持變焦的,所以設置Camera的Parameter會crash,所以要實現變焦邏輯首先判斷手機是否支持smoothzoom

sdk 2.1還是不支持setZoom的,2.3.3可以,2.2沒有測試




發佈了213 篇原創文章 · 獲贊 21 · 訪問量 72萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章