Android 5.0以后的录屏和截屏(调用系统)

效果如下:
在这里插入图片描述
开发环境:Android studio 3.4.1,Android 6.0手机一台
添加依赖:【我这里用的是eventbus通信,不用可以不添加】

//线程通讯eventbus
implementation 'org.greenrobot:eventbus:3.1.1'

注1:我这里主要是再录屏的过程中获取了一帧图作为截屏图片,可以播放视频过程中截屏和录屏
注2:按启动顺序上代码哈
1.启动代码

findViewById(R.id.sbtn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                screenGetType = RecordScreenService.TYPE_SHOTSCREEN;
                startRecordScreen();
            }
        });
        findViewById(R.id.rbtn).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                screenGetType = RecordScreenService.TYPE_RECORDSCREEN;
                startRecordScreen();
            }
        });

...
 private void startRecordScreen() {
        L.d("触发录屏服务");
        mMediaProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE);
        //调用系统录屏功能
        startActivityForResult(mMediaProjectionManager.createScreenCaptureIntent(),
                111);
    }

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        super.onActivityResult(requestCode, resultCode, data);
        switch (requestCode) {
            case 111://录屏被同意后返回
                if (resultCode == RESULT_OK && data != null) {
                    L.d("启动录屏服务");
                    Intent service = new Intent(this, RecordScreenService.class);
                    service.putExtra("code", resultCode);
                    service.putExtra("data", data);
                    service.putExtra(RecordScreenService.TYPE_FLAG_NAME, screenGetType);
                    startService(service);
                }
                break;
        }
    }

2.录屏服务类【具体业务处理】

package com.example.syss.syssign;

import android.app.Activity;
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.PixelFormat;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.Image;
import android.media.ImageReader;
import android.media.MediaRecorder;
import android.media.projection.MediaProjection;
import android.media.projection.MediaProjectionManager;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.Nullable;
import android.view.Surface;


import com.example.syss.syssign.utils.EventBean;
import com.example.syss.syssign.utils.FileUtil;
import com.example.syss.syssign.utils.L;
import com.example.syss.syssign.utils.PathUtil;
import com.example.syss.syssign.utils.Tools;

import org.greenrobot.eventbus.EventBus;

import java.io.File;
import java.io.IOException;
import java.nio.ByteBuffer;

/**
 * CreateTime 2020/1/20 09:48
 * Author LiuShiHua
 * Description:录屏和截屏
 */
public class RecordScreenService extends IntentService {

    public static final String TYPE_FLAG_NAME = "TYPE_FLAG";//传递类型名
    public static final int TYPE_SHOTSCREEN = 1;//[返回]类型-截屏
    public static final int TYPE_RECORDSCREEN = 2;//[返回]类型-录屏

    public static final int TYPE_SHOTSCREEN_FAILURE = 3;//返回类型-截屏-失败
    public static final int TYPE_RECORDSCREEN_FAILURE = 4;//返回类型-录屏-失败

    private int mResultCode, mScreenWidth, mScreenHeight;
    private int mScreenDensity;
    private Intent mResultData;
    private Context context;
    private MediaProjection mMediaProjection;
    private MediaRecorder mMediaRecorder;
    private VirtualDisplay mVirtualDisplay;
    private String savePath;//录屏和截屏保存地址
    private Bitmap mBitmap;
    private EventBus bus;

    private final long DELAY_GETCAPTURE = 2000;//延时2秒截屏
    private final long DELAY_GETCAPTURE_STOPRECORD = 2500;//延时2秒截屏后停止录制
    private final long DELAY_STOPRECORD = 6000;//延时5秒停止录制-录屏时长
    private final long DELAY_STOPRECORD_CALLBACK = 1000;//录屏结束后延时1秒返回消息

