Android10以上MediaProjection截屏

起因

在系统升级到Android10以上之后,之前的截屏方式不能用了,而且必须将MediaProjection放在forground service里面跑才行。网上搜了一圈,都是语焉不详或者没有完整的一个代码应用。只能自己写一个,记录下

代码实现

新建一个ScreenRecorder.java


public class ScreenRecorder extends Service {
    @Nullable
    @Override
    public 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";

    @Override
    public void onCreate() {
        super.onCreate();
        createNotificationChannel();
        startForeground(SERVICE_ID, new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID).build());
        mMediaProjectionManager = (MediaProjectionManager) getApplicationContext().getSystemService(Context.MEDIA_PROJECTION_SERVICE);
    }

    @Override
    public 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);
 }
// 回调里面启动服务
@Override
 protected 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()方法即可

相关推荐

  1. Android10以上MediaProjection

    2024-04-21 10:30:02       38 阅读
  2. Android 10.0 流程

    2024-04-21 10:30:02       32 阅读
  3. Android11系统去掉功能

    2024-04-21 10:30:02       12 阅读
  4. 高通Android 12/Android 13

    2024-04-21 10:30:02       9 阅读
  5. Android方法

    2024-04-21 10:30:02       26 阅读
  6. Android13系统长按power键关机弹框中添加按钮

    2024-04-21 10:30:02       30 阅读
  7. 使用 ADB 命令在 Android 设备上进行

    2024-04-21 10:30:02       12 阅读
  8. adb 脚本化Android系统图和录

    2024-04-21 10:30:02       8 阅读

最近更新

  1. TCP协议是安全的吗?

    2024-04-21 10:30:02       18 阅读
  2. 阿里云服务器执行yum,一直下载docker-ce-stable失败

    2024-04-21 10:30:02       19 阅读
  3. 【Python教程】压缩PDF文件大小

    2024-04-21 10:30:02       18 阅读
  4. 通过文章id递归查询所有评论(xml)

    2024-04-21 10:30:02       20 阅读

热门阅读

  1. 欢迎 Llama 3:Meta 的新一代开源大语言模型

    2024-04-21 10:30:02       14 阅读
  2. npm环境搭建

    2024-04-21 10:30:02       49 阅读
  3. 数据结构(data structure)(2)链表的运用

    2024-04-21 10:30:02       22 阅读
  4. React-RTK

    React-RTK

    2024-04-21 10:30:02      15 阅读
  5. 基于微信小程序的房屋租赁管理系统

    2024-04-21 10:30:02       16 阅读
  6. 迁移学习入门

    2024-04-21 10:30:02       14 阅读
  7. TensorFlow 的基本概念和使用场景

    2024-04-21 10:30:02       15 阅读
  8. 【微服务】Gateway的基本配置详解

    2024-04-21 10:30:02       17 阅读
  9. pytorch中torch.roll用法说明

    2024-04-21 10:30:02       17 阅读