2016-07-28 18 views
0

7 월 보안 업데이트로 6.0.1을 실행하는 Nexus 5에서 스크린 레코딩을 위해이 코드를 사용하고 있습니다. 화면 녹화는 5.0.1, 6.0, 6.0.1을 실행하는 다른 기기에서도 정상적으로 작동하지만 휴대 전화에서는 작동하지 않습니다. 화면 녹화를 시작하려고하면 다음과 같은 오류가 발생합니다.MediaRecorder.GetSurface() null을 반환했습니다.

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) 

화면 녹화를 위해 표면을 얻지 못했습니다. 문제의 원인은 무엇이며 어떻게 해결할 수 있습니까?

소스 코드 :

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

안부

+0

MediaRecorder를 글로벌하게 확인하십시오. –

+0

문제를 어떻게 해결할 지 모르겠습니다. 해결책 제안 뒤에있는 이유에 대해 설명해 주시겠습니까 –

+0

onCreate 메소드에서 전역 유효성 검사를 초기화해야합니다. 그 후에는 매번이 veriable으로 처리하기를 원할 경우 이미 초기화되고이 오류는 발생하지 않습니다. –

답변

0

이 기본적으로 this one와 같은 질문이다. 나는 또한이 문제에 직면 해있다. 이상한 점은 마시맬로에서만 발생하며 롤리팝에서는 작동한다는 것입니다.

documentaion는 말한다 :

표면 getSurface()가

만 준비 후 호출 할 수 있습니다. 시작하기 전에 Surface에 렌더링 된 프레임은 버려집니다. 예외 :
IllegalStateException - 보다 먼저을 호출하거나, 준비를 마친 후, 또는 VideoSource가 SURFACE로 설정되지 않은 경우 호출됩니다.

그러나 Mediarecorder.java에, 그것이

:이 호출되는 경우

는 IllegalStateException이를 @throws {@link #prepare} 이후와 이전에 {@link #STOP}. 내가prepare() 후 또는 전에 를 배치하고있어 여부가 차이가되지 않습니다 그러나

, 모두가 작동하지 않습니다. 위의 것들 중 어느 것도 적용되지 않지만 IllegalStateException을 던지는 것은 정말 이상합니다.

그러나 Matt Snider의 this solution은 마시맬로에서 작동합니다. 그러나 IMO (특히 오디오 녹음을 시도 할 때)가 더 어려우므로 MediaRecorder으로 실행하는 것이 좋습니다.

누군가가 문제를 재현하려면 this 또는 this 코드를 사용하고 마시맬로 컴퓨터에서 실행하십시오.

+0

'준비 '가 성공했는지 확인하십시오. mMediaRecorder java.io.FileNotFoundException : null/_CameraRecord/Camrecord 2017-07-20 22-21-16 : 오픈 실패 : ENOENT (해당 파일이나 디렉터리가 없음) 07-20 22 : 21 : 16.412 26052-26052/com.example.driverassistance I/LOGGG : mVirtualDisplay java.lang.IllegalStateException : 표면을 가져 오지 못했습니다. – user25

관련 문제