一般情況下,可以使用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(){@Overridepublic void onProgressChanged(SeekBar seekBar, int progress,boolean fromUser) {// TODO Auto-generated method stubLog.d(TAG, "progress:"+progress);}@Overridepublic void onStartTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stubLog.d(TAG, "onStartTrackingTouch");}@Overridepublic void onStopTrackingTouch(SeekBar seekBar) {// TODO Auto-generated method stubLog.d(TAG, "onStartTrackingTouch");} }); }private final class SurfaceViewCallback implements Callback {/** * surfaceView 被建立成功後調用此方法 */@Overridepublic 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 blocke.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(){@Overridepublic 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;}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width,int height) {Log.d(TAG,"surfaceChanged");}/** * SurfaceView 被銷毀時釋放掉 網路攝影機 */@Overridepublic void surfaceDestroyed(SurfaceHolder holder) {if(camera != null) {/* 若網路攝影機正在工作,先停止它 */if(preview) {camera.stopPreview();preview = false;}//如果註冊了此回調,在release之前調用,否則release之後還回調,crashcamera.setPreviewCallback(null);camera.release();}}}/** * 處理照片被拍攝之後的事件 */private final class TakePictureCallback implements PictureCallback {@Overridepublic 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沒有測試