2015-02-10 117 views
-1

我正在尝试使用MediaProjection录制Android 5.0 Lollipop中的手机屏幕并保存录制的视频。保存录制的手机屏幕

我试过这段代码,但是在我将saveFile(uri)加到onActivityResult之后,当我开始记录时,应用程序崩溃了。

什么是正确的方式来获取录制的视频并保存它?

public class MainActivity extends Activity { 
     private static final String TAG = "MediaProjectionDemo"; 
     private static final int PERMISSION_CODE = 1; 
     private static final List<Resolution> RESOLUTIONS = new ArrayList<Resolution>() {{ 
      add(new Resolution(640,360)); 
      add(new Resolution(960,540)); 
      add(new Resolution(1366,768)); 
      add(new Resolution(1600,900)); 
     }}; 

     private int mScreenDensity; 
     private MediaProjectionManager mProjectionManager; 

     private int mDisplayWidth; 
     private int mDisplayHeight; 
     private boolean mScreenSharing; 

     private MediaProjection mMediaProjection; 
     private VirtualDisplay mVirtualDisplay; 
     private Surface mSurface; 
     private SurfaceView mSurfaceView; 

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

      mSurfaceView = (SurfaceView) findViewById(R.id.surface); 
      mSurface = mSurfaceView.getHolder().getSurface(); 
      mProjectionManager = 
        (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); 

      ArrayAdapter<Resolution> arrayAdapter = new ArrayAdapter<Resolution>(
        this, android.R.layout.simple_list_item_1, RESOLUTIONS); 
      Spinner s = (Spinner) findViewById(R.id.spinner); 
      s.setAdapter(arrayAdapter); 
      s.setOnItemSelectedListener(new ResolutionSelector()); 
      s.setSelection(0); 
     } 

     @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, 
         "User denied screen sharing permission", Toast.LENGTH_SHORT).show(); 
       return; 
      } 

      try { 
       java.net.URI uri = new java.net.URI(data.getData().toString()); 
       saveFile(uri); 

      } catch (URISyntaxException e) { 
       e.printStackTrace(); 
      } 

      mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); 
      mVirtualDisplay = createVirtualDisplay(); 
     } 

     void saveFile(URI sourceUri) 
     { 
      String sourceFilename= sourceUri.getPath(); 
      String destinationFilename = android.os.Environment.getExternalStorageDirectory().getPath()+ File.separatorChar+"abc.mp4"; 

      BufferedInputStream bis = null; 
      BufferedOutputStream bos = null; 

      try { 
       bis = new BufferedInputStream(new FileInputStream(sourceFilename)); 
       bos = new BufferedOutputStream(new FileOutputStream(destinationFilename, false)); 
       byte[] buf = new byte[1024]; 
       bis.read(buf); 
       do { 
        bos.write(buf); 
       } while(bis.read(buf) != -1); 
      } catch (IOException e) { 

      } finally { 
       try { 
        if (bis != null) bis.close(); 
        if (bos != null) bos.close(); 
       } catch (IOException e) { 

       } 
      } 
     } 

     public void onToggleScreenShare(View view) { 
      if (((ToggleButton) view).isChecked()) { 
       shareScreen(); 
      } else { 
       stopScreenSharing(); 
      } 
     } 

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

     private void stopScreenSharing() { 
      mScreenSharing = false; 
      if (mVirtualDisplay == null) { 
       return; 
      } 
      mVirtualDisplay.release(); 
     } 

     private VirtualDisplay createVirtualDisplay() { 
      return mMediaProjection.createVirtualDisplay("ScreenSharingDemo", 
        mDisplayWidth, mDisplayHeight, mScreenDensity, 
        DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, 
        mSurface, null /*Callbacks*/, null /*Handler*/); 
     } 

     private void resizeVirtualDisplay() { 
      if (mVirtualDisplay == null) { 
       return; 
      } 
      mVirtualDisplay.resize(mDisplayWidth, mDisplayHeight, mScreenDensity); 
     } 

     private class ResolutionSelector implements Spinner.OnItemSelectedListener { 
      @Override 
      public void onItemSelected(AdapterView<?> parent, View v, int pos, long id) { 
       Resolution r = (Resolution) parent.getItemAtPosition(pos); 
       ViewGroup.LayoutParams lp = mSurfaceView.getLayoutParams(); 
       if (getResources().getConfiguration().orientation 
         == Configuration.ORIENTATION_LANDSCAPE) { 
        mDisplayHeight = r.y; 
        mDisplayWidth = r.x; 
       } else { 
        mDisplayHeight = r.x; 
        mDisplayWidth = r.y; 
       } 
       lp.height = mDisplayHeight; 
       lp.width = mDisplayWidth; 
       mSurfaceView.setLayoutParams(lp); 
      } 

      @Override 
      public void onNothingSelected(AdapterView<?> parent) { /* Ignore */ } 
     } 

     private class MediaProjectionCallback extends MediaProjection.Callback { 
      @Override 
      public void onStop() { 
       mMediaProjection = null; 
       stopScreenSharing(); 
      } 
     } 

     private class SurfaceCallbacks implements SurfaceHolder.Callback { 
      @Override 
      public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) { 
       mDisplayWidth = width; 
       mDisplayHeight = height; 
       resizeVirtualDisplay(); 
      } 

      @Override 
      public void surfaceCreated(SurfaceHolder holder) { 
       mSurface = holder.getSurface(); 
       if (mScreenSharing) { 
        shareScreen(); 
       } 
      } 

      @Override 
      public void surfaceDestroyed(SurfaceHolder holder) { 
       if (!mScreenSharing) { 
        stopScreenSharing(); 
       } 
      } 
     } 

     private static class Resolution { 
      int x; 
      int y; 

      public Resolution(int x, int y) { 
       this.x = x; 
       this.y = y; 
      } 

      @Override 
      public String toString() { 
       return x + "x" + y; 
      } 
     } 
    } 

