import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:loading_indicator/loading_indicator.dart';
import '../../widgets/constants.dart';
import '../../env.dart';
import '../../localization/app_localizations.dart';
import '../../widgets/api_services.dart';
import '../../widgets/size_config.dart';
class WeddingPlansScreen extends StatefulWidget {
@override
_WeddingPlansScreenState createState() => _WeddingPlansScreenState();
}
class _WeddingPlansScreenState extends State<WeddingPlansScreen> {
late InAppWebViewController _webViewController;
bool isLoading = true;
@override
void initState() {
super.initState();
}
@override
Widget build(BuildContext context) {
SizeConfig().init(context);
return WillPopScope(
onWillPop: () async {
if (await _webViewController.canGoBack()) {
// Navigate back within the WebView
_webViewController.goBack();
return false; // Prevent closing the WebView
}
return true; // Close the WebView screen
},
child: Scaffold(
appBar: AppBar(
automaticallyImplyLeading: false,
leading: IconButton(
icon: Icon(
Icons.arrow_back_ios_new_outlined,
color: Environment.appTheme,
size: Constants.space25,
),
onPressed: () {
Navigator.pop(context);
},
),
backgroundColor: Constants.whiteColor,
title: Text("Wedding Packages"),
),
body: Stack(
children: [
InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri.uri(Uri.parse('${Environment.testUrl}')),
),
onLoadStart: (controller, url) {
setState(() {
isLoading = true;
});
},
onLoadStop: (controller, url) async {
setState(() {
isLoading = false;
});
},
onWebViewCreated: (controller) {
_webViewController = controller;
},
),
if (isLoading)
Center(
child: Container(
height: Constants.height35,
width: Constants.height35,
child: LoadingIndicator(
strokeWidth: 3.0,
indicatorType: Indicator.lineSpinFadeLoader,
colors: [Constants.darkGreyColor.withOpacity(0.6), Constants.darkGreyColor.withOpacity(0.6),],
),
)
),
],
),
),
);
}
}
I am currently working on a WebView screen in my Flutter application. However, I am encountering an issue where PDF files are not opening correctly within the WebView. When I attempt to open a PDF, I receive the following error message in the console.
how to Fix this issue and open the pdf file or download file.
I/chromium(17997): [INFO:CONSOLE:1] "[object HTMLAnchorElement]", source: https://testurl.com/_next/static/chunks/pages/%5B%5B...slug%5D%5D-f8d06f337de73a8f.js (1)
I/chromium(17997): [INFO:CONSOLE:1] "end", source: https://testurl.com/_next/static/chunks/pages/%5B%5B...slug%5D%5D-f8d06f337de73a8f.js (1)
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onConsoleMessage" using {messageLevel: 1, message: [object HTMLAnchorElement]}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onConsoleMessage" using {messageLevel: 1, message: end}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onProgressChanged" using {progress: 10}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onProgressChanged" using {progress: 100}
[AndroidInAppWebViewController] (android) WebView ID 0 calling "onProgressChanged" using {progress: 100}
You need to handle file download requests manually, especially for PDFs, because Android WebView doesn’t support PDF rendering natively and may not download files automatically either.
Add Required Permissions to AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
For Android 10+ (API 29+), add this inside application>:
android:requestLegacyExternalStorage="true"
Update Your Widget to Handle PDF Downloads
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:path_provider/path_provider.dart';
import 'package:open_file/open_file.dart';
class WeddingPlansScreen extends StatefulWidget {
@override
_WeddingPlansScreenState createState() => _WeddingPlansScreenState();
}
class _WeddingPlansScreenState extends State<WeddingPlansScreen> {
late InAppWebViewController _webViewController;
bool isLoading = true;
@override
void initState() {
super.initState();
_requestPermissions();
}
Future<void> _requestPermissions() async {
await Permission.storage.request();
}
Future<void> _downloadFile(String url) async {
try {
final response = await HttpClient().getUrl(Uri.parse(url));
final downloadedData = await response.close();
final bytes = await downloadedData.fold<List<int>>(
[],
(buffer, data) => buffer..addAll(data),
);
final dir = await getExternalStorageDirectory();
final filePath = '${dir?.path}/downloaded_file.pdf';
final file = File(filePath);
await file.writeAsBytes(bytes);
OpenFile.open(filePath);
} catch (e) {
print("Error downloading file: $e");
}
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text("Wedding Packages"),
leading: IconButton(
icon: Icon(Icons.arrow_back_ios_new_outlined),
onPressed: () => Navigator.pop(context),
),
),
body: Stack(
children: [
InAppWebView(
initialUrlRequest: URLRequest(
url: WebUri.uri(Uri.parse('${Environment.testUrl}')),
),
onWebViewCreated: (controller) {
_webViewController = controller;
},
onLoadStart: (controller, url) {
setState(() {
isLoading = true;
});
},
onLoadStop: (controller, url) {
setState(() {
isLoading = false;
});
},
onDownloadStartRequest: (controller, request) async {
final url = request.url.toString();
if (url.endsWith(".pdf")) {
await _downloadFile(url);
} else {
print("Download requested for: $url");
}
},
),
if (isLoading)
Center(
child: CircularProgressIndicator(),
),
],
),
);
}
}