屏幕共享几乎是视频呼叫平台的基本功能。 Skype,WhatsApp,电报,团队,Google Meet。所有这些系统都具有此功能。
我们已经解释了how to implement screen sharing into a mobile iOS application。在本文中,我们将解释如何在Android上进行操作。使用代码示例。
在我们的Android系列中的其他文章中,您将学习how to make custom call notification和how we develop WebRTC systems。
屏幕共享实现
您可以在创建新的视频调用时立即启用屏幕共享。
但是,当屏幕共享本身启动后,我们将浏览最常见的情况。
为了简化屏幕共享实现的描述,请说我们已经使用了WeBRTC调用的现成应用程序。阅读有关implementation of the WebRTC video call的更多信息。
实施步骤将如下:
- 访问屏幕内容
- 使用屏幕图像创建视频轨道
- 将相机视频轨道替换为屏幕视频轨道
- 显示正在进行的屏幕共享的通知
现在每个人都详细:
访问屏幕内容
首先,我们可以使用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交换过程。 在本文中,我们介绍了在视频通话中的屏幕共享的实现,以及如何: 请参阅our secure video calling app中的屏幕共享实现的最终结果。
结论