The following classic code snippet fails to fetch the video from Bunny CDN
@override
void initState() {
super.initState();
controller = VideoPlayerController.networkUrl(Uri.parse(widget.video),
httpHeaders: {"AccessKey": CDN_READ_ONLY_TOKEN});
controller.initialize();
}
I get the following error:
E/ExoPlayerImplInternal(14202): Playback error
E/ExoPlayerImplInternal(14202): com.google.android.exoplayer2.ExoPlaybackException: Source error
E/ExoPlayerImplInternal(14202): at com.google.android.exoplayer2.ExoPlayerImplInternal.handleIoException(ExoPlayerImplInternal.java:644)
E/ExoPlayerImplInternal(14202): at com.google.android.exoplayer2.ExoPlayerImplInternal.handleMessage(ExoPlayerImplInternal.java:616)
E/ExoPlayerImplInternal(14202): at android.os.Handler.dispatchMessage(Handler.java:103)
E/ExoPlayerImplInternal(14202): at android.os.Looper.loop(Looper.java:224)
E/ExoPlayerImplInternal(14202): at android.os.HandlerThread.run(HandlerThread.java:67)
E/ExoPlayerImplInternal(14202): Caused by: com.google.android.exoplayer2.upstream.HttpDataSource$InvalidResponseCodeException: Response code: 401
E/ExoPlayerImplInternal(14202): at com.google.android.exoplayer2.upstream.DefaultHttpDataSource.open(DefaultHttpDataSource.java:413)
E/ExoPlayerImplInternal(14202): at com.google.android.exoplayer2.upstream.DefaultDataSource.open(DefaultDataSource.java:263)
E/ExoPlayerImplInternal(14202): at com.google.android.exoplayer2.upstream.StatsDataSource.open(StatsDataSource.java:84)
E/ExoPlayerImplInternal(14202): at com.google.android.exoplayer2.source.ProgressiveMediaPeriod$ExtractingLoadable.load(ProgressiveMediaPeriod.java:1005)
E/ExoPlayerImplInternal(14202): at com.google.android.exoplayer2.upstream.Loader$LoadTask.run(Loader.java:412)
E/ExoPlayerImplInternal(14202): at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1167)
E/ExoPlayerImplInternal(14202): at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:641)
E/ExoPlayerImplInternal(14202): at java.lang.Thread.run(Thread.java:919)
I would think that the problem is the accessKey, however:
- the app works perfectly on iOS
- a normal get request from anywhere else in the app with the right headers, works as expected.
After checking github and SO for potential solutions, I tried a modifying the AndroidManifest.xml
file and adding the following lines
<uses-permission android:name="android.permission.INTERNET"/>
<application android:usesCleartextTraffic="true"/>
I also tried integrating the AccessKey directly in the url like this:
https://storage.bunnycdn.com/XXX-YYY/video-acbce1cce090476a95b03cd485a1e54d.mp4?AccessKey=XXX
This link directly opens the video in the browser and also works on iOS, but fails on Android with the same error.
Finally, I found this thread on github regarding self-signed SSL certificates, but I am not sure this is the problem given that the error complains specifically about the authorization and not the server's certificates.
https://github.com/flutter/flutter/issues/75995
Nevertheless, I added the following network_security_config, which did not solve the problem
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<domain-config>
<domain includeSubdomains="true">storage.bunnycdn.com</domain>
<trust-anchors>
<!-- Trust all certificates -->
<certificates src="user" />
<certificates src="system" />
</trust-anchors>
</domain-config>
</network-security-config>
Anyone else dealt with something like this before?