Android8.0及以上基于系统MediaRecorder实现录屏最基础步骤

Posted 楠之枫雪

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android8.0及以上基于系统MediaRecorder实现录屏最基础步骤相关的知识,希望对你有一定的参考价值。

1.申请到必须的相关权限

  • xml配置,另外需要动态获取权限才行

    <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
    <uses-permission android:name="android.permission.RECORD_AUDIO" />
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
  • notification权限
   private void notificationPermission(Context context) {//判断应用的通知权限是否打开,返回Boolean值
        if (!NotificationManagerCompat.from(context).areNotificationsEnabled()) {
            Intent localIntent = new Intent();
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {//8.0及以上
                localIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                localIntent.setAction("android.settings.APPLICATION_DETAILS_SETTINGS");
                localIntent.setData(Uri.fromParts("package", context.getPackageName(), null));
            } else {
                localIntent.setAction("android.settings.APP_NOTIFICATION_SETTINGS");
                localIntent.putExtra("app_package", context.getPackageName());
                localIntent.putExtra("app_uid", context.getApplicationInfo().uid);
            }
            context.startActivity(localIntent);
        }
    }

2.编写录屏前台服务

  • 在绑定时初始化的数据,包括通过传递过来的数据获取到mediaProjection
@Override
    public IBinder onBind(Intent intent) {
        //创建前台Notification保护
        createNotificationChannel();
        //初始化MediaProjection
        initMediaProjection(intent);
        return new RecordBinder();
    }


    private void initMediaProjection(Intent intent) {
        int mResultCode = intent.getIntExtra("code", -1);
        Intent mResultData = intent.getParcelableExtra("data");
        MediaProjectionManager mMediaProjectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
        mediaProjection = mMediaProjectionManager.getMediaProjection(mResultCode, Objects.requireNonNull(mResultData));
    }


    private void createNotificationChannel() {
        Notification.Builder builder = new Notification.Builder(this.getApplicationContext());
        Intent nfIntent = new Intent(this, MainActivity.class); //点击后跳转的界面,可以设置跳转数据
        builder.setContentIntent(PendingIntent.getActivity(this, 0, nfIntent, 0)) // 设置PendingIntent
                .setLargeIcon(BitmapFactory.decodeResource(this.getResources(), R.mipmap.ic_launcher)) // 设置下拉列表中的图标(大图标)
                .setContentTitle("屏幕录制") // 设置下拉列表里的标题
                .setSmallIcon(R.mipmap.ic_launcher) // 设置状态栏内的小图标
                .setContentText("当前正在录屏中...") // 设置上下文内容
                .setWhen(System.currentTimeMillis()); // 设置该通知发生的时间

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            String notification_id = "notification_screenCap_id";
            String notification_name = "notification_screenCap_name";
            builder.setChannelId(notification_id);
            NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
            NotificationChannel channel = new NotificationChannel(notification_id, notification_name, NotificationManager.IMPORTANCE_LOW);
            notificationManager.createNotificationChannel(channel);
        }
        Notification notification = builder.build();
        notification.defaults = Notification.DEFAULT_SOUND; //设置为默认的声音
        int notification_id1 = 101;
        startForeground(notification_id1, notification);
    }
  • 开启录屏与停止录屏基础方法
 public boolean startRecord() {
        if (mediaProjection == null || running) {
            return false;
        } else {
            try {
                initRecorder();
            } catch (IOException e) {
                e.printStackTrace();
                running = false;
                return false;
            }
            createVirtualDisplay();
            mediaRecorder.start();
            running = true;
        }
        return true;
    }

    public boolean stopRecord() {
        if (running) {
            mediaRecorder.stop();
            mediaRecorder.release();
            virtualDisplay.release();
            mediaProjection.stop();
            mediaRecorder = null;
            return true;
        }
        return false;
    }


    private void createVirtualDisplay() {
        virtualDisplay = mediaProjection.createVirtualDisplay("MainScreen", width, height, dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder.getSurface(), null, null);
    }

    private void initRecorder() throws IOException {
        mediaRecorder = new MediaRecorder();
        mediaRecorder.setAudiosource(MediaRecorder.AudioSource.DEFAULT);
        mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE);
        mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP);
        videoName = System.currentTimeMillis() + ".mp4";
        mediaRecorder.setOutputFile(createSaveVideoFile());
        mediaRecorder.setVideoSize(width, height);
        mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264);
        mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AMR_NB);
        mediaRecorder.setVideoEncodingBitRate(5 * 1024 * 1024);
        mediaRecorder.setVideoFrameRate(30);
        mediaRecorder.prepare();
    }

3.申请录屏服务权限

 projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE);
 Intent captureIntent = projectionManager.createScreenCaptureIntent();
 startActivityForResult(captureIntent, RECORD_REQUEST_CODE);

4.成功后绑定录屏服务

@Override
   protected void onActivityResult(int requestCode, int resultCode, Intent data) {
       super.onActivityResult(requestCode, resultCode, data);
       if (requestCode == RECORD_REQUEST_CODE && resultCode == RESULT_OK) {
           Intent intent = new Intent(this, RecordService.class);
           intent.putExtra("code", resultCode);
           intent.putExtra("data", data);
           bindService(intent, connection, BIND_AUTO_CREATE);
       }
   }
private final ServiceConnection connection = new ServiceConnection() {
       @Override
       public void onServiceConnected(ComponentName className, IBinder service) {
           RecordService.RecordBinder binder = (RecordService.RecordBinder) service;
           recordService = binder.getRecordService();
           DisplayMetrics metrics = new DisplayMetrics();
           getWindowManager().getDefaultDisplay().getMetrics(metrics);
           //设置录屏分辨率
           recordService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi);
           recordService.startRecord();
           startBtn.setEnabled(true);
           startBtn.setText(recordService.isRunning() ? "停止录屏" : "开始录屏");
       }

       @Override
       public void onServiceDisconnected(ComponentName arg0) {
       }
   };

这样后就可以通过ServiceConnection获取到服务的引用了,下面就可以愉快的进行业务逻辑的交互开发吧。

5.初步演示效果

在这里插入图片描述
在这里插入图片描述
转载注明:https://blog.csdn.net/u014614038/article/details/117699817

以上是关于Android8.0及以上基于系统MediaRecorder实现录屏最基础步骤的主要内容,如果未能解决你的问题,请参考以下文章

Android8.0及以上基于系统MediaRecorder实现录屏最基础步骤

Android8.0适配之一应用图标适配

Marshmallow 及以上版本的许可证验证库

在 Android 8.0 以上。有啥方法可以知道系统中是不是开启了 pip 模式

Android 实现通知栏和进度条效果(适用于Android8.0以上)

Android 9.0版本及以上开发时遇到的一些版本问题