    private final int HANDLER_STOP_RECORD = 1;//停止录制
    private final int HANDLER_GETCAPTURE = 2;//截取图片
    private final int HANDLER_STOP_RECORD_CALLBACK = 3;//停止录制_返回消息
    private final int HANDLER_RECORD_FAILURE = 4;//录制失败
    private final int HANDLER_GETCAPTURE_SUCCESS = FileUtil.SAVE_FILE_SUCCESS;//截屏成功
    private final int HANDLER_GETCAPTURE_FAILURE = FileUtil.SAVE_FILE_FAILURE;//截屏失败


    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what) {
                case HANDLER_GETCAPTURE_SUCCESS:
                    bus.post(new EventBean("截屏完成", (String) msg.obj, TYPE_SHOTSCREEN));
                    break;
                case HANDLER_GETCAPTURE_FAILURE:
                    bus.post(new EventBean("截屏失败", (String) msg.obj, TYPE_SHOTSCREEN_FAILURE));
                    break;
                case HANDLER_GETCAPTURE:
                    getScreenCapture();
                    break;
                case HANDLER_STOP_RECORD:
                    stopRecord();
                    break;
                case HANDLER_STOP_RECORD_CALLBACK:
                    bus.post(new EventBean("录屏完成", (String) msg.obj, TYPE_RECORDSCREEN));
                    break;
                case HANDLER_RECORD_FAILURE:
                    bus.post(new EventBean("录屏失败", (String) msg.obj, TYPE_RECORDSCREEN_FAILURE));
                    break;
            }
        }
    };
    private int typeFlag;

    public RecordScreenService() {
        super("RecordScreenService");
    }

    @Override
    public void onCreate() {
        super.onCreate();
        this.context = this;
        bus = EventBus.getDefault();
    }

    @Override
    protected void onHandleIntent(@Nullable Intent intent) {
        mResultCode = intent.getIntExtra("code", -1);
        mResultData = intent.getParcelableExtra("data");
        typeFlag = intent.getIntExtra("TYPE_FLAG", TYPE_SHOTSCREEN);
        mScreenWidth = Tools.getScreenW(context);
        mScreenHeight = Tools.getScreenH(context);
        mScreenDensity = (int) Tools.getDensity();
        mMediaProjection = ((MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE))
                .getMediaProjection(Activity.RESULT_OK, mResultData);
        if (typeFlag == TYPE_SHOTSCREEN) {//截屏
            setupImageReader();
            mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
                    mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                    imageReaderSurface, null, null);
            handler.sendEmptyMessageDelayed(HANDLER_GETCAPTURE, DELAY_GETCAPTURE);
            handler.sendEmptyMessageDelayed(HANDLER_STOP_RECORD, DELAY_GETCAPTURE_STOPRECORD);
        } else {//录屏
            mMediaRecorder = createMediaRecorder();
            if (mMediaRecorder == null) return;
            mVirtualDisplay = mMediaProjection.createVirtualDisplay("screen-mirror",
                    mScreenWidth, mScreenHeight, mScreenDensity, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR,
                    mMediaRecorder.getSurface(), null, null);
            mMediaRecorder.start();
            handler.sendEmptyMessageDelayed(HANDLER_STOP_RECORD, DELAY_STOPRECORD);
        }
    }

    private MediaRecorder createMediaRecorder() {
        savePath = PathUtil.getScreenRecordPath();
        File file = new File(savePath);
        if (file.exists()) {
            file.delete();
        } else {
            file.getParentFile().mkdirs();
        }
        try {
            file.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
            L.e("录制屏幕失败,创建文件失败");
            Message message = new Message();
            message.what = HANDLER_RECORD_FAILURE;
            message.obj = "创建文件失败";
            handler.sendMessage(message);
            return null;
        }
        MediaRecorder mediaRecorder = new MediaRecorder();
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.MPEG_4);
        mediaRecorder.setOutputFile(savePath);
        mediaRecorder.setVideoSize(mScreenWidth, mScreenHeight);  //after setVideoSource(), setOutFormat()
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);  //after setOutputFormat()
        mediaRecorder.setVideoFrameRate(30);
        mediaRecorder.setVideoEncodingBitRate(2000 * 1024);//越大清晰度越高
        try {
            mediaRecorder.prepare();
        } catch (IllegalStateException | IOException e) {
            e.printStackTrace();
            mediaRecorder = null;
            Message message = new Message();
            message.what = HANDLER_RECORD_FAILURE;
            message.obj = "MediaRecorder创建失败";
            handler.sendMessage(message);
        }
        return mediaRecorder;
    }

    private ImageReader imageReader;
    private Surface imageReaderSurface;

    private void setupImageReader() {
        //前三个参数分别是需要的尺寸和格式,最后一个参数代表每次最多获取几帧数据,本例的3代表ImageReader中最多可以获取2帧图像流
        imageReader = ImageReader.newInstance(mScreenWidth, mScreenHeight, PixelFormat.RGBA_8888, 2);
        //获取ImageReader的Surface
        imageReaderSurface = imageReader.getSurface();
    }

    private void getScreenCapture() {
        savePath = PathUtil.getScreenShotsPath();
        Image image = imageReader.acquireLatestImage();
        if (image != null) {
            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;
            if (mBitmap == null) {
                mBitmap = Bitmap.createBitmap(width + rowPadding / pixelStride, height, Bitmap.Config.ARGB_8888);
            }
            mBitmap.copyPixelsFromBuffer(buffer);
            if (mBitmap != null) {
                FileUtil.saveBitmapToImage(mBitmap, savePath, handler);
            } else {
                L.e("获取图片失败");
                Message message = new Message();
                message.what = HANDLER_GETCAPTURE_FAILURE;
                message.obj = "获取图片失败";
                handler.sendMessage(message);
            }
            image.close();
        }
    }

    private void stopRecord() {
        if (mVirtualDisplay != null) {
            mVirtualDisplay.release();
            mVirtualDisplay = null;
        }
        if (mMediaRecorder != null) {
            mMediaRecorder.setOnErrorListener(null);
            mMediaProjection.stop();
            mMediaRecorder.reset();
        }
        if (mMediaProjection != null) {
            mMediaProjection.stop();
            mMediaProjection = null;
        }
        if (typeFlag == TYPE_RECORDSCREEN) {
            L.e("录制屏幕结束:" + savePath);
            Message message = new Message();
            message.what = HANDLER_STOP_RECORD_CALLBACK;
            message.obj = savePath;
            handler.sendMessageDelayed(message, DELAY_STOPRECORD_CALLBACK);
        }
    }
}

