1. 程式人生 > >用MediaRecoder類進行錄製視訊

用MediaRecoder類進行錄製視訊

與音訊的不同點是在視訊錄製中需要定義一個額外的SurfaceView元件,以捕獲攝像頭採集的資料。


(1)主程式

publicclass MyMediaRecorderDemo extends Activity {

    private ImageButton record = null;

    private ImageButton stop = null;

    private ImageButton browser = null;

    private TextView info = null;

    private MediaRecorder mediaRecorder = null;

    private boolean sdcardExists = false; // SD卡存在的標記

    private File recordVideoSaveFileDir = null;

    private File recordVideoSaveFile = null;

    private String recordVideoSaveFileName =null;

    private String recDir ="mldnvideo";

    private boolean isRecord = false;

    private SurfaceView surface = null;

 

    @Override

    public void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

        super.requestWindowFeature(Window.FEATURE_NO_TITLE);// 不顯示標題

        super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        super.getWindow().addFlags(

                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 高亮的風格顯示

        super.setContentView(R.layout.main);

        this.record = (ImageButton)super.findViewById(R.id.record);

        this.stop = (ImageButton) super.findViewById(R.id.stop);

        this.browser = (ImageButton)super.findViewById(R.id.browser);

        this.info = (TextView)super.findViewById(R.id.info);

        this.surface = (SurfaceView)super.findViewById(R.id.surface);

        this.surface.getHolder().setType(

                SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        this.surface.getHolder().setFixedSize(480,800);

        if ((this.sdcardExists =Environment.getExternalStorageState().equals(

                Environment.MEDIA_MOUNTED))) {

            this.recordVideoSaveFileDir = newFile(Environment

                    .getExternalStorageDirectory().toString()

                    + File.separator

                    +MyMediaRecorderDemo.this.recDir + File.separator); // 儲存資料夾

            if(!this.recordVideoSaveFileDir.exists()) {

                this.recordVideoSaveFileDir.mkdirs();// 建立資料夾

            }

        }

        this.record.setOnClickListener(newRecordOnClickListenerImpl()) ;

        this.stop.setOnClickListener(newStopOnClickListenerImpl()) ;

        this.browser.setOnClickListener(newBrowserOnClickListenerImpl()) ;

        this.stop.setEnabled(false) ;   // 停止錄象的按鈕暫時不可用

    }

    private class RecordOnClickListenerImplimplements OnClickListener {

        @Override

        public void onClick(View v) {

            if(MyMediaRecorderDemo.this.sdcardExists){ // sd卡存在

                MyMediaRecorderDemo.this.recordVideoSaveFileName= MyMediaRecorderDemo.this.recordVideoSaveFileDir

                        .toString()

                        + File.separator

                        + "MLDNVideo_"

                        +System.currentTimeMillis() + ".3gp";// 檔案的路徑名稱

                MyMediaRecorderDemo.this.recordVideoSaveFile= new File(

                        MyMediaRecorderDemo.this.recordVideoSaveFileName);//檔案路徑

                MyMediaRecorderDemo.this.mediaRecorder= new MediaRecorder() ;

                MyMediaRecorderDemo.this.mediaRecorder.reset();// 重置

                MyMediaRecorderDemo.this.mediaRecorder

                        .setAudioSource(MediaRecorder.AudioSource.MIC);

                MyMediaRecorderDemo.this.mediaRecorder

                        .setVideoSource(MediaRecorder.VideoSource.CAMERA);

                MyMediaRecorderDemo.this.mediaRecorder

                        .setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);

                MyMediaRecorderDemo.this.mediaRecorder

                .setVideoEncoder(MediaRecorder.VideoEncoder.H263);//定義視訊編碼

                MyMediaRecorderDemo.this.mediaRecorder

                .setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);//定義音訊編碼

                MyMediaRecorderDemo.this.mediaRecorder

                        .setOutputFile(MyMediaRecorderDemo.this.recordVideoSaveFileName);//定義輸出檔案

                MyMediaRecorderDemo.this.mediaRecorder.setVideoSize(320,240) ;

        MyMediaRecorderDemo.this.mediaRecorder.setVideoFrameRate(10);//每秒10

                MyMediaRecorderDemo.this.mediaRecorder

                        .setPreviewDisplay(MyMediaRecorderDemo.this.surface

                                .getHolder().getSurface());//定義視訊顯示

                try {

                    MyMediaRecorderDemo.this.mediaRecorder.prepare();

                } catch (Exception e) {

                    Log.i("MyMediaRecorderDemo",e.toString()) ;

                }

                MyMediaRecorderDemo.this.mediaRecorder.start();

                MyMediaRecorderDemo.this.info.setText("正在錄象中...") ;

                MyMediaRecorderDemo.this.stop.setEnabled(true);

                MyMediaRecorderDemo.this.record.setEnabled(false);

                MyMediaRecorderDemo.this.isRecord= true ;

            }

        }

    }

    private class StopOnClickListenerImplimplements OnClickListener {

        @Override

        public void onClick(View v) {

            if(MyMediaRecorderDemo.this.isRecord){

                MyMediaRecorderDemo.this.mediaRecorder.stop();

                MyMediaRecorderDemo.this.mediaRecorder.release();

                MyMediaRecorderDemo.this.stop.setEnabled(false);

                MyMediaRecorderDemo.this.record.setEnabled(true);

                MyMediaRecorderDemo.this.info.setText("錄象結束,檔案路徑為:"

                        +MyMediaRecorderDemo.this.recordVideoSaveFile);

            }

        }

    }

    private class BrowserOnClickListenerImplimplements OnClickListener {

        @Override

        public void onClick(View v) {

            Intent it = newIntent(MyMediaRecorderDemo.this,BroswerActivity.class) ;

            MyMediaRecorderDemo.this.startActivity(it);

        }

    }

    @Override

    public boolean onKeyDown(int keyCode,KeyEvent event) {

        if(keyCode == KeyEvent.KEYCODE_BACK) {//如果是手機上的返回鍵

            super.finish() ;//程式結束

        }

        return false ;

    }

   

}

