Flutter display blank web page with webview_flutter - flutter

I have a problem with the visualization of a web page with webview_flutter, I have to display a web view, when I run the code on ios the view is displayed correctly, when I run the same code on android I have a blank page, how do I solve this thing? To what it is due, I report below the source codes
Pubspec.yaml
ReportView.dart
import 'dart:io';
import 'package:appsafetyeurope/model/Manutenzione.dart';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
String URLLOAD = "https://marconisoftware.com";
class ReportView extends StatefulWidget {
final Manutenzione man;
final String token;
final String url;
const ReportView(this.man, this.token, this.url);
#override
createState() => ReportViewState();
}
class ReportViewState extends State<ReportView> {
void _handleLoad(String value) {}
#override
void initState() {
super.initState();
// Enable virtual display.
if (Platform.isAndroid) {
//WebView.platform = SurfaceAndroidWebView();
WebView.platform = AndroidWebView();
}
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: IconButton(
icon: Icon(Icons.arrow_back_ios),
iconSize: 20.0,
onPressed: () {
Navigator.pop(context);
},
),
centerTitle: true,
title: Text('Report')),
body: IndexedStack(
index: 0,
children: [
Column(
children: <Widget>[
Expanded(
child: WebView(
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
Map<String, String> headers = {"Cmdbuild-authorization": widget.token};
webViewController.loadUrl(
widget.url +
"/services/rest/v3/reports/286763/Activity%20report.pdf?extension=pdf&parameters=%7B%22ProcessId%22%3A" +
widget.man.id.toString() +
"%7D",
headers: headers);
},
onPageFinished: _handleLoad,
)),
],
),
Container(
color: Colors.white,
child: Center(
child: CircularProgressIndicator(),
),
),
],
));
}
}

Related

Web view doesn't show the web page in Flutter application

I have this code in my flutter app :
class WebViewWidget1 extends StatefulWidget {
WebViewWidget1({Key? key}) : super(key: key);
#override
State<WebViewWidget1> createState() => _WebViewWidget1State();
}
class _WebViewWidget1State extends State<WebViewWidget1> {
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
centerTitle: true,
title: const Text('title'),
),
body: const WebView(
initialUrl: "https://github.com/ArjunMalhotra07",
javascriptMode: JavascriptMode.unrestricted,
),
);
}
}
I want to implement web view and this was the code I took from the internet. This just doesn't work. It shows a blank white screen with app bar only. Where am I wrong? can't deduce.
please add pubspec.yaml
flutter pub add flutter_inappwebview
inappwebview
Example:
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
class InAppWebViewPage extends StatefulWidget {
final String title, uri;
const InAppWebViewPage({Key? key, required this.title, required this.uri})
: super(key: key);
#override
_InAppWebViewPageState createState() => _InAppWebViewPageState();
}
class _InAppWebViewPageState extends State<InAppWebViewPage> {
int _stackIndex = 1;
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: Padding(
padding: EdgeInsets.all(12),
child: Expanded(
child: IndexedStack(
index: _stackIndex,
children: [
InAppWebView(
initialUrlRequest: URLRequest(url: Uri.parse(widget.uri)),
initialOptions: InAppWebViewGroupOptions(
crossPlatform:
InAppWebViewOptions(useShouldOverrideUrlLoading: true),
),
onLoadStop: (_, __) {
setState(() {
_stackIndex = 0;
});
},
onLoadError: (_, __, ___, ____) {
setState(() {
_stackIndex = 0;
});
//TODO: Show error alert message (Error in receive data from server)
},
onLoadHttpError: (_, __, ___, ____) {
setState(() {
_stackIndex = 0;
});
//TODO: Show error alert message (Error in receive data from server)
},
),
const SizedBox(
height: 50,
child: CircularProgressIndicator(),
),
],
),
),
),
);
}
}
Try to wrap WebView with SizedBox and give width and height to it.
SizedBox(
width: MediaQuery.of(context).size.width, // it uses all the width of screen, you can change it
height: MediaQuery.of(context).size.height, // it uses all the height of screen, you can change it
child: WebView(
initialUrl: "https://github.com/ArjunMalhotra07",
javascriptMode: JavascriptMode.unrestricted,
),
),
And don't forget to add webview_flutter package to your pubspec.yaml file.

