Я делаю приложение для трансляции экрана телефона на веб-сайт, и оно продолжает сбиваться с этим исключением, я пробовал много вещей, но ни один из них не работает, я проверил свой logcat (мое устройство-эмулятор, средний телефон 36), я получаю эту ошибку: < /p>
Вот код для службы Secren Share < /p>
import android.app.Notification
import android.app.NotificationChannel
import android.app.NotificationManager
import android.app.Service
import android.content.Intent
import android.content.pm.ServiceInfo
import android.media.projection.MediaProjection
import android.media.projection.MediaProjectionManager
import android.os.IBinder
import android.util.Log
import androidx.core.app.NotificationCompat
import kotlinx.coroutines.CoroutineScope
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.SupervisorJob
import kotlinx.coroutines.cancelChildren
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.asStateFlow
import org.java_websocket.client.WebSocketClient
import org.java_websocket.handshake.ServerHandshake
import org.json.JSONObject
import org.webrtc.EglBase
import org.webrtc.IceCandidate
import org.webrtc.MediaConstraints
import org.webrtc.ScreenCapturerAndroid
import org.webrtc.SdpObserver
import org.webrtc.SessionDescription
import org.webrtc.SurfaceTextureHelper
import org.webrtc.VideoSource
import org.webrtc.VideoTrack
import java.net.URI
class ScreenShareService : Service() {
var mediaProjection : MediaProjection? = null
private lateinit var webRTCManager: WebRTCManager
private lateinit var permissionDataIntent: Intent
private var capturer: ScreenCapturerAndroid? = null
private var surfaceTextureHelper: SurfaceTextureHelper? = null
companion object {
var _isServiceRunning = MutableStateFlow(false)
val isServiceRunning = _isServiceRunning.asStateFlow()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
startForegroundServiceWithNotification()
if (intent?.getStringExtra("action") == "stop") {
stopSelf()
return START_NOT_STICKY
}
val resultCode = intent?.getIntExtra("resultCode", -1) ?: return START_NOT_STICKY
val data = intent.getParcelableExtra("data") ?: return START_NOT_STICKY
permissionDataIntent = data
val mediaProjectionManager = getSystemService(MediaProjectionManager::class.java)
mediaProjection = mediaProjectionManager.getMediaProjection(resultCode, data)
mediaProjection?.registerCallback(mediaProjectionCallback, null)
setupWebRTCVideo(mediaProjection!!)
connectToSignalingServer()
_isServiceRunning.value = true
return START_STICKY
}
override fun onCreate() {
super.onCreate()
webRTCManager = WebRTCManager(applicationContext)
}
private fun startForegroundServiceWithNotification() {
val channelId = "screen_share_channel"
val channelName = "Screen Sharing"
val chan = NotificationChannel(channelId, channelName, NotificationManager.IMPORTANCE_LOW)
val manager = getSystemService(NotificationManager::class.java)
manager.createNotificationChannel(chan)
val notification: Notification = NotificationCompat.Builder(this, channelId)
.setContentTitle("Screen Sharing")
.setContentText("Your screen is being shared.")
.setSmallIcon(R.drawable.ic_launcher_foreground)
.build()
startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PROJECTION)
}
private fun releaseResources() {
// Stop the MediaProjection
mediaProjection?.unregisterCallback(mediaProjectionCallback)
mediaProjection?.stop()
mediaProjection = null
// Safely stop and dispose of the capturer
try {
capturer?.stopCapture() // Safe stop if the capturer is not null
} catch (e: Exception) {
e.printStackTrace() // Log any exceptions if stopCapture fails
} finally {
capturer?.dispose() // Always dispose of capturer after stopping it
capturer = null
}
// Dispose of the SurfaceTextureHelper
surfaceTextureHelper?.dispose()
surfaceTextureHelper = null
// Dispose of videoSource AFTER capturer has been disposed
videoSource.dispose()
}
private val mediaProjectionCallback = object : MediaProjection.Callback() {
override fun onStop() {
super.onStop()
_isServiceRunning.value = false
releaseResources()
}
}
override fun onDestroy() {
super.onDestroy()
signalingWebSocket.close()
_isServiceRunning.value = false
serviceScope.coroutineContext.cancelChildren()
}
private val serviceScope = CoroutineScope(SupervisorJob() + Dispatchers.Main)
private lateinit var eglBase: EglBase
private lateinit var videoSource: VideoSource
private lateinit var videoTrack: VideoTrack
private fun setupWebRTCVideo(mediaProjection: MediaProjection) {
eglBase = EglBase.create()
val peerConnectionFactory = webRTCManager.getPeerConnectionFactory()
webRTCManager.createPeerConnection(emptyList()) { iceCandidate ->
sendIceCandidateToWeb(iceCandidate)
}
surfaceTextureHelper = SurfaceTextureHelper.create("ScreenCaptureThread", eglBase.eglBaseContext)
videoSource = peerConnectionFactory.createVideoSource(false)
capturer = ScreenCapturerAndroid(
permissionDataIntent,
object : MediaProjection.Callback() {
override fun onStop() {
_isServiceRunning.value = false
releaseResources()
super.onStop()
}
}
)
capturer?.initialize(surfaceTextureHelper, applicationContext, videoSource.capturerObserver)
capturer?.startCapture(resources.displayMetrics.widthPixels, resources.displayMetrics.heightPixels, 30) // width, height, fps
videoTrack = peerConnectionFactory.createVideoTrack("screen_track", videoSource)
webRTCManager.addVideoTrackToPeerConnection(videoTrack)
Log.d("ScreenShareService", "WebSocket connected, creating offer")
// Move createOffer inside onOpen
webRTCManager.createOffer { sessionDescription ->
sendOfferToWeb(sessionDescription.description)
}
}
private lateinit var signalingWebSocket: WebSocketClient
private fun connectToSignalingServer() {
signalingWebSocket = object : WebSocketClient(URI("ws://192.168.1.184:8080")) {
override fun onOpen(handshakedata: ServerHandshake?) {
// WebSocket connection opened
}
override fun onMessage(message: String?) {
message?.let {
try {
val jsonMessage = JSONObject(it)
when (jsonMessage.getString("type")) {
"offer" -> {
val sdp = jsonMessage.getString("sdp")
createAnswer(sdp)
}
"candidate" -> {
val candidate = jsonMessage.getString("candidate")
val sdpMid = jsonMessage.getString("sdpMid")
val sdpMLineIndex = jsonMessage.getInt("sdpMLineIndex")
webRTCManager.addIceCandidate(sdpMid, sdpMLineIndex, candidate)
}
}
} catch (e: Exception) {
e.printStackTrace()
}
}
}
override fun onClose(code: Int, reason: String?, remote: Boolean) {
// WebSocket connection closed
}
override fun onError(ex: Exception?) {
ex?.printStackTrace()
}
}
signalingWebSocket.connect()
}
private fun createAnswer(sdpOffer: String) {
val sessionDescription = SessionDescription(SessionDescription.Type.OFFER, sdpOffer)
webRTCManager.getPeerConnection()?.setRemoteDescription(object : SdpObserver {
override fun onCreateSuccess(sessionDescription: SessionDescription?) {}
override fun onSetSuccess() {
webRTCManager.getPeerConnection()?.createAnswer(object : SdpObserver {
override fun onCreateSuccess(answer: SessionDescription?) {
answer?.let {
webRTCManager.getPeerConnection()?.setLocalDescription(this, it)
val signalingMessage = JSONObject().apply {
put("type", "answer")
put("sdp", it.description)
}
signalingWebSocket.send(signalingMessage.toString())
}
}
override fun onSetSuccess() {}
override fun onCreateFailure(error: String?) {}
override fun onSetFailure(error: String?) {}
}, MediaConstraints())
}
override fun onCreateFailure(error: String?) {}
override fun onSetFailure(error: String?) {}
}, sessionDescription)
}
// Sending an offer
private fun sendOfferToWeb(offerSdp: String) {
val signalingMessage = JSONObject().apply {
put("type", "offer")
put("sdp", offerSdp)
}
signalingWebSocket.send(signalingMessage.toString())
}
// Sending ICE candidates
private fun sendIceCandidateToWeb(iceCandidate: IceCandidate) {
val signalingMessage = JSONObject().apply {
put("type", "candidate")
put("candidate", iceCandidate.sdp)
put("sdpMid", iceCandidate.sdpMid)
put("sdpMLineIndex", iceCandidate.sdpMLineIndex)
}
signalingWebSocket.send(signalingMessage.toString())
}
fun getSignalingWebSocket(): WebSocketClient {
return signalingWebSocket
}
inner class LocalBinder : android.os.Binder() {
fun getService(): ScreenShareService = this@ScreenShareService
}
override fun onBind(intent: Intent?): IBinder {
return LocalBinder()
}
}
< /code>
Это мой манифестный файл: < /p>
Подробнее здесь: https://stackoverflow.com/questions/795 ... projection
Как исправить java.lang.securityexception: Запуск FGS с типом медиапрокации ⇐ Android
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение
-
-
Почему требуется `java.lang.SecurityException: Запрещенное имя пакета: java`?
Anonymous » » в форуме JAVA - 0 Ответы
- 16 Просмотры
-
Последнее сообщение Anonymous
-