最近在項目開發中需要調用系統的攝像頭錄像並播放。
在開發中遇到了兩個問題,記錄下:
(1)開發過程中出現攝像頭占用,啟動失敗,報錯。但是我已經在onDestory()中關閉了資源。
報錯原因:打開程序,調用攝像頭,按Home鍵再打開程序調用,報錯攝像頭被占用。
解決:在onStop()中關閉資源,在onResume()中判斷是否為null,否則實例化資源。
(2)其中我錄像播放的代碼寫在Fragment+ViewPager中,在來回切換Fragment的時候,攝像頭只能調用一次,並且所在的Fragment可能會被銷毀。(這里可去看下Fragment生命周期的調用過程)
報錯原因:ViewPager有緩存加載機制,只會預緩存下一頁。所以在來回切換的過程中錄像播放Fragment存在不斷銷毀、創建的可能。
解決:如果你的ViewPager頁數不多,並大概知道它的頁數,可以修改ViewPager的緩存頁面數量。
viewPagwer.setoffscreenPageLimit(int numbers); //當頁面切換時,當前頁面相鄰兩側的numbers頁面不會被銷毀。
ViewPager的緩存機制: http://www.cnblogs.com/Joanna-Yan/p/4824434.html
下面看具體的代碼分析:
錄制過程:
mediarecorder = new MediaRecorder();// 創建mediarecorder對象 // 設置錄制視頻源為Camera(相機) mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 設置錄制完成后視頻的封裝格式THREE_GPP為3gp.MPEG_4為mp4 mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); // 設置錄制的視頻編碼h263 h264 mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 設置視頻錄制的分辨率。必須放在設置編碼和格式的后面,否則報錯 mediarecorder.setVideoSize(176, 144); // 設置錄制的視頻幀率。必須放在設置編碼和格式的后面,否則報錯 mediarecorder.setVideoFrameRate(20); mediarecorder.setPreviewDisplay(surfaceView.getHolder().getSurface()); // 設置視頻文件輸出的路徑 lastFileName = newFileName(); mediarecorder.setOutputFile(lastFileName); try { // 准備錄制 mediarecorder.prepare(); // 開始錄制 mediarecorder.start(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } 結束拍攝: if (mediarecorder != null) { // 停止 mediarecorder.stop(); mediarecorder.release(); mediarecorder = null; }
自己的封裝類:
package zyf.demo.moviedemo; import java.io.File; import java.io.IOException; import java.util.Timer; import java.util.TimerTask; import android.media.MediaRecorder; import android.view.SurfaceView; public class MovieRecorder { private MediaRecorder mediarecorder; boolean isRecording; public void startRecording(SurfaceView surfaceView) { mediarecorder = new MediaRecorder();// 創建mediarecorder對象 // 設置錄制視頻源為Camera(相機) mediarecorder.setVideoSource(MediaRecorder.VideoSource.CAMERA); // 設置錄制完成后視頻的封裝格式THREE_GPP為3gp.MPEG_4為mp4 mediarecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); // 設置錄制的視頻編碼h263 h264 mediarecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); // 設置視頻錄制的分辨率。必須放在設置編碼和格式的后面,否則報錯 mediarecorder.setVideoSize(176, 144); // 設置錄制的視頻幀率。必須放在設置編碼和格式的后面,否則報錯 mediarecorder.setVideoFrameRate(20); mediarecorder.setPreviewDisplay(surfaceView.getHolder().getSurface()); // 設置視頻文件輸出的路徑 lastFileName = newFileName(); mediarecorder.setOutputFile(lastFileName); try { // 准備錄制 mediarecorder.prepare(); // 開始錄制 mediarecorder.start(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } isRecording = true; timeSize = 0; timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { // TODO Auto-generated method stub timeSize++; } }, 0,1000); } Timer timer; int timeSize = 0; private String lastFileName; public void stopRecording() { if (mediarecorder != null) { // 停止 mediarecorder.stop(); mediarecorder.release(); mediarecorder = null; timer.cancel(); if (null != lastFileName && !"".equals(lastFileName)) { File f = new File(lastFileName); String name = f.getName().substring(0, f.getName().lastIndexOf(".3gp")); name += "_" + timeSize + "s.3gp"; String newPath = f.getParentFile().getAbsolutePath() + "/" + name; if (f.renameTo(new File(newPath))) { int i = 0; i++; } } } } public String newFileName() { try { return File.createTempFile("/mov_", ".3gp").getAbsolutePath(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); return null; } } public void release() { if (mediarecorder != null) { // 停止 mediarecorder.stop(); mediarecorder.release(); mediarecorder = null; } } }
如何播放:
public void play(String fileName, SurfaceView view) { mPlayer = new MediaPlayer(); mPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC); mPlayer.setDisplay(view.getHolder()); // 定義一個SurfaceView播放它 mPlayer.setOnCompletionListener(new OnCompletionListener() { @Override public void onCompletion(MediaPlayer arg0) { stop(); // canvas.drawColor(Color.TRANSPARENT, // PorterDuff.Mode.CLEAR); } }); try { mPlayer.setDataSource(fileName); mPlayer.prepare(); } catch (IllegalStateException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } mPlayer.start(); } 結束播放時: public void stop() { if (mPlayer != null) { mPlayer.release(); mPlayer = null; } }
附上源碼:http://pan.baidu.com/s/1dDuI2HF 提取碼:cmm6