的logcat:

java.lang.RuntimeException: Failure delivering result ResultInfo{who=null, request=1, result=-1, data=Intent { (has extras) }} to activity {com.name.name/com.name.name.MainActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference 
      at android.app.ActivityThread.deliverResults(ActivityThread.java:3539) 
      at android.app.ActivityThread.handleSendResult(ActivityThread.java:3582) 
      at android.app.ActivityThread.access$1300(ActivityThread.java:144) 
      at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327) 
      at android.os.Handler.dispatchMessage(Handler.java:102) 
      at android.os.Looper.loop(Looper.java:135) 
      at android.app.ActivityThread.main(ActivityThread.java:5221) 
      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:899) 
      at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
    Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'java.lang.String android.net.Uri.toString()' on a null object reference 
      at com.name.name.MainActivity.onActivityResult(MainActivity.java:103) // java.net.URI uri = new java.net.URI(data.getData().toString()); 
      at android.app.Activity.dispatchActivityResult(Activity.java:6135) 
      at android.app.ActivityThread.deliverResults(ActivityThread.java:3535) 
            at android.app.ActivityThread.handleSendResult(ActivityThread.java:3582) 
            at android.app.ActivityThread.access$1300(ActivityThread.java:144) 
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1327) 
            at android.os.Handler.dispatchMessage(Handler.java:102) 
            at android.os.Looper.loop(Looper.java:135) 
            at android.app.ActivityThread.main(ActivityThread.java:5221) 
            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:899) 
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694) 
+1

发布您的logcat – ianhanniballake 2015-02-10 23:53:13

+0

我发布了logcat。 – user3051755 2015-02-11 09:58:04

回答

0

当你调用startActivityOnResult,就说明你的设备上的确认对话框。一旦你对这个对话做出反应,onActivityResult被调用。如果是resultCode == RESULT_OK,这并不意味着您开始录制,只是表示您已被授予拍摄屏幕的权限(将屏幕镜像到您的活动中)。

您现在需要做的是开始使用MediaRecorder从您已有的表面上录制视频。