Mark
Mark

Reputation: 41

flutter_inappwebview - no html-video

I'm using flutter_inappwebview in a Flutter-app to display local html (from assets). (I know: not ideal. I would prefer to program the whole thing in Dart, but that is not an option right now). It works great..apart from one thing. Can't get the video in html to work.

Problem
The video works fine when I open the html in any browser (directly from assets folder). So the html should be ok. All other html works fine in the app. So files and pubspec-import should be ok. In the app, the page shows a video-player, but no content on both iOS-sim and iOS device. In the Android-sim it works.

Code
I'm using:
flutter_inappwebview: ^3.2.0
sdk: ">=2.7.0 <3.0.0"

I use the inappview like this, after the imports. Server is already running (flutter reports: flutter: Server running on http://localhost:8080)

InAppWebViewController webViewController;
InAppWebView webView;

class OfflineViewer extends StatefulWidget {
  @override
  _ViewerState createState() => _ViewerState();
}

class _ViewerState extends State<OfflineViewer> {
  @override
  Widget build(BuildContext context) {
    return InAppWebView(
      initialUrl: "http://localhost:8080/assets/source/intro.html",
      onWebViewCreated: (InAppWebViewController controller) {
        webViewController = controller;
      },
    );
  }
}

The video-tag in the loaded intro.html is:

  <video height="600" controls>
    <source src="intro.mp4" type="video/mp4">  
  Your browser does not support the video tag.
  </video>

Things I tried:
Different video-formats (webm, ogg) > no difference.
Loading an online video into the html instead of local > works. Video loads and plays.
Different methods of embedding video (video-tag, iframe, video.js) > no difference.
Setting InAppWebViewOptions, like:

cacheEnabled: true,
javaScriptCanOpenWindowsAutomatically: true,
useOnLoadResource: true,
javaScriptEnabled: true,
mediaPlaybackRequiresUserGesture: false,

What makes this hard to solve (for me) is that I can't catch the html-errors once it's embedded in the app, whereas the standalone html doesn't give an error. Any ideas on how to solve or even troubleshoot this are highly appreciated.

Greetings,
Mark

Upvotes: 2

Views: 3559

Answers (3)

Jack Ka
Jack Ka

Reputation: 1

https://stackoverflow.com/a/61999847/15258962 this make me realized ,the problem is not the WebView, its the LocalServer side.

I change the localServer logic to serve basic64 encoded video source when a video tag appeared ,and its worked for me

Upvotes: 0

Mark
Mark

Reputation: 41

Got it sorted. Just posting this in case anyone else has the same problem. Cause of the problem was: the HTTPServer-class creates a blob-server. It returns a video in one chunk (status 200). iOS doesn't accept that and wants status 206 (parts).

Based on https://stackoverflow.com/a/54004600/6007404 I created a JS-file which converts all the video's in the document. Just add it to any html-file with video:

if(navigator.platform && /iPad|iPhone|iPod|Mac/.test(navigator.platform)){
    window.addEventListener("load", streamVideoBlobs);
 }

function streamVideoBlobs(){
    var allVideos = document.getElementsByTagName("video");
    for(var i = 0, max = allVideos.length; i < max; i++) 
    {
        iOSVideoConvert(allVideos[i]);       
    }
}

async function iOSVideoConvert(video){
    let blob = await fetch(video.src).then(r => r.blob());
    var videoUrl=createObjectURL(blob);
    video.src = videoUrl;
}

function createObjectURL(object) {
    return (window.URL) ? window.URL.createObjectURL(object) : window.webkitURL.createObjectURL(object);
}

Apart from that, you'll have to set

<key>NSAppTransportSecurity</key>
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

in your info.plist. (You can also use NSAllowsArbitraryLoads, but that's more allowance then needed and Apple might flag it down when submitting the app).

Upvotes: 2

kuhnroyal
kuhnroyal

Reputation: 7563

Not sure but you may be missing the NSAppTransportSecurity setting in your Info.plist. This allows you to load unsafe content which http://localhost:8080 is.

    <key>NSAppTransportSecurity</key>
    <dict>
        <key>NSAllowsArbitraryLoads</key>
        <true/>
    </dict>

Upvotes: 0

Related Questions