i'm using webview_flutter: ^0.3.14+1.
Webview can't load web page https://m.bilibili.com/video/av57346110.html correctly. The web page is oversized
But if I open it with chrome, the web page fits screen correctly.
And I don't understand the difference between web browser and flutter webview.
Here's minimal codes to reproduce:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(new MyApp());
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
#override
Widget build(BuildContext context) {
return new MaterialApp(
home: new Scaffold(
appBar: new AppBar(),
body: Container(
child: WebView(
initialUrl: "https://m.bilibili.com/video/av57346110.html",
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (NavigationRequest request) {
print("Loading... ${request.url}");
if(request.url.startsWith("http")) {
return NavigationDecision.navigate;
} else {
return NavigationDecision.prevent;
}
},
),
),
),
);
}
}
I implement this with same plugin 'webview_flutter' and it is working just fine.
Here is my code
WebView(
initialUrl: 'https://m.bilibili.com/video/av57346110.html',
javascriptMode: JavascriptMode.unrestricted,
allowsInlineMediaPlayback: true,
)
Related
I have some simple code here that just displays a webpage. I want to make it so that, pressing the device back button takes you to the previous page on the webview. I tried looking for solutions online but was unable to integrate any of them into my code. Kindly help me out.
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatefulWidget {
#override
MyAppState createState() => MyAppState();
}
class MyAppState extends State<MyApp> {
#override
void initState() {
super.initState();
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
#override
Widget build(BuildContext context) {
return MaterialApp(
title: "Mobile App",
home: Scaffold(
body: SafeArea(
child: WebView(
initialUrl: 'https://flutter.dev',
javascriptMode: JavascriptMode.unrestricted,
))),
debugShowCheckedModeBanner: false,
);
}
}
Wrap Scaffold with this widget
WillPopScope(
onWillPop: controller.onBackPressedHandler,
child: Scaffold( ... )
Future<bool> onBackPressedHandler() {
return Future.value(false);} //return false disables default functionality
you can control back button functionality in onBackPressedHandler function.
For your case you should put this line of code inside it
webviewController.goBack();
I am working on Flutter webview apps using Flutter Webview plugin.
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child : const WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
),
)
)
);
}
}
However, if any links inside the opened web page is an app link, like: fb://profile, I will get net::ERR_UNKNOWN_URL_SCHEME.
In android, I found the solution is to override shouldOverrideUrlLoading as mentioned here, but what should I do in flutter?
I'm trying the solution mentioned here.
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child : const WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (NavigationRequest request) {
if (request.url.contains("mailto:")) {
launch(request.url);
return NavigationDecision.navigate;
}
},
),
)
)
);
}
}
But it is throwing errors like
Error: Not a constant expression.
if (request.url.contains("mailto:")) {
You can copy paste run full code below
Step 1: You can remove const keyword from const WebView
Step 2: You can use NavigationDecision.prevent
working demo
full code
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:url_launcher/url_launcher.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
body: SafeArea(
child: WebView(
initialUrl:
'https://google.com', //'''https://www.scottseverance.us/mailto.html',
javascriptMode: JavascriptMode.unrestricted,
navigationDelegate: (NavigationRequest request) {
print(request.url);
if (request.url.contains("mailto:")) {
launch(request.url);
return NavigationDecision.prevent;
} else {
return NavigationDecision.navigate;
}
},
),
)));
}
}
I am running flutter 1.17.1, using webview_flutter: ^0.3.21
dependencies added to pubspec.yaml and added this to the end of info.plist
<key>io.flutter.embedded_views_preview</key>
<string>YES</string>
Problem: Webpage loaded into webview is too big to fit mobile phone screen.
screenshot
Here is the code with the webview:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebViewContainer extends StatefulWidget {
final url;
WebViewContainer(this.url);
#override
createState() => _WebViewContainerState(this.url);
}
class _WebViewContainerState extends State<WebViewContainer> {
var _url;
final _key = UniqueKey();
_WebViewContainerState(this._url);
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(),
body: Column(
children: [
Expanded(
child: WebView(
key: _key,
javascriptMode: JavascriptMode.unrestricted,
initialUrl: _url))
],
));
}
}
Link to the full app:
https://github.com/bi-samson/mreader
I've tried a minimal repro with the url "https://www.businessinsider.jp/" and the latest version of webview_flutter, this is the output:
Minimal repro:
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'dart:async';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
visualDensity: VisualDensity.adaptivePlatformDensity,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key? key, required this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: WebView(
initialUrl: "https://www.businessinsider.jp/",
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
javascriptMode: JavascriptMode.unrestricted,
),
);
}
}
It seems that the issue doesn't occur in the latest version.
Use InAppWebView instead of WebView.
This will add a line like this to your package's pubspec.yaml:
dependencies:
flutter_inappwebview: ^5.3.2
Here is a code example:
return InAppWebView(
initialOptions: InAppWebViewGroupOptions(
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
textZoom: 100 * 2 // it makes 2 times bigger
)
),
onWebViewCreated: (InAppWebViewController controller) {
webViewController = controller;
controller.loadData(data: widget.html, mimeType: "text/html");
},
);
If you want to make it smaller, you just need to divide it as below:
textZoom: 100 / 2 // it makes 2 times smaller
I am trying to use WebView() on my flutter app. After I wrote the code there are not any errors, however, when running the debug mode on my simulator the page is blank. The AppBar is there and the text is on it also, but the body is a blank screen.
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class Audio extends StatefulWidget {
#override
_AudioState createState() => _AudioState();
}
class _AudioState extends State<Audio> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Audio"),
),
body: WebView(
key: UniqueKey(),
initialUrl: "http://google.com",
javascriptMode: JavascriptMode.unrestricted
),
);
}
}
This is pretty much an intended behavior. It seems that the initialUrl you've provided is an insecure HTTP connection.
The documentation "Insecure HTTP connections are disabled by default on iOS and Android" explains everything about this:
Starting with Android API
28
and iOS
9,
these platforms disable insecure HTTP connections by default.
With this change Flutter also disables insecure connections on mobile
platforms. Other platforms (desktop, web, etc) are not affected.
You can override this behavior by following the platform-specific
guidelines to define a domain-specific network policy. See the
migration guide below for details.
Much like the platforms, the application can still open insecure
socket connections. Flutter does not enforce any policy at socket
level; you would be responsible for securing the connection.
Here are the sample scenarios:
Scenario 1:
Using "http://google.com"
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(Audio());
}
class Audio extends StatefulWidget {
#override
_AudioState createState() => _AudioState();
}
class _AudioState extends State<Audio> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Audio"),
),
body: WebView(
key: UniqueKey(),
initialUrl: "http://google.com",
javascriptMode: JavascriptMode.unrestricted),
),
);
}
}
Scenario 2:
Using "google.com"
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(Audio());
}
class Audio extends StatefulWidget {
#override
_AudioState createState() => _AudioState();
}
class _AudioState extends State<Audio> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Audio"),
),
body: WebView(
key: UniqueKey(),
initialUrl: "google.com",
javascriptMode: JavascriptMode.unrestricted),
),
);
}
}
Scenario 3:
Using "https://www.google.com/"
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(Audio());
}
class Audio extends StatefulWidget {
#override
_AudioState createState() => _AudioState();
}
class _AudioState extends State<Audio> {
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: Text("Audio"),
),
body: WebView(
key: UniqueKey(),
initialUrl: "https://www.google.com/",
javascriptMode: JavascriptMode.unrestricted),
),
);
}
}
I am making Downloader app which has a Webview where user can browse when there is the video playing he can download by click float button .but the problem is that it has only initial URL I want final URL to send it to my API to download that video.How to get Final Url in webview
import 'dart:html';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main(){
runApp(myapp());
}
class myapp extends StatefulWidget {
#override
_myappState createState() => _myappState();
}
final Completer<WebViewController> _controller = Completer<WebViewController>();
class _myappState extends State<myapp> {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
appBar: AppBar(
title: new Text('Fb Video Downloader'),
backgroundColor: Colors.blueAccent,
),
body: Column(
children: <Widget>[
new Text(''),
WebView(
initialUrl: "https://example.com",
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webcontroller){
_controller.complete(webcontroller);
},
),
],
),
),
);
}
}`
Looking at the documentation for WebViewController it seems like it has a method called currentUrl() that probably will give you the result you're looking for.
currentUrl = await _yourWebController.currentUrl()