react-native-theoplayer 2.0.0 → 2.1.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/CHANGELOG.md +11 -0
- package/android/build.gradle +1 -1
- package/android/local/com/theoplayer/android-connector/mediasession/4.12.0-local/mediasession-4.12.0-local.aar +0 -0
- package/android/local/com/theoplayer/android-connector/mediasession/{4.11.0-local/mediasession-4.11.0-local.pom → 4.12.0-local/mediasession-4.12.0-local.pom} +1 -1
- package/android/local/com/theoplayer/android-connector/mediasession/maven-metadata-local.xml +4 -4
- package/android/src/main/java/com/theoplayer/ReactTHEOplayerContext.kt +48 -21
- package/android/src/main/java/com/theoplayer/ReactTHEOplayerView.kt +1 -3
- package/android/src/main/java/com/theoplayer/audio/BackgroundAudioConfig.kt +0 -7
- package/android/src/main/java/com/theoplayer/audio/BackgroundAudioConfigAdapter.kt +1 -5
- package/android/src/main/java/com/theoplayer/audio/MediaNotificationBuilder.kt +1 -3
- package/android/src/main/java/com/theoplayer/presentation/PresentationManager.kt +5 -12
- package/lib/commonjs/api/backgroundAudio/BackgroundAudioConfiguration.js.map +1 -1
- package/lib/module/api/backgroundAudio/BackgroundAudioConfiguration.js.map +1 -1
- package/lib/typescript/api/backgroundAudio/BackgroundAudioConfiguration.d.ts +0 -9
- package/package.json +2 -2
- package/react-native-theoplayer.podspec +5 -1
- package/src/api/backgroundAudio/BackgroundAudioConfiguration.ts +0 -10
- package/android/local/com/theoplayer/android-connector/mediasession/4.11.0-local/mediasession-4.11.0-local.aar +0 -0
package/CHANGELOG.md
CHANGED
|
@@ -5,6 +5,17 @@ All notable changes to this project will be documented in this file.
|
|
|
5
5
|
The format is based on [Keep a Changelog](http://keepachangelog.com/en/1.0.0/)
|
|
6
6
|
and this project adheres to [Semantic Versioning](http://semver.org/spec/v2.0.0.html).
|
|
7
7
|
|
|
8
|
+
## [Unreleased 2.1.0]
|
|
9
|
+
|
|
10
|
+
### Fixed
|
|
11
|
+
|
|
12
|
+
- Fixed invalid location of the typescript declaration file.
|
|
13
|
+
- Fixed an issue on Android where the player would not pause when closing the app while background playback is disabled.
|
|
14
|
+
|
|
15
|
+
### Changed
|
|
16
|
+
|
|
17
|
+
- Removed `backgroundAudioConfiguration.mediaPlaybackServiceEnabled` property on Android. Disabling background playback disables the service as well.
|
|
18
|
+
|
|
8
19
|
## [2.0.0] - 23-04-06
|
|
9
20
|
|
|
10
21
|
### Added
|
package/android/build.gradle
CHANGED
|
@@ -107,7 +107,7 @@ dependencies {
|
|
|
107
107
|
|
|
108
108
|
def theoplayer_sdk_version = safeExtGet('THEOplayer_sdk', '+')
|
|
109
109
|
// def theoplayer_mediasession_version = safeExtGet('THEOplayer_mediasession', theoplayer_sdk_version)
|
|
110
|
-
def theoplayer_mediasession_version = "4.
|
|
110
|
+
def theoplayer_mediasession_version = "4.12.0-local"
|
|
111
111
|
def enabledV4 = theoplayer_sdk_version.toString().startsWith("4.")
|
|
112
112
|
def core_prefix = enabledV4 ? 'unified' : 'core'
|
|
113
113
|
def integration_prefix = enabledV4 ? 'unified' : 'integration'
|
|
Binary file
|
package/android/local/com/theoplayer/android-connector/mediasession/maven-metadata-local.xml
CHANGED
|
@@ -3,11 +3,11 @@
|
|
|
3
3
|
<groupId>com.theoplayer.android-connector</groupId>
|
|
4
4
|
<artifactId>mediasession</artifactId>
|
|
5
5
|
<versioning>
|
|
6
|
-
<latest>4.
|
|
7
|
-
<release>4.
|
|
6
|
+
<latest>4.12.0-local</latest>
|
|
7
|
+
<release>4.12.0-local</release>
|
|
8
8
|
<versions>
|
|
9
|
-
<version>4.
|
|
9
|
+
<version>4.12.0-local</version>
|
|
10
10
|
</versions>
|
|
11
|
-
<lastUpdated>
|
|
11
|
+
<lastUpdated>20230408184844</lastUpdated>
|
|
12
12
|
</versioning>
|
|
13
13
|
</metadata>
|
|
@@ -39,12 +39,9 @@ class ReactTHEOplayerContext private constructor(
|
|
|
39
39
|
private var binder: MediaPlaybackService.MediaPlaybackBinder? = null
|
|
40
40
|
private var mediaSessionConnector: MediaSessionConnector? = null
|
|
41
41
|
|
|
42
|
-
var backgroundAudioConfig: BackgroundAudioConfig = BackgroundAudioConfig(
|
|
43
|
-
enabled = false,
|
|
44
|
-
mediaPlaybackServiceEnabled = true
|
|
45
|
-
)
|
|
42
|
+
var backgroundAudioConfig: BackgroundAudioConfig = BackgroundAudioConfig(enabled = false)
|
|
46
43
|
set(value) {
|
|
47
|
-
applyBackgroundPlaybackConfig(value)
|
|
44
|
+
applyBackgroundPlaybackConfig(value, field)
|
|
48
45
|
field = value
|
|
49
46
|
}
|
|
50
47
|
|
|
@@ -56,14 +53,18 @@ class ReactTHEOplayerContext private constructor(
|
|
|
56
53
|
var daiIntegration: GoogleDaiIntegration? = null
|
|
57
54
|
var imaIntegration: GoogleImaIntegration? = null
|
|
58
55
|
var castIntegration: CastIntegration? = null
|
|
56
|
+
var wasPlayingOnHostPause: Boolean = false
|
|
59
57
|
|
|
60
58
|
private val isBackgroundAudioEnabled: Boolean
|
|
61
|
-
get() = backgroundAudioConfig.enabled
|
|
59
|
+
get() = backgroundAudioConfig.enabled
|
|
62
60
|
|
|
63
61
|
companion object {
|
|
64
62
|
private var mediaControlledInstance: ReactTHEOplayerContext? = null
|
|
65
63
|
|
|
66
|
-
fun create(
|
|
64
|
+
fun create(
|
|
65
|
+
reactContext: ThemedReactContext,
|
|
66
|
+
playerConfig: THEOplayerConfig
|
|
67
|
+
): ReactTHEOplayerContext {
|
|
67
68
|
return ReactTHEOplayerContext(reactContext).apply {
|
|
68
69
|
initializePlayerView(playerConfig)
|
|
69
70
|
}
|
|
@@ -74,7 +75,10 @@ class ReactTHEOplayerContext private constructor(
|
|
|
74
75
|
override fun onServiceConnected(className: ComponentName, service: IBinder) {
|
|
75
76
|
binder = service as MediaPlaybackService.MediaPlaybackBinder
|
|
76
77
|
|
|
77
|
-
//
|
|
78
|
+
// Clean-up any existing media session connector
|
|
79
|
+
mediaSessionConnector?.destroy()
|
|
80
|
+
|
|
81
|
+
// Get media session connector from service
|
|
78
82
|
mediaSessionConnector = binder?.mediaSessionConnector
|
|
79
83
|
mediaSessionConnector?.player = player
|
|
80
84
|
mediaSessionConnector?.setMediaSessionMetadata(player.source)
|
|
@@ -91,17 +95,37 @@ class ReactTHEOplayerContext private constructor(
|
|
|
91
95
|
}
|
|
92
96
|
}
|
|
93
97
|
|
|
94
|
-
private fun
|
|
95
|
-
|
|
96
|
-
reactContext.applicationContext.
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
98
|
+
private fun setPlaybackServiceEnabled(enabled: Boolean) {
|
|
99
|
+
reactContext.applicationContext.packageManager.setComponentEnabledSetting(
|
|
100
|
+
ComponentName(reactContext.applicationContext, MediaPlaybackService::class.java),
|
|
101
|
+
if (enabled) PackageManager.COMPONENT_ENABLED_STATE_ENABLED
|
|
102
|
+
else PackageManager.COMPONENT_ENABLED_STATE_DISABLED,
|
|
103
|
+
PackageManager.DONT_KILL_APP
|
|
104
|
+
)
|
|
105
|
+
}
|
|
106
|
+
|
|
107
|
+
private fun applyBackgroundPlaybackConfig(
|
|
108
|
+
config: BackgroundAudioConfig,
|
|
109
|
+
prevConfig: BackgroundAudioConfig?
|
|
110
|
+
) {
|
|
111
|
+
if (prevConfig?.enabled == config.enabled) {
|
|
112
|
+
// No changes
|
|
113
|
+
return
|
|
102
114
|
}
|
|
103
115
|
|
|
104
|
-
|
|
116
|
+
if (BuildConfig.USE_PLAYBACK_SERVICE) {
|
|
117
|
+
if (prevConfig?.enabled != true && config.enabled) {
|
|
118
|
+
// Enabling background playback
|
|
119
|
+
setPlaybackServiceEnabled(true)
|
|
120
|
+
bindMediaPlaybackService()
|
|
121
|
+
} else if (prevConfig?.enabled == true) {
|
|
122
|
+
// Disabling background playback
|
|
123
|
+
binder?.stopForegroundService()
|
|
124
|
+
unbindMediaPlaybackService()
|
|
125
|
+
setPlaybackServiceEnabled(false)
|
|
126
|
+
initDefaultMediaSession()
|
|
127
|
+
}
|
|
128
|
+
}
|
|
105
129
|
}
|
|
106
130
|
|
|
107
131
|
private fun bindMediaPlaybackService() {
|
|
@@ -128,6 +152,7 @@ class ReactTHEOplayerContext private constructor(
|
|
|
128
152
|
reactContext.unbindService(connection)
|
|
129
153
|
}
|
|
130
154
|
}
|
|
155
|
+
binder = null
|
|
131
156
|
}
|
|
132
157
|
|
|
133
158
|
private fun initializePlayerView(playerConfig: THEOplayerConfig) {
|
|
@@ -156,13 +181,13 @@ class ReactTHEOplayerContext private constructor(
|
|
|
156
181
|
|
|
157
182
|
if (mediaControlledInstance == null) {
|
|
158
183
|
mediaControlledInstance = this
|
|
159
|
-
if (!BuildConfig.USE_PLAYBACK_SERVICE) {
|
|
184
|
+
if (!BuildConfig.USE_PLAYBACK_SERVICE || !isBackgroundAudioEnabled) {
|
|
160
185
|
initDefaultMediaSession()
|
|
161
186
|
}
|
|
162
187
|
}
|
|
163
188
|
|
|
164
189
|
// Apply initial backgroundPlayback config
|
|
165
|
-
applyBackgroundPlaybackConfig(backgroundAudioConfig)
|
|
190
|
+
applyBackgroundPlaybackConfig(backgroundAudioConfig, null)
|
|
166
191
|
}
|
|
167
192
|
|
|
168
193
|
private fun initDefaultMediaSession() {
|
|
@@ -225,7 +250,7 @@ class ReactTHEOplayerContext private constructor(
|
|
|
225
250
|
}
|
|
226
251
|
|
|
227
252
|
private val onPlay = EventListener<PlayEvent> {
|
|
228
|
-
if (BuildConfig.USE_PLAYBACK_SERVICE) {
|
|
253
|
+
if (BuildConfig.USE_PLAYBACK_SERVICE && isBackgroundAudioEnabled) {
|
|
229
254
|
bindMediaPlaybackService()
|
|
230
255
|
}
|
|
231
256
|
binder?.updateNotification(PlaybackStateCompat.STATE_PLAYING)
|
|
@@ -266,8 +291,10 @@ class ReactTHEOplayerContext private constructor(
|
|
|
266
291
|
* The host activity is paused.
|
|
267
292
|
*/
|
|
268
293
|
fun onHostPause() {
|
|
294
|
+
// Keep current playing state when going to background
|
|
295
|
+
wasPlayingOnHostPause = !player.isPaused
|
|
296
|
+
|
|
269
297
|
if (!isBackgroundAudioEnabled) {
|
|
270
|
-
mediaSessionConnector?.setActive(false)
|
|
271
298
|
playerView.onPause()
|
|
272
299
|
}
|
|
273
300
|
}
|
|
@@ -85,9 +85,7 @@ class ReactTHEOplayerView(private val reactContext: ThemedReactContext) :
|
|
|
85
85
|
if (BuildConfig.LOG_VIEW_EVENTS) {
|
|
86
86
|
Log.d(TAG, "onHostPause")
|
|
87
87
|
}
|
|
88
|
-
|
|
89
|
-
playerContext?.onHostPause()
|
|
90
|
-
}
|
|
88
|
+
playerContext?.onHostPause()
|
|
91
89
|
}
|
|
92
90
|
|
|
93
91
|
/**
|
|
@@ -4,16 +4,12 @@ import com.facebook.react.bridge.ReadableMap
|
|
|
4
4
|
|
|
5
5
|
object BackgroundAudioConfigAdapter {
|
|
6
6
|
private const val PROP_ENABLED = "enabled"
|
|
7
|
-
private const val PROP_SERVICE_ENABLED = "mediaPlaybackServiceEnabled"
|
|
8
7
|
|
|
9
8
|
private const val DEFAULT_ENABLED = false
|
|
10
|
-
private const val DEFAULT_SERVICE_ENABLED = true
|
|
11
9
|
|
|
12
10
|
fun fromProps(props: ReadableMap?): BackgroundAudioConfig {
|
|
13
11
|
val enabled =
|
|
14
12
|
if (props?.hasKey(PROP_ENABLED) == true) props.getBoolean(PROP_ENABLED) else DEFAULT_ENABLED
|
|
15
|
-
|
|
16
|
-
if (props?.hasKey(PROP_SERVICE_ENABLED) == true) props.getBoolean(PROP_SERVICE_ENABLED) else DEFAULT_SERVICE_ENABLED
|
|
17
|
-
return BackgroundAudioConfig(enabled, serviceEnabled)
|
|
13
|
+
return BackgroundAudioConfig(enabled)
|
|
18
14
|
}
|
|
19
15
|
}
|
|
@@ -141,9 +141,7 @@ class MediaNotificationBuilder(
|
|
|
141
141
|
|
|
142
142
|
// Associate the notification with your session. This allows third-party apps and
|
|
143
143
|
// companion devices to access and control the session.
|
|
144
|
-
|
|
145
|
-
style.setMediaSession(mediaSession.sessionToken)
|
|
146
|
-
}
|
|
144
|
+
style.setMediaSession(mediaSession.sessionToken)
|
|
147
145
|
|
|
148
146
|
// Add up to 3 actions to be shown in the notification's standard-sized contentView.
|
|
149
147
|
style.setShowActionsInCompactView(0)
|
|
@@ -81,18 +81,6 @@ class PresentationManager(
|
|
|
81
81
|
)
|
|
82
82
|
}
|
|
83
83
|
|
|
84
|
-
/**
|
|
85
|
-
* Whether playback should be allowed to continue when the activity is paused.
|
|
86
|
-
*
|
|
87
|
-
* Pause if:
|
|
88
|
-
* - No PiP available: Build.VERSION.SDK_INT < Build.VERSION_CODES.N (API 24), or;
|
|
89
|
-
* - Not in PiP mode, and;
|
|
90
|
-
* - Not configured to automatically go into PiP when going to the background.
|
|
91
|
-
*/
|
|
92
|
-
val shouldPauseOnHostPause: Boolean
|
|
93
|
-
get() = Build.VERSION.SDK_INT < Build.VERSION_CODES.N ||
|
|
94
|
-
(reactContext.currentActivity?.isInPictureInPictureMode != true && pipConfig.startsAutomatically != true)
|
|
95
|
-
|
|
96
84
|
fun destroy() {
|
|
97
85
|
try {
|
|
98
86
|
reactContext.currentActivity?.unregisterReceiver(onUserLeaveHintReceiver)
|
|
@@ -241,6 +229,11 @@ class PresentationManager(
|
|
|
241
229
|
currentPresentationMode = presentationMode
|
|
242
230
|
eventEmitter.emitPresentationModeChange(presentationMode, prevPresentationMode, context)
|
|
243
231
|
|
|
232
|
+
// Resume playing when going to PiP and player was playing
|
|
233
|
+
if (presentationMode == PresentationMode.PICTURE_IN_PICTURE && viewCtx.wasPlayingOnHostPause) {
|
|
234
|
+
viewCtx.player.play()
|
|
235
|
+
}
|
|
236
|
+
|
|
244
237
|
// Apply background audio config when closing PiP window
|
|
245
238
|
if (context?.pip == PresentationModeChangePipContext.CLOSED && !viewCtx.backgroundAudioConfig.enabled) {
|
|
246
239
|
viewCtx.player.pause()
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["BackgroundAudioConfiguration.ts"],"sourcesContent":["/**\n * Describes the configuration of the background audio feature.\n *\n * @public\n */\nexport interface BackgroundAudioConfiguration {\n /**\n * Whether background audio should be enabled when transitioning to background.\n *\n * @defaultValue `false`\n */\n readonly enabled?: boolean;\n
|
|
1
|
+
{"version":3,"names":[],"sources":["BackgroundAudioConfiguration.ts"],"sourcesContent":["/**\n * Describes the configuration of the background audio feature.\n *\n * @public\n */\nexport interface BackgroundAudioConfiguration {\n /**\n * Whether background audio should be enabled when transitioning to background.\n *\n * @defaultValue `false`\n */\n readonly enabled?: boolean;\n}\n"],"mappings":""}
|
|
@@ -1 +1 @@
|
|
|
1
|
-
{"version":3,"names":[],"sources":["BackgroundAudioConfiguration.ts"],"sourcesContent":["/**\n * Describes the configuration of the background audio feature.\n *\n * @public\n */\nexport interface BackgroundAudioConfiguration {\n /**\n * Whether background audio should be enabled when transitioning to background.\n *\n * @defaultValue `false`\n */\n readonly enabled?: boolean;\n
|
|
1
|
+
{"version":3,"names":[],"sources":["BackgroundAudioConfiguration.ts"],"sourcesContent":["/**\n * Describes the configuration of the background audio feature.\n *\n * @public\n */\nexport interface BackgroundAudioConfiguration {\n /**\n * Whether background audio should be enabled when transitioning to background.\n *\n * @defaultValue `false`\n */\n readonly enabled?: boolean;\n}\n"],"mappings":""}
|
|
@@ -10,13 +10,4 @@ export interface BackgroundAudioConfiguration {
|
|
|
10
10
|
* @defaultValue `false`
|
|
11
11
|
*/
|
|
12
12
|
readonly enabled?: boolean;
|
|
13
|
-
/**
|
|
14
|
-
* Whether Android's mediaPlaybackService is enabled.
|
|
15
|
-
*
|
|
16
|
-
* The mediaPlaybackService is a MediaBrowserService that provides notifications and background playback.
|
|
17
|
-
* It can be dynamically disabled if the host app already registers a MediaBrowserService that conflicts with this one.
|
|
18
|
-
*
|
|
19
|
-
* @defaultValue `true`
|
|
20
|
-
*/
|
|
21
|
-
readonly mediaPlaybackServiceEnabled?: boolean;
|
|
22
13
|
}
|
package/package.json
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "react-native-theoplayer",
|
|
3
|
-
"version": "2.
|
|
3
|
+
"version": "2.1.0",
|
|
4
4
|
"description": "A THEOplayer video component for react-native.",
|
|
5
5
|
"main": "lib/commonjs/index",
|
|
6
6
|
"module": "lib/module/index",
|
|
7
|
-
"types": "lib/typescript/
|
|
7
|
+
"types": "lib/typescript/index.d.ts",
|
|
8
8
|
"react-native": "src/index",
|
|
9
9
|
"source": "src/index",
|
|
10
10
|
"files": [
|
|
@@ -6,7 +6,7 @@ if File.exists?(theoconfigpath)
|
|
|
6
6
|
theoconfig = JSON.parse(File.read(theoconfigpath))
|
|
7
7
|
theofeatures = theoconfig["ios"]["features"]
|
|
8
8
|
else
|
|
9
|
-
theofeatures = []
|
|
9
|
+
theofeatures = ["NONE"]
|
|
10
10
|
end
|
|
11
11
|
|
|
12
12
|
Pod::Spec.new do |s|
|
|
@@ -28,17 +28,21 @@ Pod::Spec.new do |s|
|
|
|
28
28
|
|
|
29
29
|
# THEOplayer Dependencies
|
|
30
30
|
if theofeatures.include?("WEB")
|
|
31
|
+
puts "Using THEOplayer-basic SDK, marked features: #{theofeatures.join(' ')}"
|
|
31
32
|
s.dependency "THEOplayerSDK-basic"
|
|
32
33
|
s.pod_target_xcconfig = {
|
|
33
34
|
'SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Release]' => theofeatures.join(' '),
|
|
34
35
|
'SWIFT_ACTIVE_COMPILATION_CONDITIONS[config=Debug]' => theofeatures.join(' ')
|
|
35
36
|
}
|
|
36
37
|
else
|
|
38
|
+
puts "Using THEOplayer-core SDK"
|
|
37
39
|
s.dependency "THEOplayerSDK-core"
|
|
38
40
|
if theofeatures.include?("GOOGLE_IMA")
|
|
41
|
+
puts "Adding THEOplayer-Integration-GoogleIMA"
|
|
39
42
|
s.dependency "THEOplayer-Integration-GoogleIMA"
|
|
40
43
|
end
|
|
41
44
|
if theofeatures.include?("CHROMECAST")
|
|
45
|
+
puts "Adding THEOplayer-Integration-GoogleCast"
|
|
42
46
|
s.ios.dependency "THEOplayer-Integration-GoogleCast"
|
|
43
47
|
s.ios.dependency "google-cast-sdk-dynamic-xcframework-no-bluetooth"
|
|
44
48
|
end
|
|
@@ -10,14 +10,4 @@ export interface BackgroundAudioConfiguration {
|
|
|
10
10
|
* @defaultValue `false`
|
|
11
11
|
*/
|
|
12
12
|
readonly enabled?: boolean;
|
|
13
|
-
|
|
14
|
-
/**
|
|
15
|
-
* Whether Android's mediaPlaybackService is enabled.
|
|
16
|
-
*
|
|
17
|
-
* The mediaPlaybackService is a MediaBrowserService that provides notifications and background playback.
|
|
18
|
-
* It can be dynamically disabled if the host app already registers a MediaBrowserService that conflicts with this one.
|
|
19
|
-
*
|
|
20
|
-
* @defaultValue `true`
|
|
21
|
-
*/
|
|
22
|
-
readonly mediaPlaybackServiceEnabled?: boolean;
|
|
23
13
|
}
|