2016-07-28 10 views
0

Ich verwende diesen Code für die Bildschirmaufnahme auf meinem Nexus 5, auf dem 6.0.1 mit dem Juli-Sicherheitsupdate läuft. Die Bildschirmaufnahme funktioniert auf anderen Geräten mit 5.0.1, 6.0, 6.0.1 einwandfrei, funktioniert aber nicht auf meinem Telefon. Es gibt mir den folgenden Fehler, wenn ich versuche, die Bildschirmaufnahme zu starten.MediaRecorder.GetSurface() gibt null zurück

E/MediaRecorder: SurfaceMediaSource could not be initialized! 
E/AndroidRuntime: FATAL EXCEPTION: main 
java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1995, result=-1, data=Intent { (has extras) }} to activity {MainActivity}: java.lang.IllegalStateException: failed to get surface 
at android.app.ActivityThread.deliverResults(ActivityThread.java:3699) 
Caused by: java.lang.IllegalStateException: failed to get surface 
at android.media.MediaRecorder.getSurface(Native Method) 

Es ist nicht möglich, Oberfläche für die Bildschirmaufzeichnung zu erhalten. Was verursacht das und wie kann ich das beheben?

Source Code:

public static MediaProjectionManager getmMediaProjectionManager(final MainActivity context) { 
     DisplayMetrics metrics = new DisplayMetrics(); 
     context.getWindowManager().getDefaultDisplay().getMetrics(metrics); 
     mScreenDensity = metrics.densityDpi; 
     DISPLAY_HEIGHT = metrics.heightPixels; 
     DISPLAY_WIDTH = metrics.widthPixels; 
     mMediaRecorder = new MediaRecorder(); 

     mMediaProjectionManager = (MediaProjectionManager) context.getSystemService(Context.MEDIA_PROJECTION_SERVICE); 
     return mMediaProjectionManager; 
    } 

    @TargetApi(21) 
    public static void startScreenRecording(Intent data) { 
     mMediaProjectionCallback = new MediaProjectionCallback(); 
     initRecorder(null); 
     mMediaProjection = mMediaProjectionManager.getMediaProjection(RESULT_OK, data); 
     mMediaProjection.registerCallback(mMediaProjectionCallback, null); 
     mVirtualDisplay = createVirtualDisplay(); 
     mMediaRecorder.start(); 
    } 

    @TargetApi(21) 
    private static VirtualDisplay createVirtualDisplay() { 
     return mMediaProjection.createVirtualDisplay("MainActivity", 
       DISPLAY_WIDTH, DISPLAY_HEIGHT, mScreenDensity, 
       DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 
       mMediaRecorder.getSurface(), null /*Callbacks*/, null 
       /*Handler*/); 
    } 

    @TargetApi(21) 
    private static void initRecorder(MainActivity context) { 
     try { 
      mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); 
      mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); 
      mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4); 
      mMediaRecorder.setOutputFile(Environment 
        .getExternalStorageDirectory() + "/video"+ System.currentTimeMillis()+".mp4"); 
      mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT); 
      mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); 
      mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); 
      mMediaRecorder.setVideoEncodingBitRate(VIDEO_ENCODING_BITRATE); 
      mMediaRecorder.setVideoFrameRate(VIDEO_FRAME_RATE); 
      mMediaRecorder.prepare(); 
     } catch (Exception e) { 
      Log.e("Util", e.getLocalizedMessage()); 
     } 
    } 

    @TargetApi(21) 
    private static class MediaProjectionCallback extends MediaProjection.Callback { 
     @Override 
     public void onStop() { 

     } 
    } 

    @TargetApi(21) 
    public static void stopScreenSharing() { 
     mMediaRecorder.stop(); 
     mMediaRecorder.reset(); 
     if (mVirtualDisplay == null) { 
      return; 
     } 

     mVirtualDisplay.release(); 

     destroyMediaProjection(); 
    } 

    @TargetApi(21) 
    private static void destroyMediaProjection() { 
     if (mMediaProjection != null) { 
      Log.e(TAG, "destroying projection"); 
      mMediaProjection.unregisterCallback(mMediaProjectionCallback); 
      mMediaProjection.stop(); 
      mMediaProjection = null; 
     } 
    } 

Mit freundlichen Grüßen

+0

Machen Sie Ihren MediaRecorder global verifizierbar. –

+0

Ich sehe nicht, wie das Problem gelöst wird. Würdest du bitte etwas Licht auf den Grund hinter deiner vorgeschlagenen Lösung werfen? –

+0

Du musst global veriable machen und es einmal in deiner onCreate Methode initiieren. Danach jedes Mal, wenn Sie mit dieser Veriable machen wollen, wird es bereits initialisiert und Sie würden diesen Fehler nicht bekommen. –

Antwort

0

Dies ist im Grunde die gleiche Frage wie this one. Ich bin auch mit diesem Problem konfrontiert. Das seltsame ist, dass es nur auf Marshmallow passiert, auf Lollipop funktioniert es.

Die documentaion sagt:

Oberflächen getSurface()

erst nach Vorbereitung genannt werden kann. Frames, die vor dem Start auf die Oberfläche gerendert wurden, werden verworfen. Wirfs:
IllegalStateException - wenn es vor vorbereitete, nach dem Stop aufgerufen wird oder wenn VideoSource nicht auf OBERFLÄCHE festgelegt ist.

Aber in Mediarecorder.java, es ist:

@throws Illegal wenn es nach {@link #prepare} genannt wird und vor {@link #stop}.

jedoch es keinen Unterschied macht, ob ich es vor oder nachprepare() platzieren, nicht beide nicht funktionieren. Es ist wirklich seltsam, dass es eine IllegalStateException wirft, obwohl keine der oben genannten Dinge zutreffen.

Jedoch arbeitet this solution von Matt Snider an Marshmallow. Aber da es IMO schwieriger ist (besonders wenn man versucht, Audio aufzunehmen), wäre es großartig, wenn es auch mit MediaRecorder läuft.

Wenn jemand das Problem reproduzieren möchte, verwenden Sie einfach this oder this Code und führen Sie es auf einer Marshmallow-Maschine.

+0

sicher sein, dass 'prepare' war erfolgreich' mMediaRecorder java.io.FileNotFoundException: null/_CameraRecord/Camrecord 2017-07-20 22-21-16 : open failed: ENOENT (Keine solche Datei oder Verzeichnis) 07-20 22: 21: 16.412 26052-26052/com.example.driverassistance I/LOGGG: mVirtualDisplay java.lang.IllegalStateException: Die Oberfläche konnte nicht abgerufen werden – user25