2015-09-22 27 views
7

Tôi cố gắng kiểm tra mã mẫu về bản ghi màn hình từ liên kết bên dưới, tôi đã sửa đổi một số mã để tắt âm thanh ghi.Tôi có thể kiểm tra bản ghi màn hình trong trình mô phỏng trong Android Studio không?

http://www.truiton.com/2015/05/capture-record-android-screen-using-mediaprojection-apis/

tôi thử nghiệm mã trong Android Studio V1.3, nhưng tôi nhận được lỗi sau, và các tập tin capture.mp4 là trống.

Tôi không chắc liệu mình có phải kiểm tra mã trong điện thoại di động thực không? Bạn có thể giúp tôi ? Cảm ơn!

Lỗi Thông tin

09-22 06:41:50.250 2167-2167/? E/AndroidRuntime﹕ FATAL EXCEPTION: main 
    Process: screencapture.truiton.com.myapplication, PID: 2167 
    java.lang.RuntimeException: stop failed. 
      at android.media.MediaRecorder.stop(Native Method) 
      at screencapture.truiton.com.myapplication.MainActivity.onToggleScreenShare(MainActivity.java:93) 
      at screencapture.truiton.com.myapplication.MainActivity$1.onClick(MainActivity.java:55) 
      at android.view.View.performClick(View.java:4780) 
      at android.widget.CompoundButton.performClick(CompoundButton.java:120) 
      at android.view.View$PerformClick.run(View.java:19866) 
      at android.os.Handler.handleCallback(Handler.java:739) 
      at android.os.Handler.dispatchMessage(Handler.java:95) 
      at android.os.Looper.loop(Looper.java:135) 
      at android.app.ActivityThread.main(ActivityThread.java:5257) 
      at java.lang.reflect.Method.invoke(Native Method) 
      at java.lang.reflect.Method.invoke(Method.java:372) 
      at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698) 

Source Code

package screencapture.truiton.com.myapplication; 

public class MainActivity extends Activity { 

    private static final String TAG = "MainActivity"; 
    private static final int PERMISSION_CODE = 1; 
    private int mScreenDensity; 
    private MediaProjectionManager mProjectionManager; 
    private static final int DISPLAY_WIDTH = 480; 
    private static final int DISPLAY_HEIGHT = 640; 
    private MediaProjection mMediaProjection; 
    private VirtualDisplay mVirtualDisplay; 
    private MediaProjectionCallback mMediaProjectionCallback; 
    private ToggleButton mToggleButton; 
    private MediaRecorder mMediaRecorder; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 
     DisplayMetrics metrics = new DisplayMetrics(); 
     getWindowManager().getDefaultDisplay().getMetrics(metrics); 
     mScreenDensity = metrics.densityDpi; 

     mMediaRecorder = new MediaRecorder(); 
     initRecorder(); 
     prepareRecorder(); 

     mProjectionManager = (MediaProjectionManager) getSystemService 
       (Context.MEDIA_PROJECTION_SERVICE); 

     mToggleButton = (ToggleButton) findViewById(R.id.toggle); 
     mToggleButton.setOnClickListener(new View.OnClickListener() { 
      @Override 
      public void onClick(View v) { 
       onToggleScreenShare(v); 
      } 
     }); 

