android录屏开发总结

android录屏开发总结android 录屏实现 android 录屏

大家好,欢迎来到IT知识分享网。

开始之前先说明一下关键几个类的作用:
  • MediaProjectionManager:录屏主要管理类,发出截屏意图提醒、创建录屏等
  • IBinder:IBinder是Android中的一个接口,它定义了一组用于进程间通信的方法。通过IBinder,我们可以在不同的进程之间传递数据和调用方法,实现进程间的交互。在Android系统中,每个进程都有一个唯一的Binder对象,用于管理该进程中的Binder通信。
  • ServiceConnection:用于管理应用程序和服务之间的连接
  • MediaRecorder:Android sdk提供的一个专门用于音视频录制,一般利用手机麦克风采集音频,摄像头采集图片信息,设置参数等。
  • VirtualDisplay:创建虚拟屏幕
1、注册service组件

录屏需要后台运行服务支持,需要在mannifest中注册service组件

 <service android:name=".ScreenService" android:enabled="true" android:exported="true" android:foregroundServiceType="mediaProjection"/> 
2、activity中通过Intent绑定服务
Intent intent = new Intent(this, ScreenService.class); bindService(intent, mServiceConnection, BIND_AUTO_CREATE); 
  • 首先,绑定开始之后Android系统调用service的onBind()方法,它返回一个用来与service交互的IBinder对象,但是绑定是异步的,他需要通过mServiceConnection里面的方法来传递(后面讲)
//首先,客户端调用bindService绑定的时候会执行service中的onBind这个方法 @Override public IBinder onBind(Intent intent) { return new RecordBinder(); } //service里面的内部类 public class RecordBinder extends Binder { //里面的getRecordService方法,待会activity会调用他 public ScreenService getRecordService() { return ScreenService.this; } } 
  • 这里干了一件事,绑定服务的时候返回一个Binder,这个binder中有一个getRecordService方法,待会客户端activity那边调用这个方法可以直接返回当前的service
  • 刚才讲了绑定的时候传递了一个mServiceConnection对象,上面返回的IBinder对象会在这个类的方法中返回,拿到返回的这个IBinder对象我们就可以调用该对象的方法(这个方法是我们自己写的,返回的是当前的service对象,这样我们就在客户端的activity中拿到了后台运行的service对象)
//这个mServiceConnection对象就是绑定服务的时候传递进去的 private ServiceConnection mServiceConnection = new ServiceConnection() { // 当与service的连接建立后被调用  @Override public void onServiceConnected(ComponentName className, IBinder myBinder) { //ScreenService.RecordBinder是service中的内部类,binder就是我们返回的IBinder对象 ScreenService.RecordBinder binder = (ScreenService.RecordBinder) myBinder; //通过返回的这个IBinder对象去调用他里面的getRecordService方法,的到的时候service对象 ScreenService recordService = binder.getRecordService(); recordService.setConfig(metrics.widthPixels, metrics.heightPixels, metrics.densityDpi); } // 当与service的连接意外断开时被调用 注意是意外断开的时候调用) @Override public void onServiceDisconnected(ComponentName arg0) { } }; 
3. 录制屏幕弹窗提示申请
  • 开始检查权限(存储权限、录音权限,权限不是本文的重点,略过)
  • 权限都在的时候开始申请屏幕录制