Trying to build a future context but my build method has an error

I have this code and the problem is that:
'ProfileView.build' ('Future<Widget> Function(BuildContext)') isn't a valid override of 'StatelessWidget.build' ('Widget Function(BuildContext)').
I tried to remove future but it doesn't work, any idea?
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_bloc/flutter_bloc.dart';
import 'package:flutter_form_bloc/flutter_form_bloc.dart';
import 'package:maze/authentication/bloc/authentication_bloc.dart';
import 'package:maze/core/drawer.dart';
import 'package:webview_flutter/webview_flutter.dart';
import '../../authentication/bloc/authentication_state.dart';
import '../../core/secure_store.dart';
class ProfileView extends StatelessWidget {
const ProfileView({Key? key}) : super(key: key);
#override
Future<Widget> build(BuildContext context) async {
var state = BlocProvider
.of<AuthenticationBloc>(context)
.state;
var token = await SecureStore().credentials;
final Completer<WebViewController> _controller =
Completer<WebViewController>();
return Scaffold(
appBar: AppBar(
title: const Text('Profile'),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
child: Text("name",
style: new TextStyle(fontWeight: FontWeight.bold)),
alignment: Alignment.bottomCenter,
),
),
],
),
drawer: const CustomDrawer(),
body: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
return Center(
child: WebView(
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
webViewController.loadUrl(
"http://exemple.../",
headers: {"Authorization": "Bearer ${token}"});
_controller.complete(webViewController);
},
)
);
},
),
);
}
}
I understood that you wanted to have your build method as async because you want to wait for the token to be initialized, but there is a better way to achieve this and here is the solution:
import 'package:flutter/material.dart';
class ProfileView extends StatefulWidget {
const ProfileView({Key? key}) : super(key: key);
#override
_ProfileViewState createState() => _ProfileViewState();
}
class _ProfileViewState extends State<ProfileView> {
var state;
var token;
#override
void initState() {
super.initState();
state = BlocProvider
.of<AuthenticationBloc>(context)
.state;
initToken();
}
initToken() async {
token = await SecureStore().credentials;
}
#override
Widget build(BuildContext context) {
final Completer<WebViewController> _controller = Completer<WebViewController>();
return Scaffold(
appBar: AppBar(
title: const Text('Profile'),
actions: [
Padding(
padding: const EdgeInsets.all(8.0),
child: Align(
child: Text("name",
style: new TextStyle(fontWeight: FontWeight.bold)),
alignment: Alignment.bottomCenter,
),
),
],
),
drawer: const CustomDrawer(),
body: BlocBuilder<AuthenticationBloc, AuthenticationState>(
builder: (context, state) {
return Center(
child: WebView(
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
webViewController.loadUrl(
"http:exemple...",
headers: {"Authorization": "Bearer ${token}"});
_controller.complete(webViewController);
},
)
);
},
),
);
}
}
Read about the widget lifecycle, it would help you understand why you had the error in the first place.

How to show Loading Indicator background transparent in WebView Flutter?

I'm new to flutter and making my first webview app. Here I'm trying to add a spinner every time when a user tries to click the link or page load. I want to make spinner background opacity a bit low just like the given example(right picture) but opacity doesn't work at all.
Here is my approach:
// ignore_for_file: prefer_const_constructors
// ignore: use_key_in_widget_constructors
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
debugShowCheckedModeBanner: false,
home: Scaffold(
body: WebViewClass()
)
);
}
}
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass>{
int position = 1 ;
final key = UniqueKey();
doneLoading(String A) {
setState(() {
position = 0;
});
}
startLoading(String A){
setState(() {
position = 1;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: SafeArea(child: IndexedStack(
index: position,
children: <Widget>[
WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
key: key ,
onPageFinished: doneLoading,
onPageStarted: startLoading,
),
Container(
color: Colors.white70,
child: Center(
child: CircularProgressIndicator()),
),
]))
);
}
}
Any help or guidance will highly appreciated.
You can try like this. every time when you come in the web view screen. the loader will show.
class WebViewClass extends StatefulWidget {
WebViewState createState() => WebViewState();
}
class WebViewState extends State<WebViewClass> {
bool isLoading = false;
final key = UniqueKey();
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: SafeArea(
child: IgnorePointer(
ignoring: isLoading,
child: Stack(
children: [
WebView(
initialUrl: 'https://google.com',
javascriptMode: JavascriptMode.unrestricted,
key: key,
onPageFinished: (value) {
setState(() {
isLoading = false;
});
},
onPageStarted: (value) {
setState(() {
isLoading = true;
});
},
),
isLoading ? Container(
width: MediaQuery.of(context).size.width,
height: MediaQuery.of(context).size.height,
color: Colors.grey.withOpacity(0.5),
child: const Center(child: CircularProgressIndicator()) ,
) : Container(),
],
),
)),);
}
}

