Skip to content

Commit 733d1cb

Browse files
[video_player] Move more Java logic to Dart (#9672)
Moves some logic from native code to Dart: - User-Agent header -> ExoPlayer user agent extraction logic (with TODOs for future improvements, based on implementation issues/questions I noticed while converting it). - Asset -> URL lookup. - Conversion of buffer position to the buffer range list required for the Dart event stream. Also converts video format hint from strings to enums, which was missed in earlier Pigeon conversions. Using strings was the pre-Pigeon way of handling this kind of thing. Part of flutter/flutter#172763 ## Pre-Review Checklist **Note**: The Flutter team is currently trialing the use of [Gemini Code Assist for GitHub](https://developers.google.com/gemini-code-assist/docs/review-github-code). Comments from the `gemini-code-assist` bot should not be taken as authoritative feedback from the Flutter team. If you find its comments useful you can update your code accordingly, but if you are unsure or disagree with the feedback, please feel free to wait for a Flutter team member's review for guidance on which automated comments should be addressed. [^1]: Regular contributors who have demonstrated familiarity with the repository guidelines only need to comment if the PR is not auto-exempted by repo tooling.
1 parent ed235d1 commit 733d1cb

File tree

15 files changed

+363
-252
lines changed

15 files changed

+363
-252
lines changed

packages/video_player/video_player_android/CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,7 @@
1+
## 2.8.10
2+
3+
* Restructures internal logic to move more code to Dart.
4+
15
## 2.8.9
26

37
* Restructures the communication between Dart and Java code.

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

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -20,19 +20,19 @@
2020
import java.util.Map;
2121

2222
final class HttpVideoAsset extends VideoAsset {
23-
private static final String DEFAULT_USER_AGENT = "ExoPlayer";
24-
private static final String HEADER_USER_AGENT = "User-Agent";
25-
2623
@NonNull private final StreamingFormat streamingFormat;
2724
@NonNull private final Map<String, String> httpHeaders;
25+
@Nullable private final String userAgent;
2826

2927
HttpVideoAsset(
3028
@Nullable String assetUrl,
3129
@NonNull StreamingFormat streamingFormat,
32-
@NonNull Map<String, String> httpHeaders) {
30+
@NonNull Map<String, String> httpHeaders,
31+
@Nullable String userAgent) {
3332
super(assetUrl);
3433
this.streamingFormat = streamingFormat;
3534
this.httpHeaders = httpHeaders;
35+
this.userAgent = userAgent;
3636
}
3737

3838
@NonNull
@@ -75,10 +75,6 @@ public MediaSource.Factory getMediaSourceFactory(@NonNull Context context) {
7575
@VisibleForTesting
7676
MediaSource.Factory getMediaSourceFactory(
7777
Context context, DefaultHttpDataSource.Factory initialFactory) {
78-
String userAgent = DEFAULT_USER_AGENT;
79-
if (!httpHeaders.isEmpty() && httpHeaders.containsKey(HEADER_USER_AGENT)) {
80-
userAgent = httpHeaders.get(HEADER_USER_AGENT);
81-
}
8278
unstableUpdateDataSourceFactory(initialFactory, httpHeaders, userAgent);
8379
DataSource.Factory dataSourceFactory = new DefaultDataSource.Factory(context, initialFactory);
8480
return new DefaultMediaSourceFactory(context).setDataSourceFactory(dataSourceFactory);

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

Lines changed: 95 additions & 65 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,19 @@ public enum PlatformVideoViewType {
7777
}
7878
}
7979

80+
/** Pigeon equivalent of video_platform_interface's VideoFormat. */
81+
public enum PlatformVideoFormat {
82+
DASH(0),
83+
HLS(1),
84+
SS(2);
85+
86+
final int index;
87+
88+
PlatformVideoFormat(final int index) {
89+
this.index = index;
90+
}
91+
}
92+
8093
/**
8194
* Information passed to the platform view creation.
8295
*
@@ -151,43 +164,26 @@ ArrayList<Object> toList() {
151164

152165
/** Generated class from Pigeon that represents data sent in messages. */
153166
public static final class CreateMessage {
154-
private @Nullable String asset;
155-
156-
public @Nullable String getAsset() {
157-
return asset;
158-
}
167+
private @NonNull String uri;
159168

160-
public void setAsset(@Nullable String setterArg) {
161-
this.asset = setterArg;
162-
}
163-
164-
private @Nullable String uri;
165-
166-
public @Nullable String getUri() {
169+
public @NonNull String getUri() {
167170
return uri;
168171
}
169172

170-
public void setUri(@Nullable String setterArg) {
173+
public void setUri(@NonNull String setterArg) {
174+
if (setterArg == null) {
175+
throw new IllegalStateException("Nonnull field \"uri\" is null.");
176+
}
171177
this.uri = setterArg;
172178
}
173179

174-
private @Nullable String packageName;
175-
176-
public @Nullable String getPackageName() {
177-
return packageName;
178-
}
179-
180-
public void setPackageName(@Nullable String setterArg) {
181-
this.packageName = setterArg;
182-
}
180+
private @Nullable PlatformVideoFormat formatHint;
183181

184-
private @Nullable String formatHint;
185-
186-
public @Nullable String getFormatHint() {
182+
public @Nullable PlatformVideoFormat getFormatHint() {
187183
return formatHint;
188184
}
189185

190-
public void setFormatHint(@Nullable String setterArg) {
186+
public void setFormatHint(@Nullable PlatformVideoFormat setterArg) {
191187
this.formatHint = setterArg;
192188
}
193189

@@ -204,6 +200,16 @@ public void setHttpHeaders(@NonNull Map<String, String> setterArg) {
204200
this.httpHeaders = setterArg;
205201
}
206202

203+
private @Nullable String userAgent;
204+
205+
public @Nullable String getUserAgent() {
206+
return userAgent;
207+
}
208+
209+
public void setUserAgent(@Nullable String setterArg) {
210+
this.userAgent = setterArg;
211+
}
212+
207213
private @Nullable PlatformVideoViewType viewType;
208214

209215
public @Nullable PlatformVideoViewType getViewType() {
@@ -226,58 +232,49 @@ public boolean equals(Object o) {
226232
return false;
227233
}
228234
CreateMessage that = (CreateMessage) o;
229-
return Objects.equals(asset, that.asset)
230-
&& Objects.equals(uri, that.uri)
231-
&& Objects.equals(packageName, that.packageName)
235+
return uri.equals(that.uri)
232236
&& Objects.equals(formatHint, that.formatHint)
233237
&& httpHeaders.equals(that.httpHeaders)
238+
&& Objects.equals(userAgent, that.userAgent)
234239
&& Objects.equals(viewType, that.viewType);
235240
}
236241

237242
@Override
238243
public int hashCode() {
239-
return Objects.hash(asset, uri, packageName, formatHint, httpHeaders, viewType);
244+
return Objects.hash(uri, formatHint, httpHeaders, userAgent, viewType);
240245
}
241246

242247
public static final class Builder {
243248

244-
private @Nullable String asset;
245-
246-
@CanIgnoreReturnValue
247-
public @NonNull Builder setAsset(@Nullable String setterArg) {
248-
this.asset = setterArg;
249-
return this;
250-
}
251-
252249
private @Nullable String uri;
253250

254251
@CanIgnoreReturnValue
255-
public @NonNull Builder setUri(@Nullable String setterArg) {
252+
public @NonNull Builder setUri(@NonNull String setterArg) {
256253
this.uri = setterArg;
257254
return this;
258255
}
259256

260-
private @Nullable String packageName;
257+
private @Nullable PlatformVideoFormat formatHint;
261258

262259
@CanIgnoreReturnValue
263-
public @NonNull Builder setPackageName(@Nullable String setterArg) {
264-
this.packageName = setterArg;
260+
public @NonNull Builder setFormatHint(@Nullable PlatformVideoFormat setterArg) {
261+
this.formatHint = setterArg;
265262
return this;
266263
}
267264

268-
private @Nullable String formatHint;
265+
private @Nullable Map<String, String> httpHeaders;
269266

270267
@CanIgnoreReturnValue
271-
public @NonNull Builder setFormatHint(@Nullable String setterArg) {
272-
this.formatHint = setterArg;
268+
public @NonNull Builder setHttpHeaders(@NonNull Map<String, String> setterArg) {
269+
this.httpHeaders = setterArg;
273270
return this;
274271
}
275272

276-
private @Nullable Map<String, String> httpHeaders;
273+
private @Nullable String userAgent;
277274

278275
@CanIgnoreReturnValue
279-
public @NonNull Builder setHttpHeaders(@NonNull Map<String, String> setterArg) {
280-
this.httpHeaders = setterArg;
276+
public @NonNull Builder setUserAgent(@Nullable String setterArg) {
277+
this.userAgent = setterArg;
281278
return this;
282279
}
283280

@@ -291,41 +288,37 @@ public static final class Builder {
291288

292289
public @NonNull CreateMessage build() {
293290
CreateMessage pigeonReturn = new CreateMessage();
294-
pigeonReturn.setAsset(asset);
295291
pigeonReturn.setUri(uri);
296-
pigeonReturn.setPackageName(packageName);
297292
pigeonReturn.setFormatHint(formatHint);
298293
pigeonReturn.setHttpHeaders(httpHeaders);
294+
pigeonReturn.setUserAgent(userAgent);
299295
pigeonReturn.setViewType(viewType);
300296
return pigeonReturn;
301297
}
302298
}
303299

304300
@NonNull
305301
ArrayList<Object> toList() {
306-
ArrayList<Object> toListResult = new ArrayList<>(6);
307-
toListResult.add(asset);
302+
ArrayList<Object> toListResult = new ArrayList<>(5);
308303
toListResult.add(uri);
309-
toListResult.add(packageName);
310304
toListResult.add(formatHint);
311305
toListResult.add(httpHeaders);
306+
toListResult.add(userAgent);
312307
toListResult.add(viewType);
313308
return toListResult;
314309
}
315310

316311
static @NonNull CreateMessage fromList(@NonNull ArrayList<Object> pigeonVar_list) {
317312
CreateMessage pigeonResult = new CreateMessage();
318-
Object asset = pigeonVar_list.get(0);
319-
pigeonResult.setAsset((String) asset);
320-
Object uri = pigeonVar_list.get(1);
313+
Object uri = pigeonVar_list.get(0);
321314
pigeonResult.setUri((String) uri);
322-
Object packageName = pigeonVar_list.get(2);
323-
pigeonResult.setPackageName((String) packageName);
324-
Object formatHint = pigeonVar_list.get(3);
325-
pigeonResult.setFormatHint((String) formatHint);
326-
Object httpHeaders = pigeonVar_list.get(4);
315+
Object formatHint = pigeonVar_list.get(1);
316+
pigeonResult.setFormatHint((PlatformVideoFormat) formatHint);
317+
Object httpHeaders = pigeonVar_list.get(2);
327318
pigeonResult.setHttpHeaders((Map<String, String>) httpHeaders);
328-
Object viewType = pigeonVar_list.get(5);
319+
Object userAgent = pigeonVar_list.get(3);
320+
pigeonResult.setUserAgent((String) userAgent);
321+
Object viewType = pigeonVar_list.get(4);
329322
pigeonResult.setViewType((PlatformVideoViewType) viewType);
330323
return pigeonResult;
331324
}
@@ -345,8 +338,13 @@ protected Object readValueOfType(byte type, @NonNull ByteBuffer buffer) {
345338
return value == null ? null : PlatformVideoViewType.values()[((Long) value).intValue()];
346339
}
347340
case (byte) 130:
348-
return PlatformVideoViewCreationParams.fromList((ArrayList<Object>) readValue(buffer));
341+
{
342+
Object value = readValue(buffer);
343+
return value == null ? null : PlatformVideoFormat.values()[((Long) value).intValue()];
344+
}
349345
case (byte) 131:
346+
return PlatformVideoViewCreationParams.fromList((ArrayList<Object>) readValue(buffer));
347+
case (byte) 132:
350348
return CreateMessage.fromList((ArrayList<Object>) readValue(buffer));
351349
default:
352350
return super.readValueOfType(type, buffer);
@@ -358,11 +356,14 @@ protected void writeValue(@NonNull ByteArrayOutputStream stream, Object value) {
358356
if (value instanceof PlatformVideoViewType) {
359357
stream.write(129);
360358
writeValue(stream, value == null ? null : ((PlatformVideoViewType) value).index);
361-
} else if (value instanceof PlatformVideoViewCreationParams) {
359+
} else if (value instanceof PlatformVideoFormat) {
362360
stream.write(130);
361+
writeValue(stream, value == null ? null : ((PlatformVideoFormat) value).index);
362+
} else if (value instanceof PlatformVideoViewCreationParams) {
363+
stream.write(131);
363364
writeValue(stream, ((PlatformVideoViewCreationParams) value).toList());
364365
} else if (value instanceof CreateMessage) {
365-
stream.write(131);
366+
stream.write(132);
366367
writeValue(stream, ((CreateMessage) value).toList());
367368
} else {
368369
super.writeValue(stream, value);
@@ -382,6 +383,9 @@ public interface AndroidVideoPlayerApi {
382383

383384
void setMixWithOthers(@NonNull Boolean mixWithOthers);
384385

386+
@NonNull
387+
String getLookupKeyForAsset(@NonNull String asset, @Nullable String packageName);
388+
385389
/** The codec used by AndroidVideoPlayerApi. */
386390
static @NonNull MessageCodec<Object> getCodec() {
387391
return PigeonCodec.INSTANCE;
@@ -498,6 +502,32 @@ static void setUp(
498502
channel.setMessageHandler(null);
499503
}
500504
}
505+
{
506+
BasicMessageChannel<Object> channel =
507+
new BasicMessageChannel<>(
508+
binaryMessenger,
509+
"dev.flutter.pigeon.video_player_android.AndroidVideoPlayerApi.getLookupKeyForAsset"
510+
+ messageChannelSuffix,
511+
getCodec());
512+
if (api != null) {
513+
channel.setMessageHandler(
514+
(message, reply) -> {
515+
ArrayList<Object> wrapped = new ArrayList<>();
516+
ArrayList<Object> args = (ArrayList<Object>) message;
517+
String assetArg = (String) args.get(0);
518+
String packageNameArg = (String) args.get(1);
519+
try {
520+
String output = api.getLookupKeyForAsset(assetArg, packageNameArg);
521+
wrapped.add(0, output);
522+
} catch (Throwable exception) {
523+
wrapped = wrapError(exception);
524+
}
525+
reply.reply(wrapped);
526+
});
527+
} else {
528+
channel.setMessageHandler(null);
529+
}
530+
}
501531
}
502532
}
503533
/** Generated interface from Pigeon that represents a handler of messages from Flutter. */

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

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,8 @@ public MediaItem getMediaItem() {
2626
// TODO: Migrate to stable API, see https://github.com/flutter/flutter/issues/147039.
2727
@OptIn(markerClass = UnstableApi.class)
2828
@Override
29-
public MediaSource.Factory getMediaSourceFactory(Context context) {
29+
@NonNull
30+
public MediaSource.Factory getMediaSourceFactory(@NonNull Context context) {
3031
return new RtspMediaSource.Factory();
3132
}
3233
}

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

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -40,8 +40,9 @@ static VideoAsset fromAssetUrl(@NonNull String assetUrl) {
4040
static VideoAsset fromRemoteUrl(
4141
@Nullable String remoteUrl,
4242
@NonNull StreamingFormat streamingFormat,
43-
@NonNull Map<String, String> httpHeaders) {
44-
return new HttpVideoAsset(remoteUrl, streamingFormat, new HashMap<>(httpHeaders));
43+
@NonNull Map<String, String> httpHeaders,
44+
@Nullable String userAgent) {
45+
return new HttpVideoAsset(remoteUrl, streamingFormat, new HashMap<>(httpHeaders), userAgent);
4546
}
4647

4748
/**

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

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -8,10 +8,7 @@
88
import androidx.annotation.Nullable;
99
import androidx.annotation.VisibleForTesting;
1010
import io.flutter.plugin.common.EventChannel;
11-
import java.util.Arrays;
12-
import java.util.Collections;
1311
import java.util.HashMap;
14-
import java.util.List;
1512
import java.util.Map;
1613

1714
final class VideoPlayerEventCallbacks implements VideoPlayerCallbacks {
@@ -66,12 +63,9 @@ public void onBufferingStart() {
6663

6764
@Override
6865
public void onBufferingUpdate(long bufferedPosition) {
69-
// iOS supports a list of buffered ranges, so we send as a list with a single range.
7066
Map<String, Object> event = new HashMap<>();
7167
event.put("event", "bufferingUpdate");
72-
73-
List<? extends Number> range = Arrays.asList(0, bufferedPosition);
74-
event.put("values", Collections.singletonList(range));
68+
event.put("position", bufferedPosition);
7569
eventSink.success(event);
7670
}
7771

0 commit comments

Comments
 (0)