(2)定義BrowserActivity程式完成ListView列表顯示
public class BroswerActivity extends Activity {

    private ImageButton back = null ;

    private ListView videolist = null ;

    private SimpleAdapter recordSimpleAdapter =null ;

    private List<Map<String,Object>>recordFiles = null ;

    private String recDir ="mldnvideo";

    private File recordVideoSaveFileDir = null;

    private boolean sdcardExists = false;

    @Override

    public void onCreate(Bundle savedInstanceState){

        super.onCreate(savedInstanceState);

        super.requestWindowFeature(Window.FEATURE_NO_TITLE);// 不顯示標題

        super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        super.getWindow().addFlags(

                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 高亮的風格顯示

        super.setContentView(R.layout.broswer);

        if ((this.sdcardExists =Environment.getExternalStorageState().equals(

                Environment.MEDIA_MOUNTED))) {

            this.recordVideoSaveFileDir = newFile(Environment

                    .getExternalStorageDirectory().toString()

                    + File.separator

                    +BroswerActivity.this.recDir + File.separator); // 儲存資料夾

            if(!this.recordVideoSaveFileDir.exists()) {

                this.recordVideoSaveFileDir.mkdirs();// 建立資料夾

            }

        }

        this.back = (ImageButton)super.findViewById(R.id.back) ;

        this.videolist = (ListView)super.findViewById(R.id.videolist) ;

        this.back.setOnClickListener(newBackOnClickListenerImpl()) ;

        this.getRecordFiles() ;

        this.videolist.setOnItemClickListener(newOnItemClickListenerImpl()) ;

    }

 

    private void getRecordFiles() {

        this.recordFiles = newArrayList<Map<String, Object>>();

        if(this.sdcardExists){

            File files [] =this.recordVideoSaveFileDir.listFiles() ;

            for (int x = 0; x < files.length;x++) {

                Map<String, Object>fileInfo = new HashMap<String, Object>();

                fileInfo.put("filename",files[x].getName()) ;

                this.recordFiles.add(fileInfo) ;

            }

            this.recordSimpleAdapter = newSimpleAdapter(this,

                    this.recordFiles,R.layout.recordfiles,

                    new String[] {"filename" }, new int[] { R.id.filename });

            this.videolist.setAdapter(this.recordSimpleAdapter);

        }

    }

   

    private class BackOnClickListenerImplimplements OnClickListener {

        @Override

        public void onClick(View v) {

            Intent it = newIntent(BroswerActivity.this,MyMediaRecorderDemo.class) ;

            BroswerActivity.this.startActivity(it);

        }

    }

    private class OnItemClickListenerImplimplements OnItemClickListener {

        @Override

        public voidonItemClick(AdapterView<?> adapter, View view, int position,

                long id) {

            if(BroswerActivity.this.recordSimpleAdapter.getItem(position) instanceof Map) {

                Map<?, ?> map = (Map<?,?>) BroswerActivity.this.recordSimpleAdapter

                        .getItem(position);

                Intent intent = new Intent(BroswerActivity.this,PlayVideoActivity.class);

                intent.putExtra("filepath",

                        BroswerActivity.this.recordVideoSaveFileDir.toString()

                                + File.separator

                                +map.get("filename").toString());

                BroswerActivity.this.startActivity(intent);

            }

        }

       

    }

}

(3)視訊播放程式

publicclass PlayVideoActivity extends Activity {

    private ImageButton play = null;

    private ImageButton stop = null;

    private ImageButton back = null;

    private MediaPlayer media = null;

    private SurfaceView sufaceView = null;

    private SurfaceHolder surfaceHolder = null;

    private String filepath = null;

 

    @Override

    public void onCreate(BundlesavedInstanceState) {

        super.onCreate(savedInstanceState);

        super.requestWindowFeature(Window.FEATURE_NO_TITLE);// 不顯示標題

        super.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,

                WindowManager.LayoutParams.FLAG_FULLSCREEN);

        super.getWindow().addFlags(

                WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);// 高亮的風格顯示

        super.setContentView(R.layout.play);

 

        this.filepath =super.getIntent().getStringExtra("filepath") ;

       

        this.play = (ImageButton)super.findViewById(R.id.play);

        this.stop = (ImageButton)super.findViewById(R.id.stop);

        this.back = (ImageButton)super.findViewById(R.id.back);

        this.sufaceView = (SurfaceView)super.findViewById(R.id.surfaceView) ;

        this.surfaceHolder =this.sufaceView.getHolder() ;

        this.surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);

