Skip to content

Commit ca5d1e2

Browse files
committed
refactor(video_player_android): change audio track ID from string to separate indices
- Replaced string-based track ID format ("groupIndex_trackIndex") with separate Long parameters for groupIndex and trackIndex - Updated ExoPlayerAudioTrackData to store indices separately instead of concatenated string - Removed string parsing logic and error handling for invalid track ID formats in selectAudioTrack method
1 parent aa2f339 commit ca5d1e2

File tree

11 files changed

+159
-124
lines changed

11 files changed

+159
-124
lines changed

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/ExoPlayerEventListener.java

Lines changed: 10 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -95,25 +95,29 @@ public void onIsPlayingChanged(boolean isPlaying) {
9595
@Override
9696
public void onTracksChanged(@NonNull Tracks tracks) {
9797
// Find the currently selected audio track and notify
98-
String selectedTrackId = findSelectedAudioTrackId(tracks);
99-
events.onAudioTrackChanged(selectedTrackId);
98+
Long[] selectedTrackIndices = findSelectedAudioTrackIndices(tracks);
99+
if (selectedTrackIndices != null) {
100+
events.onAudioTrackChanged(selectedTrackIndices[0], selectedTrackIndices[1]);
101+
} else {
102+
events.onAudioTrackChanged(null, null);
103+
}
100104
}
101105

102106
/**
103-
* Finds the ID of the currently selected audio track.
107+
* Finds the indices of the currently selected audio track.
104108
*
105109
* @param tracks The current tracks
106-
* @return The track ID in format "groupIndex_trackIndex", or null if no audio track is selected
110+
* @return An array with [groupIndex, trackIndex], or null if no audio track is selected
107111
*/
108112
@Nullable
109-
private String findSelectedAudioTrackId(@NonNull Tracks tracks) {
113+
private Long[] findSelectedAudioTrackIndices(@NonNull Tracks tracks) {
110114
int groupIndex = 0;
111115
for (Tracks.Group group : tracks.getGroups()) {
112116
if (group.getType() == C.TRACK_TYPE_AUDIO && group.isSelected()) {
113117
// Find the selected track within this group
114118
for (int i = 0; i < group.length; i++) {
115119
if (group.isTrackSelected(i)) {
116-
return groupIndex + "_" + i;
120+
return new Long[] {(long) groupIndex, (long) i};
117121
}
118122
}
119123
}

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayer.java

Lines changed: 38 additions & 58 deletions
Original file line numberDiff line numberDiff line change
@@ -160,7 +160,8 @@ public ExoPlayer getExoPlayer() {
160160
// Create audio track data with metadata
161161
ExoPlayerAudioTrackData audioTrack =
162162
new ExoPlayerAudioTrackData(
163-
groupIndex + "_" + trackIndex,
163+
(long) groupIndex,
164+
(long) trackIndex,
164165
format.label,
165166
format.language,
166167
isSelected,
@@ -178,78 +179,57 @@ public ExoPlayer getExoPlayer() {
178179

179180
@UnstableApi
180181
@Override
181-
public void selectAudioTrack(@NonNull String trackId) {
182+
public void selectAudioTrack(long groupIndex, long trackIndex) {
182183
if (trackSelector == null) {
183184
Log.w("VideoPlayer", "Cannot select audio track: track selector is null");
184185
return;
185186
}
186187

187-
try {
188-
// Parse the trackId (format: "groupIndex_trackIndex")
189-
String[] parts = trackId.split("_");
190-
if (parts.length != 2) {
191-
Log.w(
192-
"VideoPlayer",
193-
"Cannot select audio track: invalid trackId format '"
194-
+ trackId
195-
+ "'. Expected format: 'groupIndex_trackIndex'");
196-
return;
197-
}
188+
// Get current tracks
189+
Tracks tracks = exoPlayer.getCurrentTracks();
198190

199-
int groupIndex = Integer.parseInt(parts[0]);
200-
int trackIndex = Integer.parseInt(parts[1]);
191+
if (groupIndex >= tracks.getGroups().size()) {
192+
Log.w(
193+
"VideoPlayer",
194+
"Cannot select audio track: groupIndex "
195+
+ groupIndex
196+
+ " is out of bounds (available groups: "
197+
+ tracks.getGroups().size()
198+
+ ")");
199+
return;
200+
}
201201

202-
// Get current tracks
203-
Tracks tracks = exoPlayer.getCurrentTracks();
202+
Tracks.Group group = tracks.getGroups().get((int) groupIndex);
204203

205-
if (groupIndex >= tracks.getGroups().size()) {
204+
// Verify it's an audio track and the track index is valid
205+
if (group.getType() != C.TRACK_TYPE_AUDIO || trackIndex >= group.length) {
206+
if (group.getType() != C.TRACK_TYPE_AUDIO) {
206207
Log.w(
207208
"VideoPlayer",
208-
"Cannot select audio track: groupIndex "
209+
"Cannot select audio track: group at index "
209210
+ groupIndex
210-
+ " is out of bounds (available groups: "
211-
+ tracks.getGroups().size()
211+
+ " is not an audio track (type: "
212+
+ group.getType()
213+
+ ")");
214+
} else {
215+
Log.w(
216+
"VideoPlayer",
217+
"Cannot select audio track: trackIndex "
218+
+ trackIndex
219+
+ " is out of bounds (available tracks in group: "
220+
+ group.length
212221
+ ")");
213-
return;
214-
}
215-
216-
Tracks.Group group = tracks.getGroups().get(groupIndex);
217-
218-
// Verify it's an audio track and the track index is valid
219-
if (group.getType() != C.TRACK_TYPE_AUDIO || trackIndex >= group.length) {
220-
if (group.getType() != C.TRACK_TYPE_AUDIO) {
221-
Log.w(
222-
"VideoPlayer",
223-
"Cannot select audio track: group at index "
224-
+ groupIndex
225-
+ " is not an audio track (type: "
226-
+ group.getType()
227-
+ ")");
228-
} else {
229-
Log.w(
230-
"VideoPlayer",
231-
"Cannot select audio track: trackIndex "
232-
+ trackIndex
233-
+ " is out of bounds (available tracks in group: "
234-
+ group.length
235-
+ ")");
236-
}
237-
return;
238222
}
223+
return;
224+
}
239225

240-
// Get the track group and create a selection override
241-
TrackGroup trackGroup = group.getMediaTrackGroup();
242-
TrackSelectionOverride override = new TrackSelectionOverride(trackGroup, trackIndex);
243-
244-
// Apply the track selection override
245-
trackSelector.setParameters(
246-
trackSelector.buildUponParameters().setOverrideForType(override).build());
226+
// Get the track group and create a selection override
227+
TrackGroup trackGroup = group.getMediaTrackGroup();
228+
TrackSelectionOverride override = new TrackSelectionOverride(trackGroup, (int) trackIndex);
247229

248-
} catch (NumberFormatException | ArrayIndexOutOfBoundsException e) {
249-
Log.w(
250-
"VideoPlayer",
251-
"Cannot select audio track: invalid trackId format '" + trackId + "'. " + e.getMessage());
252-
}
230+
// Apply the track selection override
231+
trackSelector.setParameters(
232+
trackSelector.buildUponParameters().setOverrideForType(override).build());
253233
}
254234

255235
public void dispose() {

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerCallbacks.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -25,5 +25,5 @@ public interface VideoPlayerCallbacks {
2525

2626
void onIsPlayingStateUpdate(boolean isPlaying);
2727

28-
void onAudioTrackChanged(@Nullable String selectedTrackId);
28+
void onAudioTrackChanged(@Nullable Long selectedGroupIndex, @Nullable Long selectedTrackIndex);
2929
}

packages/video_player/video_player_android/android/src/main/java/io/flutter/plugins/videoplayer/VideoPlayerEventCallbacks.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,8 @@ public void onIsPlayingStateUpdate(boolean isPlaying) {
6565
}
6666

6767
@Override
68-
public void onAudioTrackChanged(@Nullable String selectedTrackId) {
69-
eventSink.success(new AudioTrackChangedEvent(selectedTrackId));
68+
public void onAudioTrackChanged(
69+
@Nullable Long selectedGroupIndex, @Nullable Long selectedTrackIndex) {
70+
eventSink.success(new AudioTrackChangedEvent(selectedGroupIndex, selectedTrackIndex));
7071
}
7172
}

packages/video_player/video_player_android/android/src/main/kotlin/io/flutter/plugins/videoplayer/Messages.kt

Lines changed: 36 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -234,19 +234,23 @@ data class IsPlayingStateEvent(val isPlaying: Boolean) : PlatformVideoEvent() {
234234
* Generated class from Pigeon that represents data sent in messages.
235235
*/
236236
data class AudioTrackChangedEvent(
237-
/** The ID of the newly selected audio track, if any. */
238-
val selectedTrackId: String? = null
237+
/** The group index of the newly selected audio track, if any. */
238+
val selectedGroupIndex: Long? = null,
239+
/** The track index of the newly selected audio track, if any. */
240+
val selectedTrackIndex: Long? = null
239241
) : PlatformVideoEvent() {
240242
companion object {
241243
fun fromList(pigeonVar_list: List<Any?>): AudioTrackChangedEvent {
242-
val selectedTrackId = pigeonVar_list[0] as String?
243-
return AudioTrackChangedEvent(selectedTrackId)
244+
val selectedGroupIndex = pigeonVar_list[0] as Long?
245+
val selectedTrackIndex = pigeonVar_list[1] as Long?
246+
return AudioTrackChangedEvent(selectedGroupIndex, selectedTrackIndex)
244247
}
245248
}
246249

247250
fun toList(): List<Any?> {
248251
return listOf(
249-
selectedTrackId,
252+
selectedGroupIndex,
253+
selectedTrackIndex,
250254
)
251255
}
252256

@@ -461,7 +465,8 @@ data class AudioTrackMessage(
461465
* Generated class from Pigeon that represents data sent in messages.
462466
*/
463467
data class ExoPlayerAudioTrackData(
464-
val trackId: String,
468+
val groupIndex: Long,
469+
val trackIndex: Long,
465470
val label: String? = null,
466471
val language: String? = null,
467472
val isSelected: Boolean,
@@ -472,22 +477,32 @@ data class ExoPlayerAudioTrackData(
472477
) {
473478
companion object {
474479
fun fromList(pigeonVar_list: List<Any?>): ExoPlayerAudioTrackData {
475-
val trackId = pigeonVar_list[0] as String
476-
val label = pigeonVar_list[1] as String?
477-
val language = pigeonVar_list[2] as String?
478-
val isSelected = pigeonVar_list[3] as Boolean
479-
val bitrate = pigeonVar_list[4] as Long?
480-
val sampleRate = pigeonVar_list[5] as Long?
481-
val channelCount = pigeonVar_list[6] as Long?
482-
val codec = pigeonVar_list[7] as String?
480+
val groupIndex = pigeonVar_list[0] as Long
481+
val trackIndex = pigeonVar_list[1] as Long
482+
val label = pigeonVar_list[2] as String?
483+
val language = pigeonVar_list[3] as String?
484+
val isSelected = pigeonVar_list[4] as Boolean
485+
val bitrate = pigeonVar_list[5] as Long?
486+
val sampleRate = pigeonVar_list[6] as Long?
487+
val channelCount = pigeonVar_list[7] as Long?
488+
val codec = pigeonVar_list[8] as String?
483489
return ExoPlayerAudioTrackData(
484-
trackId, label, language, isSelected, bitrate, sampleRate, channelCount, codec)
490+
groupIndex,
491+
trackIndex,
492+
label,
493+
language,
494+
isSelected,
495+
bitrate,
496+
sampleRate,
497+
channelCount,
498+
codec)
485499
}
486500
}
487501

488502
fun toList(): List<Any?> {
489503
return listOf(
490-
trackId,
504+
groupIndex,
505+
trackIndex,
491506
label,
492507
language,
493508
isSelected,
@@ -841,8 +856,8 @@ interface VideoPlayerInstanceApi {
841856
fun getBufferedPosition(): Long
842857
/** Gets the available audio tracks for the video. */
843858
fun getAudioTracks(): NativeAudioTrackData
844-
/** Selects which audio track is chosen for playback from its [trackId] */
845-
fun selectAudioTrack(trackId: String)
859+
/** Selects which audio track is chosen for playback from its group and track indices. */
860+
fun selectAudioTrack(groupIndex: Long, trackIndex: Long)
846861

847862
companion object {
848863
/** The codec used by VideoPlayerInstanceApi. */
@@ -1062,10 +1077,11 @@ interface VideoPlayerInstanceApi {
10621077
if (api != null) {
10631078
channel.setMessageHandler { message, reply ->
10641079
val args = message as List<Any?>
1065-
val trackIdArg = args[0] as String
1080+
val groupIndexArg = args[0] as Long
1081+
val trackIndexArg = args[1] as Long
10661082
val wrapped: List<Any?> =
10671083
try {
1068-
api.selectAudioTrack(trackIdArg)
1084+
api.selectAudioTrack(groupIndexArg, trackIndexArg)
10691085
listOf(null)
10701086
} catch (exception: Throwable) {
10711087
MessagesPigeonUtils.wrapError(exception)

packages/video_player/video_player_android/android/src/test/java/io/flutter/plugins/videoplayer/AudioTracksTest.java

Lines changed: 12 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -125,7 +125,8 @@ public void testGetAudioTracks_withMultipleAudioTracks() {
125125

126126
// Verify first track
127127
ExoPlayerAudioTrackData track1 = result.get(0);
128-
assertEquals("0_0", track1.getTrackId());
128+
assertEquals(0L, track1.getGroupIndex());
129+
assertEquals(0L, track1.getTrackIndex());
129130
assertEquals("English", track1.getLabel());
130131
assertEquals("en", track1.getLanguage());
131132
assertTrue(track1.isSelected());
@@ -136,7 +137,8 @@ public void testGetAudioTracks_withMultipleAudioTracks() {
136137

137138
// Verify second track
138139
ExoPlayerAudioTrackData track2 = result.get(1);
139-
assertEquals("1_0", track2.getTrackId());
140+
assertEquals(1L, track2.getGroupIndex());
141+
assertEquals(0L, track2.getTrackIndex());
140142
assertEquals("Español", track2.getLabel());
141143
assertEquals("es", track2.getLanguage());
142144
assertFalse(track2.isSelected());
@@ -197,7 +199,8 @@ public void testGetAudioTracks_withNullValues() {
197199
assertEquals(1, result.size());
198200

199201
ExoPlayerAudioTrackData track = result.get(0);
200-
assertEquals("0_0", track.getTrackId());
202+
assertEquals(0L, track.getGroupIndex());
203+
assertEquals(0L, track.getTrackIndex());
201204
assertNull(track.getLabel()); // Null values should be preserved
202205
assertNull(track.getLanguage()); // Null values should be preserved
203206
assertFalse(track.isSelected());
@@ -246,12 +249,14 @@ public void testGetAudioTracks_withMultipleTracksInSameGroup() {
246249
assertNotNull(result);
247250
assertEquals(2, result.size());
248251

249-
// Verify track IDs are unique
252+
// Verify track indices are unique
250253
ExoPlayerAudioTrackData track1 = result.get(0);
251254
ExoPlayerAudioTrackData track2 = result.get(1);
252-
assertEquals("0_0", track1.getTrackId());
253-
assertEquals("0_1", track2.getTrackId());
254-
assertNotEquals(track1.getTrackId(), track2.getTrackId());
255+
assertEquals(0L, track1.getGroupIndex());
256+
assertEquals(0L, track1.getTrackIndex());
257+
assertEquals(0L, track2.getGroupIndex());
258+
assertEquals(1L, track2.getTrackIndex());
259+
assertNotEquals(track1.getTrackIndex(), track2.getTrackIndex());
255260
}
256261

257262
@Test

packages/video_player/video_player_android/example/pubspec.yaml

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,3 +34,7 @@ flutter:
3434
assets:
3535
- assets/flutter-mark-square-64.png
3636
- assets/Butterfly-209.mp4
37+
# FOR TESTING AND INITIAL REVIEW ONLY. DO NOT MERGE.
38+
# See https://github.com/flutter/flutter/blob/master/docs/ecosystem/contributing/README.md#changing-federated-plugins
39+
dependency_overrides:
40+
video_player_platform_interface: {path: ../../../../packages/video_player/video_player_platform_interface}

packages/video_player/video_player_android/lib/src/android_video_player.dart

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,8 @@ class AndroidVideoPlayer extends VideoPlayerPlatform {
237237
for (final ExoPlayerAudioTrackData track in nativeData.exoPlayerTracks!) {
238238
tracks.add(
239239
VideoAudioTrack(
240-
id: track.trackId,
240+
groupIndex: track.groupIndex!,
241+
trackIndex: track.trackIndex!,
241242
label: track.label,
242243
language: track.language,
243244
isSelected: track.isSelected,
@@ -254,8 +255,11 @@ class AndroidVideoPlayer extends VideoPlayerPlatform {
254255
}
255256

256257
@override
257-
Future<void> selectAudioTrack(int playerId, String trackId) {
258-
return _playerWith(id: playerId).selectAudioTrack(trackId);
258+
Future<void> selectAudioTrack(int playerId, VideoAudioTrack track) {
259+
// Extract groupIndex and trackIndex from the track object for Android's ExoPlayer
260+
return _playerWith(
261+
id: playerId,
262+
).selectAudioTrack(track.groupIndex, track.trackIndex);
259263
}
260264

261265
@override
@@ -351,12 +355,12 @@ class _PlayerInstance {
351355
return _api.getAudioTracks();
352356
}
353357

354-
Future<void> selectAudioTrack(String trackId) async {
358+
Future<void> selectAudioTrack(int groupIndex, int trackIndex) async {
355359
// Create a completer to wait for the track selection to complete
356360
_audioTrackSelectionCompleter = Completer<void>();
357361

358362
try {
359-
await _api.selectAudioTrack(trackId);
363+
await _api.selectAudioTrack(groupIndex, trackIndex);
360364

361365
// Wait for the onTracksChanged event from ExoPlayer with a timeout
362366
await _audioTrackSelectionCompleter!.future.timeout(

0 commit comments

Comments
 (0)