Android crashes when I try to use qr scanning with a web view

I try to use a QR Code Scanner from qr_code_scanner in conjunction with a Webview component webview_flutter.
Everything works fine on iOS but on Android devices it doesn't work, the QR scanner doesn't show and I get a repeated console print.
D/mali_winsys(30667): EGLint new_window_surface(egl_winsys_display *, void *, EGLSurface, EGLConfig, egl_winsys_surface **, EGLBoolean) returns 0x3000
I've tried this on two Android devices (Android 10, v29 and Android 7, v24) with same results.
Below is a minimal app that reproduce the issue. It requires the following dependencies:
qr_code_scanner: ^0.3.5
webview_flutter: ^2.0.2
The code below shows a full-screen webview with a button on-top. Press the button and the QR scanner will/should show up...
import 'package:flutter/material.dart';
import 'dart:io';
import 'package:flutter/foundation.dart';
import 'package:qr_code_scanner/qr_code_scanner.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() {
runApp(MyApp());
}
class MyApp extends StatelessWidget {
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}
class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);
final String title;
#override
_MyHomePageState createState() => _MyHomePageState();
}
class _MyHomePageState extends State<MyHomePage> {
bool _showQr = false;
#override
void initState() {
super.initState();
// Enable hybrid composition.
if (Platform.isAndroid) WebView.platform = SurfaceAndroidWebView();
}
void closeQr() {
setState(() {
_showQr = false;
});
}
#override
Widget build(BuildContext context) {
return Stack(
children: [
Stack(
children: [
WebView(
initialUrl: 'https://flutter.dev',
),
Center(
child: TextButton(
onPressed: () {
setState(() {
_showQr = !_showQr;
});
},
child: Text('Show QR Scanner'),
style: TextButton.styleFrom(
primary: Colors.white,
backgroundColor: Colors.teal,
onSurface: Colors.grey,
),
),
),
],
),
Center(
child: (_showQr) ? QRWidget(onClose: closeQr) : null,
),
],
);
}
}
class QRWidget extends StatefulWidget {
const QRWidget({
Key key,
this.onClose,
}) : super(key: key);
final Function onClose;
#override
State<StatefulWidget> createState() => _QRWidgetState();
}
class _QRWidgetState extends State<QRWidget> {
Barcode result;
QRViewController controller;
final GlobalKey qrKey = GlobalKey(debugLabel: 'QR');
// In order to get hot reload to work we need to pause the camera if the platform
// is android, or resume the camera if the platform is iOS.
#override
void reassemble() {
super.reassemble();
if (Platform.isAndroid) {
controller.pauseCamera();
}
controller.resumeCamera();
}
#override
Widget build(BuildContext context) {
return Scaffold(
body: Stack(
children: <Widget>[
_buildQrView(context),
Container(
alignment: Alignment.bottomCenter,
padding: EdgeInsets.only(bottom: 60.0),
child: Row(
children: <Widget>[
Expanded(
child: RawMaterialButton(
onPressed: () {
setState(() {
widget.onClose();
});
},
elevation: 2.0,
fillColor: Colors.white,
child: Icon(
Icons.close_sharp,
color: Color(0xff459d44),
size: 40.0,
),
padding: EdgeInsets.all(8.0),
shape: CircleBorder(),
),
),
],
),
)
],
),
);
}
Widget _buildQrView(BuildContext context) {
// For this example we check how width or tall the device is and change the scanArea and overlay accordingly.
var scanArea = (MediaQuery.of(context).size.width < 400 ||
MediaQuery.of(context).size.height < 400)
? 150.0
: 300.0;
// To ensure the Scanner view is properly sizes after rotation
// we need to listen for Flutter SizeChanged notification and update controller
return QRView(
key: qrKey,
onQRViewCreated: _onQRViewCreated,
overlay: QrScannerOverlayShape(
borderColor: Color(0xff459d44),
borderRadius: 10,
borderLength: 30,
borderWidth: 10,
cutOutSize: scanArea),
);
}
void _onQRViewCreated(QRViewController controller) {
setState(() {
this.controller = controller;
});
controller.scannedDataStream.listen((scanData) {
setState(() {
result = scanData;
});
});
}
#override
void dispose() {
controller?.dispose();
super.dispose();
}
}
Why doesn't it work on Android?
did you add the permission in AndroidManifest.xml
<uses-permission android:name="android.permission.CAMERA" />
if its webview, why dont you use flutter_inappwebview . Its good to use and has a lot of additional features you may want later. it still needs permission on androidmanifest. Following is the example if you decide to choose flutter_inappwebview.
class _HomePageState extends State<HomePage> {
InAppWebViewController webView;
String url = "";
#override
void initState(){
checkPermissions();
super.initState();
}
#override
void dispose() {
super.dispose();
}
checkPermissions() async{
await [
Permission.camera,
Permission.storage,
].request();
}
#override
Widget build(BuildContext context) {
return Scaffold(
resizeToAvoidBottomInset: false,
body: SafeArea(
child: Container(
child: Column(children: <Widget>[
Expanded(
child: Container(
child: InAppWebView(
initialUrl: 'https://flutter.dev',
initialHeaders: {},
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
},
onLoadStart: (InAppWebViewController controller, String url) {
setState(() {
this.url = url;
});
},
onLoadStop: (InAppWebViewController controller, String url) async {
setState(() {
this.url = url;
});
},
/// this is the important one to pass the permission
androidOnPermissionRequest: (InAppWebViewController controller, String origin, List<String> resources) async {
return PermissionRequestResponse(resources: resources, action: PermissionRequestResponseAction.GRANT);
},
),
),
),
])
),
),
);
}
}
dont forget to add this permission_handler in your pubspec.yaml

