如何实现屏幕共享到您的Android应用程序[2023]。使用代码示例
#android #mobile #webrtc

屏幕共享几乎是视频呼叫平台的基本功能。 Skype,WhatsApp,电报,团队,Google Meet。所有这些系统都具有此功能。

我们已经解释了how to implement screen sharing into a mobile iOS application。在本文中,我们将解释如何在Android上进行操作。使用代码示例。

在我们的Android系列中的其他文章中,您将学习how to make custom call notificationhow we develop WebRTC systems

屏幕共享实现

您可以在创建新的视频调用时立即启用屏幕共享。

但是,当屏幕共享本身启动后,我们将浏览最常见的情况。

为了简化屏幕共享实现的描述,请说我们已经使用了WeBRTC调用的现成应用程序。阅读有关implementation of the WebRTC video call的更多信息。

实施步骤将如下:

  1. 访问屏幕内容
  2. 使用屏幕图像创建视频轨道
  3. 将相机视频轨道替换为屏幕视频轨道
  4. 显示正在进行的屏幕共享的通知

现在每个人都详细:

访问屏幕内容

首先,我们可以使用Media Projection API
访问屏幕内容和设备声音

val screenSharingPermissionLauncher = registerForActivityResult( 
   ActivityResultContracts.StartActivityForResult() 
) { result -> 
   // Handle request result 
   val screenSharingIntent = result.data 
   if (screenSharingIntent != null) { 
       // Success request 
   } 
} 

val mediaProjectionManager = getSystemService(Context.MEDIA_PROJECTION_SERVICE) as MediaProjectionManager 
val intent = mediaProjectionManager.createScreenCaptureIntent() 
screenSharingPermissionLauncher.launch(intent)

呼叫ScreenSharingPermissionLauncher.launch(意图)时,将出现一个对话框窗口。它将告诉用户媒体投影将访问屏幕上显示的所有信息。

由于成功访问屏幕内容,我们获得了屏幕截图

使用屏幕图像创建视频轨道

创建视频关注者,它将从屏幕上捕获图像:

val mediaProjectionCallback = object : MediaProjection.Callback() { 
   override fun onStop() { 
       // screen capture stopped 
   } 
} 
val videoCapturer = ScreenCapturerAndroid(screenSharingIntent, mediaProjectionCallback)

然后创建LocalVideOtrack:

val surfaceTextureHelper = SurfaceTextureHelper.create("CaptureThread", eglBase.eglBaseContext) 
val videoSource = peerConnectionFactory.createVideoSource(/* isScreencast = */ true) 
videoCapturer.initialize(surfaceTextureHelper,context, videoSource.capturerObserver) 
videoCapturer.startCapture(displayWidth, displayHeight, fps) 
val localVideoTrack = peerConnectionFactory.createVideoTrack(VIDEO_TRACK_ID, videoSource) 

将相机视频轨道替换为屏幕视频轨道

要正确替换视频轨道,请为两个呼叫参与者实现重新谈判逻辑。在更改本地媒体曲目时,WEBRTC调用了OnreneGotiation。它重复SDP交换过程:

val peerConnectionObserver = object : PeerConnection.Observer { 
   ... 
   override fun onRenegotiationNeeded() { 
       // Launch sdp exchange 
       peerConnection.createOffer(...) 
   } 
} 
val peerConnection = peerConnectionFactory.createPeerConnection(iceServers, peerConnectionObserver) 

现在要替换视频轨道。从当地媒体中删除相机视频轨道:

localMediaStream.removeTrack(cameraVideoTrack) 

停止捕获相机视频:

cameraVideoCapturer.stopCapture() 

添加屏幕共享视频曲目:

localMediaStream.addTrack(screenVideoTrack) 

显示有关正在进行的屏幕截图的通知

在屏幕共享开始时,有必要在示威开始的通知中运行Foreground Service

创建一个屏幕截图,然后将其添加到AndroidManifest.xml中。还指定ForegroundServiceType参数:

<service 
   android:name=".ScreencastService" 
   android:foregroundServiceType="mediaProjection" 
   android:stopWithTask="true" /> 

用屏幕共享视频轨道从相机替换视频段之前,请启动ScracenCastService:

val intent = Intent(this, ScreencastService::class.java) 
ContextCompat.startForegroundService(this, intent) 

然后,在ScracenCastService(例如,在OnstartCommand())中,调用开始前线方法:

startForeground(NOTIFICATION_ID, notification) 

实施的常见问题

该应用程序在Android 10+设备上使用媒体预测崩溃,需要type serviceinfo.foreground_service_type_media_media_prodoctive工作的前景服务。

前景服务可确保系统不会在屏幕共享期间杀死该应用程序。前景服务通知将告知用户运行屏幕共享,并允许快速返回应用程序。

如何解决:不要忘记显示有关启动屏幕共享ð

的通知

没有替换摄像机视频轨道到屏幕

如果一个或两个呼叫者的侧面未实现识别逻辑(正确)。

如何求解: peerconnection.observer中的替代方法(其他平台上的方法名称可能有所不同)。当调用OnreneGotiationed时,必须启动SDP交换过程。

结论

在本文中,我们介绍了在视频通话中的屏幕共享的实现,以及如何:

  • 使用MediaProcotdion API访问屏幕内容
  • 用屏幕capturerandroid捕获屏幕内容
  • 使用屏幕图像创建本地视频轨道
  • 用屏幕视频轨道替换相机视频轨道
  • 实现显示屏幕截图通知的前景服务

请参阅our secure video calling app中的屏幕共享实现的最终结果。