Reputation: 41
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
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
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
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