3.截屏,录屏后返回处理Activity中添加Eventbus接收方法

@Subscribe(threadMode = ThreadMode.MAIN)
    public void onMessage(EventBean bean) {
        text.setText(text.getText().toString() + "\n" + bean.getMsg());
        if (bean.getType() == null || bean.getContent() == null) return;
        int type = bean.getType();
        switch (type) {
            case RecordScreenService.TYPE_SHOTSCREEN://截屏成功返回
                Glide.with(this).asBitmap().load(bean.getContent()).into(image);//加载到imageview中
                break;
            case RecordScreenService.TYPE_SHOTSCREEN_FAILURE:
                image.setImageDrawable(null);
                break;
            case RecordScreenService.TYPE_RECORDSCREEN://录屏成功返回
                videoPlayerUtil.play(bean.getContent(), false);//播放
                break;
            case RecordScreenService.TYPE_RECORDSCREEN_FAILURE:

                break;
        }
    }

其他类说明:
L类:日志Log
Tools类:获取了屏幕的宽高和密度
PathUtil类:获取配置的路径
FileUtil类:将bitmap存储为图片文件

  • 3
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Android 9.0 及更高版本中,您可以使用 MediaProjection API 来设置应用程序禁用系统录屏。您可以通过以下方式实现: 1. 在您的 AndroidManifest.xml 文件中添加以下权限: ``` <uses-permission android:name="android.permission.MEDIA_CONTENT_CONTROL" /> ``` 2. 在您的 Activity 或 Service 中,使用以下代码请求媒体投影权限: ```java private static final int REQUEST_CODE_SCREEN_CAPTURE = 1; private MediaProjectionManager mProjectionManager; private MediaProjection mMediaProjection; private void requestScreenCapturePermission() { mProjectionManager = (MediaProjectionManager) getSystemService(Context.MEDIA_PROJECTION_SERVICE); startActivityForResult(mProjectionManager.createScreenCaptureIntent(), REQUEST_CODE_SCREEN_CAPTURE); } @Override protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) { super.onActivityResult(requestCode, resultCode, data); if (requestCode == REQUEST_CODE_SCREEN_CAPTURE && resultCode == RESULT_OK) { mMediaProjection = mProjectionManager.getMediaProjection(resultCode, data); // 在此处执行禁用系统录屏的逻辑 } } ``` 3. 在获取到 MediaProjection 对象后,您可以使用 `mMediaProjection.createVirtualDisplay()` 方法创建一个虚拟显示器,并通过 `Display.FLAG_SECURE` 标志来禁用系统录屏: ```java private static final int DISPLAY_WIDTH = 720; private static final int DISPLAY_HEIGHT = 1280; private static final int DISPLAY_DPI = 320; private void createVirtualDisplay() { VirtualDisplay virtualDisplay = mMediaProjection.createVirtualDisplay( "MyVirtualDisplay", DISPLAY_WIDTH, DISPLAY_HEIGHT, DISPLAY_DPI, DisplayManager.VIRTUAL_DISPLAY_FLAG_OWN_CONTENT_ONLY | DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC | Display.FLAG_SECURE, null, null ); } ``` 这样,您就可以在您的应用程序中禁用系统录屏了。注意,这只会影响到 Android 9.0 及更高版本的系统。在之前的版本中,您无法禁用系统录屏

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值