本文主要是介绍Android10以上MediaProjection截屏,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
起因
在系统升级到Android10以上之后,之前的截屏方式不能用了,而且必须将MediaProjection放在forground service里面跑才行。网上搜了一圈,都是语焉不详或者没有完整的一个代码应用。只能自己写一个,记录下
代码实现
新建一个ScreenRecorder.java
public class ScreenRecorder extends Service {@Nullable@Overridepublic IBinder onBind(Intent intent) {return null;}private MediaProjection mMediaProjection;private MediaProjectionManager mMediaProjectionManager;private int SERVICE_ID = 123;private String NOTIFICATION_CHANNEL_ID = "Screen Capture channel";public static final String ACTION_START = "RecordService:Start";public static final String ACTION_SNAPSHOT = "RecordService:Snapshot";public static final String ACTION_STOP = "RecordService:Stop";public static final String EXTRA_RESULT_DATA = "RecordService:Extra:ResultData";@Overridepublic void onCreate() {super.onCreate();createNotificationChannel();startForeground(SERVICE_ID, new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID).build());mMediaProjectionManager = (MediaProjectionManager) getApplicationContext().getSystemService(Context.MEDIA_PROJECTION_SERVICE);}@Overridepublic int onStartCommand(final Intent intent, int flags, int startId) {if (intent != null) {if (intent.getAction() != null) {switch (intent.getAction()) {case ACTION_START:Log.d(TAG, "onStartCommand: start recorder");mMediaProjection = mMediaProjectionManager.getMediaProjection(Activity.RESULT_OK,Objects.requireNonNull(intent.getParcelableExtra(EXTRA_RESULT_DATA)));startCapture();return START_STICKY;case ACTION_SNAPSHOT:
// stopSelf();snapshot();break;case ACTION_STOP:Log.d(TAG, "onStartCommand: close imagereader");if (mImageReader != null){try{mImageReader.close();}catch (Exception exception){Log.e(TAG, "onStartCommand: "+ exception.getMessage() );}}stopSelf();return START_NOT_STICKY;}}}return super.onStartCommand(intent, flags, startId);}private void createNotificationChannel() {NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID,"ScreenRecorder",NotificationManager.IMPORTANCE_DEFAULT);NotificationManager manager = getSystemService(NotificationManager.class);manager.createNotificationChannel(notificationChannel);}private ImageReader mImageReader;private void startCapture() {DisplayMetrics displayMetrics = new DisplayMetrics();WindowManager windowManager = (WindowManager) getSystemService(Context.WINDOW_SERVICE);windowManager.getDefaultDisplay().getMetrics(displayMetrics);int screenWidth = displayMetrics.widthPixels;int screenHeight = displayMetrics.heightPixels;mImageReader = ImageReader.newInstance(screenWidth, screenHeight, PixelFormat.RGBA_8888, 2);mMediaProjection.createVirtualDisplay("mediaprojection", screenWidth, screenHeight,displayMetrics.densityDpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mImageReader.getSurface(), null, null);}private void snapshot(){if (mImageReader != null){Image image = mImageReader.acquireLatestImage();int width = image.getWidth();int height = image.getHeight();final Image.Plane[] planes = image.getPlanes();final ByteBuffer buffer = planes[0].getBuffer();int pixelStride = planes[0].getPixelStride();int rowStride = planes[0].getRowStride();int rowPadding = rowStride - pixelStride * width;Bitmap bitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height,Bitmap.Config.ARGB_8888);bitmap.copyPixelsFromBuffer(buffer);bitmap = Bitmap.createBitmap(bitmap, 0, 0, width, height);//保存图片到本地CommonLib.saveMyBitmap("snapshot", bitmap);image.close();}}
}
AndroidManifest.xml中注册
<!-- 申请权限 />-->
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<service android:name=".ScreenRecorder"android:exported="true"android:foregroundServiceType="mediaProjection"/>
Activity中调用
public void onCreate(Bundle bundle) {super.onCreate(bundle);requestCapturePermission();}
/**
* 申请权限
*/public void requestCapturePermission() {MediaProjectionManager mediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);Intent intent = new Intent(mediaProjectionManager.createScreenCaptureIntent());startActivityForResult(intent, REQUESTRESULT);}
// 回调里面启动服务
@Overrideprotected void onActivityResult(int requestCode, int resultCode, Intent data) {if (resultCode == RESULT_OK) {Intent intent = new Intent(this, ScreenRecorder.class);intent.setAction(ScreenRecorder.ACTION_START);intent.putExtra(ScreenRecorder.EXTRA_RESULT_DATA, data);startForegroundService(intent);EnableTakePhotos = true;}
}
snapshot方法
private void startSnapshot(){Intent intent = new Intent(this, ScreenRecorder.class);intent.setAction(ScreenRecorder.ACTION_SNAPSHOT);startService(intent);
}
可以设置一个按钮,然后在点击事件里面调用startSnapshot()
方法即可
这篇关于Android10以上MediaProjection截屏的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!