2015-11-05 41 views
7

我開始使用MediaRecorder和MediaProjection函數在Android 5.1的reord屏幕服務,我認爲代碼方法1將導致應用程序無法響應錯誤,因爲它在主線程中工作。爲什麼MediaRecorder函數不會導致ANR錯誤?

  1. 我測試的代碼方法1重新編寫屏幕很長一段時間,但不會出現「應用無響應的錯誤」,爲什麼呢?這是否意味着MediaRecorder和MediaProjection函數在獨立線程中工作?

  2. 在代碼方法2,我創建一個線程來運行mRecordHelper.StartRecord(mRecordArg,發送resultCode,mIntent);但是我得到錯誤java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(),爲什麼?

感謝您的幫助。

呼叫號碼

MPublicPar.RecordArg mRecordArg =new MPublicPar().new RecordArg(mContext); 
Intent intent = new Intent(mContext,bll.RecordService.class); 
intent.putExtra("resultCode",resultCode); 
intent.putExtra("dataIntent",data); 
intent.putExtra("mRecordArg",mRecordArg); 

startService(intent); 

方法1

public class RecordService extends Service { 

    private RecordHelper mRecordHelper; 
    private Context mContext; 

    @Override 
    public void onCreate(){ 
     mContext=this; 

     mRecordHelper=new RecordHelper(mContext); 
    } 

    @Override 
    public void onDestroy(){ 
     mRecordHelper.StopRecord(); 
    } 


    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     final int resultCode=intent.getIntExtra("resultCode",0); 
     final Intent mIntent=(Intent)intent.getParcelableExtra("dataIntent"); 
     final MPublicPar.RecordArg mRecordArg=(MPublicPar.RecordArg)intent.getSerializableExtra("mRecordArg"); 

     mRecordHelper.StartRecord(mRecordArg,resultCode,mIntent); 
     return super.onStartCommand(intent, flags, startId); 
    } 

} 

方法2

public class RecordService extends Service { 

    private RecordHelper mRecordHelper; 
    private Context mContext; 

    @Override 
    public void onCreate(){ 
     mContext=this; 

     mRecordHelper=new RecordHelper(mContext); 
    } 

    @Override 
    public void onDestroy(){ 
     mRecordHelper.StopRecord(); 
    } 


    @Override 
    public int onStartCommand(Intent intent, int flags, int startId) { 

     final int resultCode=intent.getIntExtra("resultCode",0); 
     final Intent mIntent=(Intent)intent.getParcelableExtra("dataIntent"); 
     final MPublicPar.RecordArg mRecordArg=(MPublicPar.RecordArg)intent.getSerializableExtra("mRecordArg");  

     new Thread(new Runnable() { 
      public void run() {  
       mRecordHelper.StartRecord(mRecordArg,resultCode,mIntent);   
      } 
     }).start(); 
     return super.onStartCommand(intent, flags, startId); 
    } 

} 

個RecordHelper.cs

public class RecordHelper { 

    private MediaRecorder mMediaRecorder; 
    private MediaProjection mMediaProjection; 
    private VirtualDisplay mVirtualDisplay; 
    private MediaProjectionManager mProjectionManager; 

    private Context mContext; 
    private Toast mToastText; 

    public RecordHelper(Context mContext){ 
     this.mContext=mContext; 
     mProjectionManager = (MediaProjectionManager) mContext.getSystemService(Context.MEDIA_PROJECTION_SERVICE); 
     mMediaRecorder = new MediaRecorder(); 
    } 

    public void StartRecord(RecordArg mRecordArg, int resultCode, Intent data){ 

     initRecorder(mRecordArg); 
     prepareRecorder(); 

     mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); 
     MediaProjectionCallback mMediaProjectionCallback = new MediaProjectionCallback(); 
     mMediaProjection.registerCallback(mMediaProjectionCallback, null); 

     mVirtualDisplay=createVirtualDisplay(mRecordArg); 

     DelayStartRecord(mRecordArg); 
    } 


    public void StopRecord(){ 
     try { 
      mMediaRecorder.stop(); 
      mMediaRecorder.reset(); 

      mVirtualDisplay.release(); 
      mMediaRecorder.release(); 

      mMediaProjection.stop(); 
      mMediaProjection = null; 

     }catch (Exception e){ 
      Utility.LogError("StopRecord Error " + e.getMessage() + " " + e.toString()); 
     } 
    } 

    private void DelayStartRecord(RecordArg mRecordArg){ 
     mMediaRecorder.start(); 
    } 


    private void initRecorder(RecordArg mRecordArg) { 
     mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
     mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
     mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
     mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 
     mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
     mMediaRecorder.setVideoEncodingBitRate(512 * 1000); 
     mMediaRecorder.setVideoFrameRate(30); 
     mMediaRecorder.setVideoSize(mRecordArg.screenWidth, mRecordArg.screenHeight); 
     mMediaRecorder.setOutputFile(mRecordArg.videoFilename); 
    } 


    private void prepareRecorder() { 
     try { 
      mMediaRecorder.prepare(); 
     } catch (IllegalStateException e) { 
      e.printStackTrace(); 
      Utility.LogError(e.getMessage()); 

     } catch (IOException e) { 
      e.printStackTrace(); 
      Utility.LogError(e.getMessage()); 
     } 
    } 


    private VirtualDisplay createVirtualDisplay(RecordArg mRecordArg) { 
      return mMediaProjection.createVirtualDisplay("ScreenRecord", 
       mRecordArg.screenWidth, mRecordArg.screenHeight, mRecordArg.mScreenDensity, 
       DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 
       mMediaRecorder.getSurface(), null /*Callbacks*/, null /*Handler*/); 
    } 


    //Called when the MediaProjection session is no longer valid. 
    private class MediaProjectionCallback extends MediaProjection.Callback { 
     @Override 
     public void onStop() { 

     } 
    } 

} 
+0

我覺得你應該把它放在UI線程。 –

回答

4

,但我得到的錯誤了java.lang.RuntimeException:無法內螺紋創建處理程序尚未調用Looper.prepare(),爲什麼?

我想你知道你的第二個問題。事實上,如果您在主線程上調用mRecordHelper.StartRecord(mRecordArg,resultCode,mIntent);並不意味着所有代碼函數都在該線程上運行,它所做的只是更新調用線程(這是主線程)上的UI信息以及背景上的辛苦工作線。如果你從不同的線程中顯式地調用,你正在指示它從那個線程中改變一個UI對象,因此你得到這個異常 - 一個使用異步任務的類,或者SurfaceView,不要混淆先生,你總是可以去檢查源代碼並看看它是如何工作的。

這是不是一個大問題 - (我謙虛地說)

爲什麼呢?這是否意味着MediaRecorder和MediaProjection函數在獨立線程中工作?

檢查上述-i猜測是在方法2

+0

謝謝!有沒有辦公室文件告訴我,MediaRecorder和MediaProjection在單獨的線程中工作? – HelloCW

相關問題