        this.media = new MediaPlayer() ;

        this.media.reset() ;

        try {

            this.media.setDataSource(this.filepath);

        } catch (Exception e) {

        }

       

        this.play.setOnClickListener(newPlayOnClickListenerImpl());

        this.stop.setOnClickListener(newStopOnClickListenerImpl());

        this.back.setOnClickListener(newBackOnClickListenerImpl());

    }

 

    private class PlayOnClickListenerImplimplements OnClickListener {

        @Override

        public void onClick(View v) {

            PlayVideoActivity.this.media.setAudioStreamType(AudioManager.STREAM_MUSIC);

            PlayVideoActivity.this.media.setDisplay(PlayVideoActivity.this.surfaceHolder);

            try {

                PlayVideoActivity.this.media.prepare();

                PlayVideoActivity.this.media.start();

            } catch (Exception e) {

            }

        }

    }

 

    private class StopOnClickListenerImplimplements OnClickListener {

        @Override

        public void onClick(View v) {

            PlayVideoActivity.this.media.stop();

        }

    }

 

    private class BackOnClickListenerImplimplements OnClickListener {

        @Override

        public void onClick(View v) {

            Intent it = newIntent(PlayVideoActivity.this, BroswerActivity.class);

            PlayVideoActivity.this.startActivity(it);

        }

    }

    @Override

    public boolean onKeyDown(int keyCode,KeyEvent event) {

        if(keyCode == KeyEvent.KEYCODE_BACK) {

            this.media.stop() ;

            this.media.release() ;

            super.finish() ;

        }

        return false ;

    }

}

(4)定義BrowserActivity程式進行ListView顯示時的佈局管理器---recordfiles.xml

<?xmlversion="1.0" encoding="utf-8"?>

<TableLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent">

    <TableRow>

        <ImageView

            android:id="@+id/icon"

            android:layout_width="fill_parent"

            android:layout_height="wrap_content"

            android:src="@drawable/file_icon"/>

        <TextView

            android:id="@+id/filename"

            android:textSize="25px"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"/>

    </TableRow>

</TableLayout>

(5)定義BrowserActivity程式的佈局管理器---browser.xml

<?xmlversion="1.0" encoding="utf-8"?>

<LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent">

    <LinearLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        android:orientation="horizontal"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content"

        android:gravity="center">

        <TextView

            android:id="@+id/info"

            android:textSize="25px"

            android:gravity="center"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:text="視訊檔案列表" />

        <ImageButton

            android:id="@+id/back"

            android:layout_width="wrap_content"

            android:layout_height="wrap_content"

            android:src="@drawable/back"/>

    </LinearLayout>

    <ListView

        android:id="@+id/videolist"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"/>

</LinearLayout>

(6)定義視訊播放程式PlayVideoActivity的佈局管理器---play.xml

<?xmlversion="1.0" encoding="utf-8"?>

<LinearLayout

    xmlns:android="http://schemas.android.com/apk/res/android"

    android:orientation="vertical"

    android:layout_width="fill_parent"

    android:layout_height="fill_parent">

    <LinearLayout

        xmlns:android="http://schemas.android.com/apk/res/android"

        android:orientation="horizontal"

        android:layout_width="wrap_content"

        android:layout_height="wrap_content">

        <ImageButton

            android:id="@+id/play"

            android:layout_width="wrap_content"

            android:layout_height="fill_parent"

            android:src="@drawable/play"/>

        <ImageButton

            android:id="@+id/stop"

            android:layout_width="wrap_content"

            android:layout_height="fill_parent"

            android:src="@drawable/stop"/>

        <ImageButton

            android:id="@+id/back"

            android:layout_width="wrap_content"

            android:layout_height="fill_parent"

            android:src="@drawable/back"/>

    </LinearLayout>

    <SurfaceView

        android:id="@+id/surfaceView"

        android:layout_width="fill_parent"

        android:layout_height="fill_parent"/>

</LinearLayout>

(7)配置許可權檔案

<uses-permissionandroid:name="android.permission.RECORD_AUDIO" />

    <uses-permissionandroid:name="android.permission.WRITE_EXTERNAL_STORAGE" />

    <uses-permissionandroid:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />

    <uses-permissionandroid:name="android.permission.CAMERA" />