홀로렌즈2 화면을 안드로이드 앱에서 보기

PanaxW·3일 전
0

Android

목록 보기
17/21

홀로렌즈 2는 웹에서 실시간 스트리밍을 지원하는 API를 제공

이 API를 활용하면 앱에서도 화면 미러링을 할 수 있음

본 글에서는 ExoPlayer를 이용해 미러링을 구현하는 방법을 소개

📱 테스트 환경

  • Galaxy Tab S6 Lite, Galaxy Z Flip 4
  • Android API 33
  • ExoPlayer 버전: media3:1.3.1

🔧 ExoPlayer 설정

라이브러리 버전 설정, 아래 코드는 libs.versions.toml 파일 기준준

media3 = "1.3.1"

media-exoplayer = { group = "androidx.media3", name = "media3-exoplayer", version.ref = "media3" }
media-exoplayer-dash = { group = "androidx.media3", name = "media3-exoplayer-dash", version.ref = "media3" }
media-ui = { group = "androidx.media3", name = "media3-ui", version.ref = "media3" }

dependencies {
    implementation(libs.media.exoplayer)
    implementation(libs.media.exoplayer.dash)
    implementation(libs.media.ui)
}

🚨 문제 1: 인증서 오류 (HTTPS)

스트리밍 API는 HTTPS로 제공되는데, 인증서를 신뢰하지 못하면 오류가 발생

이를 우회하려면 인증서를 강제로 신뢰하도록 설정해야 함

✅ Application에 인증서 무시 로직 추가

class TestApplication : Application() {
    override fun onCreate() {
        super.onCreate()
        disableSSLCertificateChecking()
    }

    private fun disableSSLCertificateChecking() {
        val trustAllCerts: Array<TrustManager> = arrayOf(
            object : X509TrustManager {
                override fun checkClientTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
                override fun checkServerTrusted(chain: Array<out X509Certificate>?, authType: String?) {}
                override fun getAcceptedIssuers(): Array<X509Certificate> = arrayOf()
            }
        )

        try {
            val sc = SSLContext.getInstance("TLS")
            sc.init(null, trustAllCerts, SecureRandom())

            // 반드시 설정
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.socketFactory)

            // 선택 사항
            HttpsURLConnection.setDefaultHostnameVerifier { _, _ -> true }

        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}

Manifest에 Application 추가

<application
    android:name=".TestApplication"
    ... />

🔐 문제 2: 인증 헤더 추가

홀로렌즈 API는 인증이 필요하며, 아이디와 비밀번호를 Base64로 인코딩한 값을 Authorization 헤더에 포함시켜야 함

예시

"Authorization": "Basic Zm9ybWFsd29ya3M6Zm9ybWFsd29ya3M="
  • "아이디:비밀번호" 문자열을 Base64로 인코딩

🎞 DataSourceFactory 구현

@OptIn(UnstableApi::class)
private fun getSourceFactory(): DataSource.Factory {
    val defaultFactory = DefaultHttpDataSource.Factory()
        .setUserAgent(Util.getUserAgent(this, getString(R.string.app_name)))

    val headers = mapOf(
        "Authorization" to "Basic Zm9ybWFsd29ya3M6Zm9ybWFsd29ya3M="
    )

    return ResolvingDataSource.Factory(defaultFactory) { spec ->
        spec.withAdditionalHeaders(headers)
    }
}

▶️ ExoPlayer 연결

@OptIn(UnstableApi::class)
private fun getExoPlayer(): ExoPlayer {
    val mediaItem = MediaItem.Builder().setUri(streamUri).build()
    val mediaSource = ProgressiveMediaSource.Factory(getSourceFactory())
        .createMediaSource(mediaItem)

    return ExoPlayer.Builder(this)
        .setLoadControl(DefaultLoadControl())
        .setTrackSelector(DefaultTrackSelector(this))
        .build().apply {
            setMediaSource(mediaSource)
            playWhenReady = true
            repeatMode = Player.REPEAT_MODE_OFF
        }
}

🔗 스트리밍 URI 예시

private val streamUri =
    "https://~~~~~~~~~~/api/holographic/stream/live_low.mp4?holo=true&pv=false&mic=false&loopback=false&RenderFromCamera=true"

📚 참고 문서

✅ 결론

  1. 인증서 신뢰 우회 (HTTPS)
  2. 인증 헤더 처리 (Basic Auth)
  3. ExoPlayer에서 DataSource.Factory 커스터마이징
profile
Android Developer

0개의 댓글