@24i/smartapps-bigscreen-rnv-build-engine 5.0.0-alpha.16 → 5.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/build-freshness.js +158 -0
- package/dist/.build-freshness.json +1010 -0
- package/dist/templates/platforms/firetv/project/README.md +196 -0
- package/dist/templates/platforms/firetv/project/amazoniap/build.gradle +41 -0
- package/dist/templates/platforms/firetv/project/amazoniap/consumer-rules.pro +0 -0
- package/dist/templates/platforms/firetv/project/amazoniap/proguard-rules.pro +21 -0
- package/dist/templates/platforms/firetv/project/amazoniap/src/main/kotlin/com/twentyfouri/bridgetv/amazoniap/AmazonIapService.kt +91 -0
- package/dist/templates/platforms/firetv/project/amazoniap/src/main/kotlin/com/twentyfouri/bridgetv/amazoniap/AmazonIapServiceFactory.kt +13 -0
- package/dist/templates/platforms/firetv/project/app/build.gradle +138 -0
- package/dist/templates/platforms/firetv/project/app/proguard-rules.pro +47 -0
- package/dist/templates/platforms/firetv/project/app/src/bigscreenAppstage/kotlin/com/twentyfouri/tvbridge/Flavor.kt +9 -0
- package/dist/templates/platforms/firetv/project/app/src/bigscreenAppstage/res/raw/configuration.json +8 -0
- package/dist/templates/platforms/firetv/project/app/src/main/AndroidManifest.xml +52 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/FlavorBase.kt +9 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/bridge/BridgeFromJavaScript.kt +421 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/bridge/BridgeToJavaScript.kt +121 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/configuration/BridgeConfig.kt +19 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/configuration/ConfigCallback.kt +6 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/configuration/ConfigProvider.kt +27 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/configuration/Drm.kt +10 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/configuration/UserAgent.kt +6 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/BaseApplication.kt +73 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/di/ActivityComponent.kt +13 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/di/ActivityModule.kt +14 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/di/ApplicationComponent.kt +23 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/di/ApplicationModule.kt +51 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/di/PerActivity.kt +26 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/LocalStorage.kt +30 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/LoggingDrmCallback.kt +38 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/OverriddenHttpMediaDrmCallback.kt +134 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/PlayerFactoryBitmovinCustomized.kt +19 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/PlayerFactoryConfigured.kt +37 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/PlayerFactoryExoPlayerCustomized.kt +106 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/PlayerFactoryExoPlayerNpaw.kt +581 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/PlayerFactoryVersion.kt +27 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/SimpleActivityLifecycleCallback.kt +32 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/global/utils/SourceDrmOverridden.kt +91 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/sound/TouchPlayer.kt +86 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/client/BridgeWebView.kt +82 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/client/BridgeWebViewClient.kt +114 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/model/AnalyticsPlaybackInfo.kt +10 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/model/ContentModel.kt +14 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/model/DrmModel.kt +20 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/model/MediaEventType.kt +31 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/parser/PlaybackInfoParser.kt +10 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/parser/SourceParser.kt +89 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/parser/TrackJsonModelParser.kt +58 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/view/Mainview.kt +18 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/view/PlayerCache.kt +15 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/view/WebViewActivity.kt +252 -0
- package/dist/templates/platforms/firetv/project/app/src/main/kotlin/com/twentyfouri/tvbridge/webview/viewmodel/WebViewModel.kt +748 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/drawable/button_background_focus.xml +10 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/drawable/button_background_normal.xml +7 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/drawable/button_background_pressed.xml +7 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/drawable/button_focus.xml +8 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/layout/activity_web_view.xml +28 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/raw/click.ogg +0 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/values/styles.xml +12 -0
- package/dist/templates/platforms/firetv/project/app/src/main/res/xml/network_security_config.xml +4 -0
- package/dist/templates/platforms/firetv/project/build.gradle +45 -0
- package/dist/templates/platforms/firetv/project/common/build.gradle +41 -0
- package/dist/templates/platforms/firetv/project/common/consumer-rules.pro +0 -0
- package/dist/templates/platforms/firetv/project/common/proguard-rules.pro +21 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/Util.kt +11 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/iap/IapCallback.kt +11 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/iap/IapException.kt +14 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/iap/IapProduct.kt +16 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/iap/IapPurchase.kt +9 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/iap/IapService.kt +14 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/iap/IapServiceFactory.kt +8 -0
- package/dist/templates/platforms/firetv/project/common/src/main/kotlin/com/twentyfouri/tvbridge/common/iap/NullIapService.kt +32 -0
- package/dist/templates/platforms/firetv/project/googleiap/build.gradle +41 -0
- package/dist/templates/platforms/firetv/project/googleiap/consumer-rules.pro +0 -0
- package/dist/templates/platforms/firetv/project/googleiap/proguard-rules.pro +21 -0
- package/dist/templates/platforms/firetv/project/googleiap/src/main/kotlin/com/twentyfouri/tvbridge/googleiap/GoogleIapService.kt +6 -0
- package/dist/templates/platforms/firetv/project/googleiap/src/main/kotlin/com/twentyfouri/tvbridge/googleiap/GoogleIapServiceFactory.kt +13 -0
- package/dist/templates/platforms/firetv/project/gradle/wrapper/gradle-wrapper.jar +0 -0
- package/dist/templates/platforms/firetv/project/gradle/wrapper/gradle-wrapper.properties +7 -0
- package/dist/templates/platforms/firetv/project/gradle.properties +4 -0
- package/dist/templates/platforms/firetv/project/gradlew +251 -0
- package/dist/templates/platforms/firetv/project/gradlew.bat +94 -0
- package/dist/templates/platforms/firetv/project/proguard-rules.pro +42 -0
- package/dist/templates/platforms/firetv/project/settings.gradle +4 -0
- package/index.js +2 -31
- package/package.json +7 -3
- package/project.json +96 -0
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.di
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import com.twentyfouri.tvbridge.webview.viewmodel.WebViewModel
|
|
5
|
+
import dagger.Component
|
|
6
|
+
import javax.inject.Provider
|
|
7
|
+
|
|
8
|
+
@PerActivity
|
|
9
|
+
@Component(dependencies = [ApplicationComponent::class], modules = [ActivityModule::class])
|
|
10
|
+
interface ActivityComponent : ApplicationComponent {
|
|
11
|
+
val activity: Activity
|
|
12
|
+
val viewModelFactory: Provider<WebViewModel>
|
|
13
|
+
}
|
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.di
|
|
2
|
+
|
|
3
|
+
import android.app.Activity
|
|
4
|
+
import dagger.Module
|
|
5
|
+
import dagger.Provides
|
|
6
|
+
|
|
7
|
+
@Module
|
|
8
|
+
class ActivityModule(
|
|
9
|
+
private val activity: Activity
|
|
10
|
+
) {
|
|
11
|
+
@Provides
|
|
12
|
+
fun provideActivity() =
|
|
13
|
+
activity
|
|
14
|
+
}
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.di
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.twentyfouri.player.base.PlayerFactoryBase
|
|
5
|
+
import com.twentyfouri.tvbridge.common.iap.IapService
|
|
6
|
+
import com.twentyfouri.tvbridge.configuration.BridgeConfig
|
|
7
|
+
import com.twentyfouri.tvbridge.global.BaseApplication
|
|
8
|
+
import com.twentyfouri.tvbridge.global.utils.LocalStorage
|
|
9
|
+
import com.twentyfouri.tvbridge.sound.TouchPlayer
|
|
10
|
+
import dagger.Component
|
|
11
|
+
import javax.inject.Singleton
|
|
12
|
+
|
|
13
|
+
@Singleton
|
|
14
|
+
@Component(modules = [ApplicationModule::class])
|
|
15
|
+
interface ApplicationComponent {
|
|
16
|
+
val application: BaseApplication
|
|
17
|
+
val localStorage: LocalStorage
|
|
18
|
+
val configuration: BridgeConfig
|
|
19
|
+
val playerFactory: PlayerFactoryBase
|
|
20
|
+
val applicationContext: Context
|
|
21
|
+
val touchPlayer: TouchPlayer
|
|
22
|
+
val iapService: IapService
|
|
23
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.di
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.twentyfouri.player.base.PlayerFactoryBase
|
|
5
|
+
import com.twentyfouri.tvbridge.Flavor
|
|
6
|
+
import com.twentyfouri.tvbridge.common.iap.NullIapService
|
|
7
|
+
import com.twentyfouri.tvbridge.configuration.BridgeConfig
|
|
8
|
+
import com.twentyfouri.tvbridge.global.BaseApplication
|
|
9
|
+
import com.twentyfouri.tvbridge.global.utils.LocalStorage
|
|
10
|
+
import com.twentyfouri.tvbridge.global.utils.PlayerFactoryConfigured
|
|
11
|
+
import com.twentyfouri.tvbridge.sound.TouchPlayer
|
|
12
|
+
import dagger.Module
|
|
13
|
+
import dagger.Provides
|
|
14
|
+
import javax.inject.Singleton
|
|
15
|
+
|
|
16
|
+
@Module
|
|
17
|
+
class ApplicationModule(
|
|
18
|
+
private val baseApplication: BaseApplication,
|
|
19
|
+
private val configuration: BridgeConfig
|
|
20
|
+
) {
|
|
21
|
+
@Provides
|
|
22
|
+
fun getApplication() = baseApplication
|
|
23
|
+
|
|
24
|
+
@Provides
|
|
25
|
+
fun getConfiguration() = configuration
|
|
26
|
+
|
|
27
|
+
@Provides
|
|
28
|
+
fun provideApplicationContext(): Context = baseApplication
|
|
29
|
+
|
|
30
|
+
@Singleton
|
|
31
|
+
@Provides
|
|
32
|
+
fun provideLocalStorage() = LocalStorage(baseApplication.applicationContext)
|
|
33
|
+
|
|
34
|
+
@Singleton
|
|
35
|
+
@Provides
|
|
36
|
+
fun provideTouchPlayer() = TouchPlayer(baseApplication)
|
|
37
|
+
|
|
38
|
+
@Singleton
|
|
39
|
+
@Provides
|
|
40
|
+
fun provideIapService() = Flavor
|
|
41
|
+
.iapServiceFactories
|
|
42
|
+
.firstOrNull { it.detectSupport(baseApplication) }
|
|
43
|
+
?.build(baseApplication)
|
|
44
|
+
?: NullIapService()
|
|
45
|
+
|
|
46
|
+
@Provides
|
|
47
|
+
@Singleton
|
|
48
|
+
fun providePlayerFactory(config: BridgeConfig): PlayerFactoryBase =
|
|
49
|
+
PlayerFactoryConfigured.buildFactory(config, baseApplication)
|
|
50
|
+
|
|
51
|
+
}
|
|
@@ -0,0 +1,26 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.di
|
|
2
|
+
|
|
3
|
+
import javax.inject.Scope
|
|
4
|
+
|
|
5
|
+
/*
|
|
6
|
+
* Copyright (C) 2013 Square, Inc.
|
|
7
|
+
*
|
|
8
|
+
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
9
|
+
* you may not use this file except in compliance with the License.
|
|
10
|
+
* You may obtain a copy of the License at
|
|
11
|
+
*
|
|
12
|
+
* http://www.apache.org/licenses/LICENSE-2.0
|
|
13
|
+
*
|
|
14
|
+
* Unless required by applicable law or agreed to in writing, software
|
|
15
|
+
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
16
|
+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
17
|
+
* See the License for the specific language governing permissions and
|
|
18
|
+
* limitations under the License.
|
|
19
|
+
*/ /**
|
|
20
|
+
* A scoping annotation to permit objects whose lifetime should
|
|
21
|
+
* conform to the life of the activity to be memoized in the
|
|
22
|
+
* correct component.
|
|
23
|
+
*/
|
|
24
|
+
@Scope
|
|
25
|
+
@kotlin.annotation.Retention(AnnotationRetention.RUNTIME)
|
|
26
|
+
annotation class PerActivity
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.utils
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import android.content.SharedPreferences
|
|
5
|
+
|
|
6
|
+
class LocalStorage(context: Context) {
|
|
7
|
+
|
|
8
|
+
private val preferences: SharedPreferences =
|
|
9
|
+
context.applicationContext.getSharedPreferences(SHARED_PREFERENCES, Context.MODE_PRIVATE)
|
|
10
|
+
|
|
11
|
+
fun saveCookieJson(key: String?, value: String?) {
|
|
12
|
+
val editor = preferences.edit()
|
|
13
|
+
editor.putString(key, value)
|
|
14
|
+
editor.apply()
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
fun removeFromLocalStorage(key: String?) {
|
|
18
|
+
val editor = preferences.edit()
|
|
19
|
+
editor.remove(key)
|
|
20
|
+
editor.apply()
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
fun getFromLocalStorage(key: String?): String? {
|
|
24
|
+
return preferences.getString(key, null)
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
companion object {
|
|
28
|
+
private const val SHARED_PREFERENCES = "com.twentyfouri.tvbridge"
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,38 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.utils
|
|
2
|
+
|
|
3
|
+
import android.util.Base64
|
|
4
|
+
import android.util.Log
|
|
5
|
+
import com.google.android.exoplayer2.drm.ExoMediaDrm
|
|
6
|
+
import com.google.android.exoplayer2.drm.MediaDrmCallback
|
|
7
|
+
import java.util.*
|
|
8
|
+
|
|
9
|
+
class LoggingDrmCallback(
|
|
10
|
+
private val base: MediaDrmCallback,
|
|
11
|
+
private val licenseUrl: String? = null
|
|
12
|
+
) : MediaDrmCallback {
|
|
13
|
+
override fun executeProvisionRequest(
|
|
14
|
+
uuid: UUID,
|
|
15
|
+
request: ExoMediaDrm.ProvisionRequest
|
|
16
|
+
): ByteArray {
|
|
17
|
+
return base.executeProvisionRequest(uuid, request)
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
override fun executeKeyRequest(uuid: UUID, request: ExoMediaDrm.KeyRequest): ByteArray {
|
|
21
|
+
if (com.twentyfouri.player.exoplayer.BuildConfig.DEBUG) {
|
|
22
|
+
Log.v(TAG, "DRM Embedded URL: ${request.licenseServerUrl}")
|
|
23
|
+
Log.v(TAG, "DRM Default URL: $licenseUrl")
|
|
24
|
+
Log.v(TAG, "DRM request:\n${request.data.toBase64()}")
|
|
25
|
+
}
|
|
26
|
+
val response = base.executeKeyRequest(uuid, request)
|
|
27
|
+
if (com.twentyfouri.player.exoplayer.BuildConfig.DEBUG) {
|
|
28
|
+
Log.v(TAG, "DRM response:\n" + response.toBase64())
|
|
29
|
+
}
|
|
30
|
+
return response
|
|
31
|
+
}
|
|
32
|
+
|
|
33
|
+
private fun ByteArray.toBase64(): String = Base64.encodeToString(this, Base64.DEFAULT)
|
|
34
|
+
|
|
35
|
+
companion object {
|
|
36
|
+
const val TAG = "DrmCallback"
|
|
37
|
+
}
|
|
38
|
+
}
|
|
@@ -0,0 +1,134 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.utils
|
|
2
|
+
|
|
3
|
+
import android.net.Uri
|
|
4
|
+
import android.util.Base64
|
|
5
|
+
import android.util.Log
|
|
6
|
+
import com.google.android.exoplayer2.C
|
|
7
|
+
import com.google.android.exoplayer2.drm.ExoMediaDrm
|
|
8
|
+
import com.google.android.exoplayer2.drm.MediaDrmCallback
|
|
9
|
+
import com.google.android.exoplayer2.upstream.DataSourceInputStream
|
|
10
|
+
import com.google.android.exoplayer2.upstream.DataSpec
|
|
11
|
+
import com.google.android.exoplayer2.upstream.HttpDataSource
|
|
12
|
+
import com.google.android.exoplayer2.util.Util
|
|
13
|
+
import com.twentyfouri.tvbridge.BuildConfig
|
|
14
|
+
import org.json.JSONException
|
|
15
|
+
import org.json.JSONObject
|
|
16
|
+
import java.io.BufferedReader
|
|
17
|
+
import java.io.IOException
|
|
18
|
+
import java.io.InputStreamReader
|
|
19
|
+
import java.net.MalformedURLException
|
|
20
|
+
import java.net.URL
|
|
21
|
+
import java.net.URLEncoder
|
|
22
|
+
import java.util.HashMap
|
|
23
|
+
import java.util.UUID
|
|
24
|
+
|
|
25
|
+
class OverriddenHttpMediaDrmCallback(
|
|
26
|
+
private val defaultLicenseUrl: String?,
|
|
27
|
+
private val forceDefaultLicenseUrl: Boolean,
|
|
28
|
+
private val dataSourceFactory: HttpDataSource.Factory
|
|
29
|
+
) : MediaDrmCallback {
|
|
30
|
+
|
|
31
|
+
@Throws(IOException::class)
|
|
32
|
+
override fun executeProvisionRequest(uuid: UUID, request: ExoMediaDrm.ProvisionRequest): ByteArray {
|
|
33
|
+
Log.d(TAG, "executeProvisionRequest")
|
|
34
|
+
val url = request.defaultUrl + "&signedRequest=" + String(request.data)
|
|
35
|
+
return executePost(dataSourceFactory, url, ByteArray(0), null)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
@Throws(Exception::class)
|
|
39
|
+
override fun executeKeyRequest(uuid: UUID, request: ExoMediaDrm.KeyRequest): ByteArray {
|
|
40
|
+
Log.d(TAG, "executeKeyRequest")
|
|
41
|
+
var url: String? = request.licenseServerUrl
|
|
42
|
+
if (forceDefaultLicenseUrl || url.isNullOrEmpty()) {
|
|
43
|
+
url = defaultLicenseUrl
|
|
44
|
+
}
|
|
45
|
+
val requestProperties: MutableMap<String, String> = HashMap()
|
|
46
|
+
// Add standard request properties for supported schemes.
|
|
47
|
+
val contentType = "text/plain"
|
|
48
|
+
requestProperties["Content-Type"] = contentType
|
|
49
|
+
if (C.PLAYREADY_UUID == uuid) {
|
|
50
|
+
requestProperties["SOAPAction"] = "http://schemas.microsoft.com/DRM/2007/03/protocols/AcquireLicense"
|
|
51
|
+
}
|
|
52
|
+
|
|
53
|
+
//adding data to url
|
|
54
|
+
val challenge = request.data
|
|
55
|
+
val encoded = URLEncoder.encode(Base64.encodeToString(challenge, Base64.NO_WRAP), "UTF-8")
|
|
56
|
+
url = appendQuery(url, "_widevineChallenge=$encoded")
|
|
57
|
+
if (BuildConfig.DEBUG) {
|
|
58
|
+
Log.d(TAG, "Executing post on url $url with content type $contentType")
|
|
59
|
+
}
|
|
60
|
+
return executeGet(url)
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
companion object {
|
|
64
|
+
private const val TAG = "DrmCallback"
|
|
65
|
+
|
|
66
|
+
private fun executeGet(urlString: String): ByteArray {
|
|
67
|
+
try {
|
|
68
|
+
val licenserRequest = URL(urlString)
|
|
69
|
+
val yc = licenserRequest.openConnection()
|
|
70
|
+
val input = BufferedReader(InputStreamReader(yc.getInputStream()))
|
|
71
|
+
val builder = StringBuilder()
|
|
72
|
+
var inputLine: String?
|
|
73
|
+
while (input.readLine().also { inputLine = it } != null) {
|
|
74
|
+
builder.append(inputLine)
|
|
75
|
+
}
|
|
76
|
+
input.close()
|
|
77
|
+
val jsonObject = JSONObject(builder.toString())
|
|
78
|
+
val container = jsonObject.getJSONObject("getWidevineLicenseResponse")
|
|
79
|
+
val license = container.getString("license")
|
|
80
|
+
if (BuildConfig.DEBUG) {
|
|
81
|
+
Log.d(TAG, "Finished post: $license")
|
|
82
|
+
}
|
|
83
|
+
return Base64.decode(license, Base64.NO_WRAP)
|
|
84
|
+
} catch (e: MalformedURLException) {
|
|
85
|
+
e.printStackTrace()
|
|
86
|
+
} catch (e: IOException) {
|
|
87
|
+
e.printStackTrace()
|
|
88
|
+
} catch (e: JSONException) {
|
|
89
|
+
e.printStackTrace()
|
|
90
|
+
}
|
|
91
|
+
return byteArrayOf()
|
|
92
|
+
}
|
|
93
|
+
|
|
94
|
+
@Throws(IOException::class)
|
|
95
|
+
private fun executePost(
|
|
96
|
+
dataSourceFactory: HttpDataSource.Factory,
|
|
97
|
+
url: String,
|
|
98
|
+
data: ByteArray,
|
|
99
|
+
requestProperties: Map<String, String>?
|
|
100
|
+
): ByteArray {
|
|
101
|
+
Log.d(TAG, "executePost")
|
|
102
|
+
val dataSource = dataSourceFactory.createDataSource()
|
|
103
|
+
if (requestProperties != null) {
|
|
104
|
+
for ((key, value) in requestProperties) {
|
|
105
|
+
dataSource.setRequestProperty(key, value)
|
|
106
|
+
}
|
|
107
|
+
}
|
|
108
|
+
val dataSpec = DataSpec.Builder()
|
|
109
|
+
.setUri(Uri.parse(url))
|
|
110
|
+
.setFlags(DataSpec.FLAG_ALLOW_GZIP)
|
|
111
|
+
.setHttpMethod(DataSpec.HTTP_METHOD_POST)
|
|
112
|
+
.setHttpBody(data)
|
|
113
|
+
.setHttpRequestHeaders(requestProperties ?: emptyMap())
|
|
114
|
+
.build()
|
|
115
|
+
val inputStream = DataSourceInputStream(dataSource, dataSpec)
|
|
116
|
+
return try {
|
|
117
|
+
Util.toByteArray(inputStream)
|
|
118
|
+
} finally {
|
|
119
|
+
Util.closeQuietly(inputStream)
|
|
120
|
+
}
|
|
121
|
+
}
|
|
122
|
+
|
|
123
|
+
fun appendQuery(url: String?, appendQuery: String): String {
|
|
124
|
+
val oldUri = Uri.parse(url)
|
|
125
|
+
var newQuery = oldUri.query
|
|
126
|
+
if (newQuery == null) {
|
|
127
|
+
newQuery = appendQuery
|
|
128
|
+
} else {
|
|
129
|
+
newQuery += "&$appendQuery"
|
|
130
|
+
}
|
|
131
|
+
return oldUri.scheme + "://" + oldUri.authority + oldUri.path + "?" + newQuery
|
|
132
|
+
}
|
|
133
|
+
}
|
|
134
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.utils
|
|
2
|
+
|
|
3
|
+
import android.app.Application
|
|
4
|
+
import com.twentyfouri.player.bitmovin.NpawConfig
|
|
5
|
+
import com.twentyfouri.player.bitmovin.PlayerBitmovin
|
|
6
|
+
import com.twentyfouri.player.bitmovin.PlayerFactoryBitmovin
|
|
7
|
+
import com.twentyfouri.tvbridge.configuration.BridgeConfig
|
|
8
|
+
|
|
9
|
+
class PlayerFactoryBitmovinCustomized(config: BridgeConfig, application: Application) :
|
|
10
|
+
PlayerFactoryBitmovin(
|
|
11
|
+
config.bitmovinLicense,
|
|
12
|
+
if (config.npawAccount.isNotEmpty()) {
|
|
13
|
+
NpawConfig(config.npawAccount, application)
|
|
14
|
+
} else {
|
|
15
|
+
null
|
|
16
|
+
},
|
|
17
|
+
config.bitmovinAnalytics.ifEmpty { PlayerBitmovin.ANALYTICS_LICENSE_DEFERRED }
|
|
18
|
+
),
|
|
19
|
+
PlayerFactoryVersion
|
|
@@ -0,0 +1,37 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.utils
|
|
2
|
+
|
|
3
|
+
import android.app.Application
|
|
4
|
+
import com.twentyfouri.player.base.PlayerFactoryBase
|
|
5
|
+
import com.twentyfouri.tvbridge.configuration.BridgeConfig
|
|
6
|
+
|
|
7
|
+
object PlayerFactoryConfigured {
|
|
8
|
+
fun buildFactory(bridgeConfig: BridgeConfig, application: Application): PlayerFactoryBase {
|
|
9
|
+
var factory: PlayerFactoryBase? = null
|
|
10
|
+
if (bridgeConfig.bitmovinLicense.isNotEmpty()) {
|
|
11
|
+
factory = factory ?: buildBitmovinFactory(bridgeConfig, application)
|
|
12
|
+
}
|
|
13
|
+
if (bridgeConfig.npawAccount.isNotEmpty()) {
|
|
14
|
+
factory = factory ?: buildNpawFactory(bridgeConfig)
|
|
15
|
+
}
|
|
16
|
+
factory = factory ?: buildExoFactory(bridgeConfig)
|
|
17
|
+
return factory ?: throw Exception("Cannot create player factory")
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
private fun buildExoFactory(bridgeConfig: BridgeConfig) = try {
|
|
21
|
+
PlayerFactoryExoPlayerCustomized(bridgeConfig)
|
|
22
|
+
} catch (e: NoClassDefFoundError) {
|
|
23
|
+
null
|
|
24
|
+
}
|
|
25
|
+
|
|
26
|
+
private fun buildNpawFactory(bridgeConfig: BridgeConfig) = try {
|
|
27
|
+
PlayerFactoryExoPlayerNpaw(bridgeConfig)
|
|
28
|
+
} catch (e: NoClassDefFoundError) {
|
|
29
|
+
null
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
private fun buildBitmovinFactory(bridgeConfig: BridgeConfig, application: Application) = try {
|
|
33
|
+
PlayerFactoryBitmovinCustomized(bridgeConfig, application)
|
|
34
|
+
} catch (e: NoClassDefFoundError) {
|
|
35
|
+
null
|
|
36
|
+
}
|
|
37
|
+
}
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
package com.twentyfouri.tvbridge.global.utils
|
|
2
|
+
|
|
3
|
+
import android.content.Context
|
|
4
|
+
import com.google.android.exoplayer2.C
|
|
5
|
+
import com.google.android.exoplayer2.ExoPlayerLibraryInfo
|
|
6
|
+
import com.google.android.exoplayer2.drm.DefaultDrmSessionManager
|
|
7
|
+
import com.google.android.exoplayer2.drm.DrmSessionManager
|
|
8
|
+
import com.google.android.exoplayer2.drm.FrameworkMediaDrm
|
|
9
|
+
import com.google.android.exoplayer2.drm.MediaDrmCallback
|
|
10
|
+
import com.google.android.exoplayer2.ext.ima.ImaAdsLoader
|
|
11
|
+
import com.google.android.exoplayer2.upstream.HttpDataSource
|
|
12
|
+
import com.google.android.exoplayer2.upstream.LoadErrorHandlingPolicy
|
|
13
|
+
import com.twentyfouri.player.base.DrmPlayready
|
|
14
|
+
import com.twentyfouri.player.base.DrmWidevine
|
|
15
|
+
import com.twentyfouri.player.base.Source
|
|
16
|
+
import com.twentyfouri.player.base.SourceDrm
|
|
17
|
+
import com.twentyfouri.player.base.TimeProvider
|
|
18
|
+
import com.twentyfouri.player.exoplayer.*
|
|
19
|
+
import com.twentyfouri.tvbridge.configuration.BridgeConfig
|
|
20
|
+
|
|
21
|
+
class PlayerFactoryExoPlayerCustomized(
|
|
22
|
+
private val config: BridgeConfig
|
|
23
|
+
) : PlayerFactoryExoPlayer(), PlayerFactoryVersion {
|
|
24
|
+
|
|
25
|
+
override val engineName: String = "Exoplayer"
|
|
26
|
+
|
|
27
|
+
override val engineVersion: String = ExoPlayerLibraryInfo.VERSION
|
|
28
|
+
|
|
29
|
+
override fun createSharedComponents(context: Context): SharedComponents =
|
|
30
|
+
CustomizedSharedComponents(context)
|
|
31
|
+
|
|
32
|
+
private inner class CustomizedSharedComponents(context: Context) : DefaultSharedComponents(context) {
|
|
33
|
+
|
|
34
|
+
override val drmProvider: DrmSessionManagerProvider by lazy {
|
|
35
|
+
CustomizedDrmSessionManagerProvider(loadErrorHandlingPolicy)
|
|
36
|
+
}
|
|
37
|
+
|
|
38
|
+
override val applicationName: String
|
|
39
|
+
get() = config.playerAppName ?: super.applicationName
|
|
40
|
+
|
|
41
|
+
override fun buildIsolatedComponents(): PlayerComponents {
|
|
42
|
+
return CustomizedPlayerComponents(this)
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
override val mainSourceProvider: MediaSourceFactoryProvider by lazy {
|
|
46
|
+
DefaultMediaSourceFactoryProvider().also {
|
|
47
|
+
it.useLiveMediaTailorWorkaround = true
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
override val focusSkipButton: Boolean
|
|
52
|
+
get() = false
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
private inner class CustomizedPlayerComponents(shared: SharedComponents) : DefaultPlayerComponents(shared) {
|
|
56
|
+
override val handleAudioFocus: Boolean
|
|
57
|
+
get() = false
|
|
58
|
+
}
|
|
59
|
+
|
|
60
|
+
private class CustomizedDrmSessionManagerProvider(
|
|
61
|
+
loadErrorHandlingPolicy: LoadErrorHandlingPolicy
|
|
62
|
+
) : DefaultDrmSessionManagerProvider(loadErrorHandlingPolicy) {
|
|
63
|
+
override fun buildDrmSessionManager(
|
|
64
|
+
dataSourceFactory: AuthorizedDataSourceProvider,
|
|
65
|
+
source: Source,
|
|
66
|
+
sourceDrm: SourceDrm
|
|
67
|
+
): DrmSessionManager? {
|
|
68
|
+
if (sourceDrm is SourceDrmOverridden) {
|
|
69
|
+
return buildDrmOverridden(dataSourceFactory, sourceDrm)
|
|
70
|
+
} else {
|
|
71
|
+
return super.buildDrmSessionManager(dataSourceFactory, source, sourceDrm)
|
|
72
|
+
}
|
|
73
|
+
}
|
|
74
|
+
|
|
75
|
+
private fun buildDrmOverridden(dataSourceFactory: AuthorizedDataSourceProvider, sourceDrm: SourceDrmOverridden): DrmSessionManager? {
|
|
76
|
+
val drmUuid = when (sourceDrm.packageName) {
|
|
77
|
+
DrmWidevine.packageName -> C.WIDEVINE_UUID
|
|
78
|
+
DrmPlayready.packageName -> C.PLAYREADY_UUID
|
|
79
|
+
else -> C.UUID_NIL
|
|
80
|
+
}
|
|
81
|
+
val licenseUrl = sourceDrm.licenseServer?.toString() ?: ""
|
|
82
|
+
val forceLicenseUrl = sourceDrm.forceLicenseServer
|
|
83
|
+
val httpDataSourceFactory = dataSourceFactory.buildHttpDataSourceFactory(sourceDrm.authorization)
|
|
84
|
+
|
|
85
|
+
val drmCallback = LoggingDrmCallback(
|
|
86
|
+
OverriddenHttpMediaDrmCallback(
|
|
87
|
+
licenseUrl,
|
|
88
|
+
forceLicenseUrl,
|
|
89
|
+
httpDataSourceFactory
|
|
90
|
+
),
|
|
91
|
+
licenseUrl
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
return DefaultDrmSessionManager.Builder()
|
|
95
|
+
.setUuidAndExoMediaDrmProvider(drmUuid, FrameworkMediaDrm.DEFAULT_PROVIDER)
|
|
96
|
+
.setMultiSession(false)
|
|
97
|
+
.setLoadErrorHandlingPolicy(loadErrorHandlingPolicy)
|
|
98
|
+
.build(drmCallback)
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
override fun buildDrmCallback(licenseUrl: String, forceLicenseUrl: Boolean, httpDataSourceFactory: HttpDataSource.Factory): MediaDrmCallback {
|
|
102
|
+
return LoggingDrmCallback(super.buildDrmCallback(licenseUrl, forceLicenseUrl, httpDataSourceFactory), licenseUrl)
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|
|
106
|
+
|