Flutter load webview inside the fragment

// Here is my flutter code
import 'package:flutter/material.dart';
import 'package:flutter_webview_plugin/flutter_webview_plugin.dart';
class HairtipsPage extends StatefulWidget {
#override
_HairtipsPageState createState() => _HairtipsPageState();
}
class _HairtipsPageState extends State<HairtipsPage> {
#override
Widget build(BuildContext context) {
return Scaffold(
body: Center(
child : WebviewScaffold(
url: "https://www.google.com",
appBar: new AppBar(
// title: new Text('Hairtips'),
),
withZoom: true,
withLocalStorage: true,
)
),
);
}
}
I am using bottom navigation in my app and trying to implement webview inside the fragment.i know how to acheive the same in android also i dont want the webview should open in a browser.i am expecting the webview should load inside the app and within the fragment.
You can use the Flutter webview plugin. Here is the URL for the plugin https://pub.dartlang.org/packages/webview_flutter
The webview will load inside the App with CircularProgressIndicator.
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
class WebView extends StatefulWidget {
#override
_WebViewState createState() => _WebViewState();
}
class _WebViewState extends State<WebView> {
final Completer<WebViewController> _controller =
Completer<WebViewController>();
num _stackToView = 1;
void _handleLoad(String value) {
setState(() {
_stackToView = 0;
});
}
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
leading: Builder(builder: (BuildContext context) {
return IconButton(
icon: Icon(Icons.volume_up, color: Colors.black,),
onPressed: () {
Navigator.pop(context);
},
);
}),
backgroundColor: Colors.white10,
elevation: 0,
),
body: IndexedStack(
index: _stackToView,
children: [
Column(
children: <Widget>[
Expanded(
child: WebView(
initialUrl: "https://www.google.co.in/",
javascriptMode: JavascriptMode.unrestricted,
onPageFinished: _handleLoad,
onWebViewCreated: (WebViewController webViewController) {
_controller.complete(webViewController);
},
)),
],
),
Container(
child: Center(child: CircularProgressIndicator(),)
),
],
));
}
}