2015-11-05 14 views
7

Avvio un servizio per riordinare lo schermo utilizzando MediaRecorder e MediaProjection in Android 5.1, penso che il codice Metodo 1 causerà l'errore di Non risposta dell'applicazione poiché funziona nel thread principale.Perché la funzione MediaRecorder non causa l'errore ANR?

  1. ho testare il codice Metodo 1 ricodificare schermo da molto tempo, non si verifica "Applicazione non risponde errore", perché? Significa che la funzione MediaRecorder e MediaProjection funzionino in thread separati?

  2. Nel codice Metodo 2, a creare un thread per eseguire mRecordHelper.StartRecord (mRecordArg, resultCode, mIntent); ma ottengo l'errore java.lang.RuntimeException: Can't create handler inside thread that has not called Looper.prepare(), perché?

Grazie per il vostro aiuto.

codice di chiamata

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); 

Metodo 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); 
    } 

} 

Metodo 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

nel metodo 2 Penso che si dovrebbe mettere sul ui Discussione. –

risposta

4

ma ho l'java.lang.RuntimeException errore: Impossibile creare il gestore di filettatura interna che non ha chiamato Looper.prepare(), perché?

Immagino che tu sappia quindi la tua seconda domanda. Il fatto che se chiami mRecordHelper.StartRecord(mRecordArg,resultCode,mIntent); sul thread principale, non significhi che tutte le funzioni di codice vengano eseguite su quel thread, tutto ciò che aggiorna sono le informazioni dell'interfaccia utente sul thread chiamante, che è il thread principale e il duro lavoro su uno sfondo Filo. se si richiama xpticamente da un thread diverso si sta indicando di cambiare un oggetto UI da quel thread quindi si ottiene quell'eccezione - un'immagine di una classe usando task asincrono, o SurfaceView, non si confonda signore, si può sempre andare controllare il codice sorgente e vedi come funziona

Questo non è un grosso problema - (umilmente parlo)

perché? Significa che la funzione MediaRecorder e MediaProjection funzionino in thread separati?

di controllo di cui sopra -i indovinare sì

+0

Grazie! C'è un documento dell'ufficio per dirmi che MediaRecorder e MediaProjection hanno funzionato in thread separati? – HelloCW

Problemi correlati