     mMediaProjectionCallback = new MediaProjectionCallback(); 
    } 

    @Override 
    public void onDestroy() { 
     super.onDestroy(); 
     if (mMediaProjection != null) { 
      mMediaProjection.stop(); 
      mMediaProjection = null; 
     } 
    } 

    @Override 
    public void onActivityResult(int requestCode, int resultCode, Intent data) { 
     if (requestCode != PERMISSION_CODE) { 
      Log.e(TAG, "Unknown request code: " + requestCode); 
      return; 
     } 
     if (resultCode != RESULT_OK) { 
      Toast.makeText(this, 
        "Screen Cast Permission Denied", Toast.LENGTH_SHORT).show(); 
      mToggleButton.setChecked(false); 
      return; 
     } 
     mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); 
     mMediaProjection.registerCallback(mMediaProjectionCallback, null); 
     mVirtualDisplay = createVirtualDisplay(); 
     mMediaRecorder.start(); 
    } 

    public void onToggleScreenShare(View view) { 
     if (((ToggleButton) view).isChecked()) { 
      shareScreen(); 
     } else { 
      mMediaRecorder.stop(); 
      mMediaRecorder.reset(); 
      Log.v(TAG, "Recording Stopped"); 
      stopScreenSharing(); 
      initRecorder(); 
      prepareRecorder(); 
     } 
    } 

    private void shareScreen() { 
     if (mMediaProjection == null) { 
      startActivityForResult(mProjectionManager.createScreenCaptureIntent(), PERMISSION_CODE); 
      return; 
     } 
     mVirtualDisplay = createVirtualDisplay(); 
     mMediaRecorder.start(); 
    } 

    private void stopScreenSharing() { 
     if (mVirtualDisplay == null) { 
      return; 
     } 
     mVirtualDisplay.release(); 
     //mMediaRecorder.release(); 
    } 

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

    private class MediaProjectionCallback extends MediaProjection.Callback { 
     @Override 
     public void onStop() { 
      if (mToggleButton.isChecked()) { 
       mToggleButton.setChecked(false); 
       mMediaRecorder.stop(); 
       mMediaRecorder.reset(); 
       Log.v(TAG, "Recording Stopped"); 
       initRecorder(); 
       prepareRecorder(); 
      } 
      mMediaProjection = null; 
      stopScreenSharing(); 
      Log.i(TAG, "MediaProjection Stopped"); 
     } 
    } 

    private void prepareRecorder() { 
     try { 
      mMediaRecorder.prepare(); 
     } catch (IllegalStateException e) { 
      e.printStackTrace(); 
      finish(); 
     } catch (IOException e) { 
      e.printStackTrace(); 
      finish(); 
     } 
    } 

    private void initRecorder() { 

     //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(DISPLAY_WIDTH, DISPLAY_HEIGHT); 
     mMediaRecorder.setOutputFile(Environment.getExternalStorageDirectory() + "/capture.mp4"); 
    } 
} 
+0

Xem: http://stackoverflow.com/questions/26545970/take-a-screenshot-using-mediaprojection –

+0

tại sao bạn không thử chạy trong thiết bị. ít nhất bạn sẽ khám phá ra một cái gì đó nhiều hơn –

+0

Xin lỗi, tôi không có thiết bị Android với Android 5.0 được cài đặt, tôi có thể kiểm tra bản ghi màn hình trong trình giả lập không? Cảm ơn! – HelloCW

Trả lời

1

Từ kinh nghiệm của tôi, giả lập Android làm phép đọc từ bề mặt (đó là điều duy nhất thực sự cần thiết để ghi âm) nhưng thất bại để mã hóa video (và đôi khi chụp ảnh màn hình) do lỗi/hạn chế trong mã Java của khung công tác. Có hai lý do chính:

  • Các giả lập chưa được công bố hỗ trợ cho EGL_ANDROID_recordable phần mở rộng, được yêu cầu của MediaRecorder/MediaCodec. Bạn có thể kiểm tra hỗ trợ tiện ích mở rộng bằng cách thực hiện lệnh sau:

    adb shell dumpsys SurfaceFlinger | grep EGL_ANDROID_recordable 
    
  • Định dạng màu duy nhất, được hỗ trợ bởi bộ mã hóa phần mềm dựng sẵn Android 6, là YUV. Bộ đệm video, đến từ trình giả lập GPU, có khả năng có định dạng khác nhau.

Lưu ý rằng các giới hạn ở trên không độc quyền cho trình mô phỏng và có thể gây ra lỗi trên thiết bị thực. Bạn có thể làm việc xung quanh chúng bằng cách thực hiện chuyển đổi định dạng trong phần mềm (trên CPU hoặc qua GLES), bằng cách sử dụng phương pháp tiếp cận phác thảo trong this answer, nhưng hiệu suất của bộ mã hóa phần mềm sẽ không hoạt động theo cách nào.

Các vấn đề liên quan