//通过MediaProjectionManager这个类来启动,这个是录屏之前的一个保护弹窗,询问你是不是需要开始录屏 //点击同意之后系统会回调到onActivityResult 通过这个REQUEST_CODE_RECORD参数来标识 private MediaProjectionManager projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE); Intent captureIntent = projectionManager.createScreenCaptureIntent(); startActivityForResult(captureIntent, REQUEST_CODE_RECORD); //点击同意之后如下 @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { super.onActivityResult(requestCode, resultCode, data); if (resultCode == RESULT_OK) { if (requestCode == REQUEST_CODE_RECORD)//上述传递的标识参数 { //录屏逻辑 Intent service = new Intent(this, ScreenService.class); service.putExtra("resultCode", resultCode); service.putExtra("requestCode", requestCode); service.putExtra("data", data); //启动service服务,启动服务之后会执行service中的onStartCommand,可以在onStartCommand中做逻辑操作 startForegroundService(service); // handler.postDelayed(runnable, 10*1000);//最多录制10s } } } 
4. 开始录制,启动服务之后执行service中的onStartCommand方法,然后开始录屏逻辑的实现
 @Override public int onStartCommand(Intent intent, int flags, int startId) { int resultCode = intent.getIntExtra("resultCode", -1); int requestCode = intent.getIntExtra("requestCode", -1); Intent resultData = intent.getParcelableExtra("data"); startNotification(); projectionManager = (MediaProjectionManager) getSystemService(MEDIA_PROJECTION_SERVICE); mediaProjection = projectionManager.getMediaProjection(resultCode, resultData);//必须在通知显示之后调用 //录屏 try { startRecord(); } catch (JSONException e) { e.printStackTrace(); } return super.onStartCommand(intent, flags, startId); } private final String NOTIFICATION_CHANNEL_ID="com.yun.screenrecord.MediaService"; private final String NOTIFICATION_CHANNEL_NAME="com.yun.screenrecord.channel_name"; private final String NOTIFICATION_CHANNEL_DESC="com.yun.screenrecord.channel_desc"; public void startNotification() { if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { //Call Start foreground with notification Intent notificationIntent = new Intent(this, ScreenService.class); PendingIntent pendingIntent;//适配31及以上的版本隐式启动 if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) { pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_IMMUTABLE); } else { pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_ONE_SHOT); } NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground)) .setSmallIcon(R.drawable.ic_launcher_foreground) .setContentTitle("Starting recording") .setContentText("Starting screen record service") .setContentIntent(pendingIntent); Notification notification = notificationBuilder.build(); NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, NOTIFICATION_CHANNEL_NAME, NotificationManager.IMPORTANCE_DEFAULT); channel.setDescription(NOTIFICATION_CHANNEL_DESC); NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); notificationManager.createNotificationChannel(channel); startForeground(1, notification); //必须使用此方法显示通知,不能使用notificationManager.notify,否则还是会报上面的错误 } } 
5. 配置录屏的相关操作,完善startRecord代码
 public boolean startRecord() throws JSONException { if (mediaProjection == null || running) { return false; } initRecorder(); createVirtualDisplay(); mediaRecorder.start(); running = true; return true; } private void initRecorder() throws JSONException { CamcorderProfile mProfile = CamcorderProfile.get(CamcorderProfile.QUALITY_1080P); //判断是不是需要声音 if (this.dataOption.get("voiceStatus") == "1"){ mediaRecorder.setAudioSource(MediaRecorder.AudioSource.MIC);//设置声音 } mediaRecorder.setVideoSource(MediaRecorder.VideoSource.SURFACE); mediaRecorder.setOutputFormat(MediaRecorder.OutputFormat.THREE_GPP); //判断是不是需要声音 if (this.dataOption.get("voiceStatus") == "1"){ mediaRecorder.setAudioEncoder(MediaRecorder.AudioEncoder.AAC); } mediaRecorder.setVideoEncoder(MediaRecorder.VideoEncoder.H264); mediaRecorder.setVideoSize(this.width, this.height); mediaRecorder.setVideoFrameRate(30); mediaRecorder.setVideoEncodingBitRate(mProfile.videoBitRate); //设置文件输出路径 mediaRecorder.setOutputFile(''); try { mediaRecorder.prepare(); } catch (IOException e) { e.printStackTrace(); } } / * 创建一个录屏 Virtual */ private void createVirtualDisplay() { //VirtualDisplay录屏功能,主要通过这个类来实现,VirtualDisplay对应虚拟Display,主要用来进行屏幕录制等相关功能 virtualDisplay = mediaProjection .createVirtualDisplay("mediaprojection", width, height, dpi, DisplayManager.VIRTUAL_DISPLAY_FLAG_AUTO_MIRROR, mediaRecorder .getSurface(), null, null); } 
6. 结束录屏
 / * 结束录屏 */ public boolean stopRecord() { if (!running) { return false; } running = false; mediaRecorder.stop(); mediaRecorder.reset(); virtualDisplay.release(); mediaProjection.stop(); return true; }

免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/144339.html

(0)
上一篇 2025-04-27 15:15
下一篇 2025-04-27 15:20

相关推荐

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注

关注微信