androidflutterflutter-video-playerbunnycdn

video_player returns a 401 Unauthorized with Bunny CDN on Android


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:

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?


Solution

  • You cannot pull directly from the storage zone. You should set up a pull zone and access the link through there. On top of that you will not need an accessKey