录屏,google了一下,记录下来,以免翻墙
android 4.4 录屏可通过adb:adb shell screenrecord /sdcard/video.mp4 (未测试)
android 5.0:开始提供了屏幕录制api了(https://developer.android.com/about/versions/android-5.0#UI)
大概:
MediaProjectionManager是一个系统服务,通过他最终创建VirtualDisplay,创建时将MediaRecorder的Surface提供给VirtualDisplay
代码来源:https://www.truiton.com/2015/05/capture-record-android-screen-using-mediaprojection-apis/
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> <uses-permission android:name="android.permission.RECORD_AUDIO"/>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:background="#FFFFFF" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context=".MainActivity"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_alignParentTop="true" android:layout_centerHorizontal="true" android:layout_marginTop="10dp" android:text="Recording Status: " android:textAppearance="?android:attr/textAppearanceLarge"/> <ToggleButton android:id="@+id/toggle" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@+id/textView" android:layout_centerHorizontal="true" android:layout_marginTop="5dp" android:text="Start"/> <ImageView android:id="@+id/imageView" android:layout_width="150dp" android:layout_height="150dp" android:layout_below="@+id/toggle" android:layout_centerHorizontal="true" android:layout_marginTop="85dp" android:src="@mipmap/truiton_short"/> </RelativeLayout>
package com.truiton.screencapture; import android.Manifest; import android.content.Context; import android.content.Intent; import android.content.pm.PackageManager; import android.hardware.display.DisplayManager; import android.hardware.display.VirtualDisplay; import android.media.MediaRecorder; import android.media.projection.MediaProjection; import android.media.projection.MediaProjectionManager; import android.net.Uri; import android.os.Bundle; import android.os.Environment; import android.provider.Settings; import android.support.annotation.NonNull; import android.support.design.widget.Snackbar; import android.support.v4.app.ActivityCompat; import android.support.v4.content.ContextCompat; import android.support.v7.app.AppCompatActivity; import android.util.DisplayMetrics; import android.util.Log; import android.util.SparseIntArray; import android.view.Surface; import android.view.View; import android.widget.Toast; import android.widget.ToggleButton; import java.io.IOException; public class MainActivity extends AppCompatActivity { private static final String TAG = "MainActivity"; private static final int REQUEST_CODE = 1000; private int mScreenDensity; private MediaProjectionManager mProjectionManager; private static final int DISPLAY_WIDTH = 720; private static final int DISPLAY_HEIGHT = 1280; private MediaProjection mMediaProjection; private VirtualDisplay mVirtualDisplay; private MediaProjectionCallback mMediaProjectionCallback; private ToggleButton mToggleButton; private MediaRecorder mMediaRecorder; private static final SparseIntArray ORIENTATIONS = new SparseIntArray(); private static final int REQUEST_PERMISSIONS = 10; static { ORIENTATIONS.append(Surface.ROTATION_0, 90); ORIENTATIONS.append(Surface.ROTATION_90, 0); ORIENTATIONS.append(Surface.ROTATION_180, 270); ORIENTATIONS.append(Surface.ROTATION_270, 180); } @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(); mProjectionManager = (MediaProjectionManager) getSystemService (Context.MEDIA_PROJECTION_SERVICE); mToggleButton = (ToggleButton) findViewById(R.id.toggle); mToggleButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (ContextCompat.checkSelfPermission(MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) + ContextCompat .checkSelfPermission(MainActivity.this, Manifest.permission.RECORD_AUDIO) != PackageManager.PERMISSION_GRANTED) { if (ActivityCompat.shouldShowRequestPermissionRationale (MainActivity.this, Manifest.permission.WRITE_EXTERNAL_STORAGE) || ActivityCompat.shouldShowRequestPermissionRationale (MainActivity.this, Manifest.permission.RECORD_AUDIO)) { mToggleButton.setChecked(false); Snackbar.make(findViewById(android.R.id.content), R.string.label_permissions, Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", new View.OnClickListener() { @Override public void onClick(View v) { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, REQUEST_PERMISSIONS); } }).show(); } else { ActivityCompat.requestPermissions(MainActivity.this, new String[]{Manifest.permission .WRITE_EXTERNAL_STORAGE, Manifest.permission.RECORD_AUDIO}, REQUEST_PERMISSIONS); } } else { onToggleScreenShare(v); } } }); } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode != REQUEST_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; } mMediaProjectionCallback = new MediaProjectionCallback(); mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); mMediaProjection.registerCallback(mMediaProjectionCallback, null); mVirtualDisplay = createVirtualDisplay(); mMediaRecorder.start(); } public void onToggleScreenShare(View view) { if (((ToggleButton) view).isChecked()) { initRecorder(); shareScreen(); } else { mMediaRecorder.stop(); mMediaRecorder.reset(); Log.v(TAG, "Stopping Recording"); stopScreenSharing(); } } private void shareScreen() { if (mMediaProjection == null) { startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE); return; } mVirtualDisplay = createVirtualDisplay(); mMediaRecorder.start(); } 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 void initRecorder() { try { mMediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC); mMediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mMediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); mMediaRecorder.setOutputFile(Environment .getExternalStoragePublicDirectory(Environment .DIRECTORY_DOWNLOADS) + "/video.mp4"); mMediaRecorder.setVideoSize(DISPLAY_WIDTH, DISPLAY_HEIGHT); mMediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mMediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB); mMediaRecorder.setVideoEncodingBitRate(512 * 1000); mMediaRecorder.setVideoFrameRate(30); int rotation = getWindowManager().getDefaultDisplay().getRotation(); int orientation = ORIENTATIONS.get(rotation + 90); mMediaRecorder.setOrientationHint(orientation); mMediaRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } } 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"); } mMediaProjection = null; stopScreenSharing(); } } private void stopScreenSharing() { if (mVirtualDisplay == null) { return; } mVirtualDisplay.release(); //mMediaRecorder.release(); //If used: mMediaRecorder object cannot // be reused again destroyMediaProjection(); } @Override public void onDestroy() { super.onDestroy(); destroyMediaProjection(); } private void destroyMediaProjection() { if (mMediaProjection != null) { mMediaProjection.unregisterCallback(mMediaProjectionCallback); mMediaProjection.stop(); mMediaProjection = null; } Log.i(TAG, "MediaProjection Stopped"); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case REQUEST_PERMISSIONS: { if ((grantResults.length > 0) && (grantResults[0] + grantResults[1]) == PackageManager.PERMISSION_GRANTED) { onToggleScreenShare(mToggleButton); } else { mToggleButton.setChecked(false); Snackbar.make(findViewById(android.R.id.content), R.string.label_permissions, Snackbar.LENGTH_INDEFINITE).setAction("ENABLE", new View.OnClickListener() { @Override public void onClick(View v) { Intent intent = new Intent(); intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); intent.addCategory(Intent.CATEGORY_DEFAULT); intent.setData(Uri.parse("package:" + getPackageName())); intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); intent.addFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivity(intent); } }).show(); } return; } } } }