skip to Main Content

I need to open http sites in a webview in my flutter app but it’s not working in adnroid. For IOS, I added keys in info.plist files but I can’t find a solution for android. Is there any way to allow to open sites that are not secured?

I am using the package webview_flutter

I tried to add the following xml file to allow unsecure sites and providing it’s path to AndroidManifest file but it didn’t work.

android/app/src/main/res/xml/network_security_config.xml
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
    <base-config cleartextTrafficPermitted="true">
        <trust-anchors>
            <!-- You can add trusted certificates here if needed -->
        </trust-anchors>
    </base-config>
</network-security-config>

This is my manifest file:

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.webview_demo">

<uses-permission android:name="android.permission.INTERNET" />
<application
    android:name="${applicationName}"
    android:icon="@mipmap/ic_launcher"
    android:label="webview_demo"
    android:networkSecurityConfig="@xml/network_security_config"
    android:usesCleartextTraffic="true">
    <activity
        android:name=".MainActivity"
        android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
        android:exported="true"
        android:hardwareAccelerated="true"
        android:launchMode="singleTop"
        android:theme="@style/LaunchTheme"
        android:windowSoftInputMode="adjustResize">
        <!-- Specifies an Android theme to apply to this Activity as soon as
             the Android process has started. This theme is visible to the user
             while the Flutter UI initializes. After that, this theme continues
             to determine the Window background behind the Flutter UI. -->
        <meta-data
            android:name="io.flutter.embedding.android.NormalTheme"
            android:resource="@style/NormalTheme" />
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <!-- Don't delete the meta-data below.
         This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
    <meta-data
        android:name="flutterEmbedding"
        android:value="2" />
</application>

My webview code:

import 'dart:developer';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';

class WebviewScreen extends StatefulWidget {
  final String url;

  const WebviewScreen({Key? key, required this.url}) : super(key: key);

  @override
  State<WebviewScreen> createState() => _WebviewScreenState();
}

class _WebviewScreenState extends State<WebviewScreen> {
  WebViewController? webViewController;

  @override
  void initState() {
    super.initState();
    loadWebView();
  }

  loadWebView() {
    webViewController = WebViewController()
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(Colors.white)
      ..setNavigationDelegate(
        NavigationDelegate(
          onPageStarted: (String url) {
            log('Page started loading: $url');
          },
          onProgress: (int progress) {
            log('WebView is loading (progress : $progress%)');
          },
          onPageFinished: (String url) {
            log('Page finished loading: $url');
          },
          onWebResourceError: (WebResourceError error) {
            log('Webview resource error $error');
          },
          onNavigationRequest: (NavigationRequest request) {
            if (request.url.contains("http:/")) {
              log("first redirection ${request.url}");
              return NavigationDecision.navigate;
            }
            return NavigationDecision.navigate;
          },
        ),
      )
      ..loadRequest(
        Uri.parse(widget.url),
      );
  }

  @override
  Widget build(BuildContext context) {
    return WillPopScope(
        onWillPop: () async {
          return true;
        },
        child: Scaffold(
          appBar: AppBar(
            leading: const BackButton(),
            title: const Text('Webview'),
            centerTitle: true,
          ),
          body: SafeArea(
            bottom: false,
            child: Column(
              children: [
                Expanded(
                  child: WebViewWidget(
                    controller: webViewController!,
                  ),
                )
              ],
            ),
          ),
        ));
  }
}

enter code here

2

Answers


  1. Android

    Add a piece of code in label application on AndroidManifst.xml file

    android:networkSecurityConfig="@xml/network_security_config"
    android:usesCleartextTraffic="true"
    

    Add a file named network_security_config.xml in res/xml directory, The content of the file is

    <?xml version="1.0" encoding="utf-8"?>
    <network-security-config>
        <base-config cleartextTrafficPermitted="true" />
    </network-security-config>
    

    iOS

    Add a piece of code in label dict on Info.plist file

    <key>NSAppTransportSecurity</key>  
    <dict>  
        <key>NSAllowsArbitraryLoads</key><true/>  
    </dict>
    
    Login or Signup to reply.
  2. This is probably the best / easiest way to create an WebView with Flutter.

    import the package webview_flutter to your project

    import 'package:webview_flutter/webview_flutter.dart';
    

    Create a class for the webview:

    import 'package:flutter/material.dart';
    import 'package:webview_flutter/webview_flutter.dart';
    
    class WebViewContainer extends StatefulWidget {
      final String websiteURL;
      WebViewContainer({super.key, required this.websiteURL});
    
      @override
      State<StatefulWidget> createState() => _WebViewContainerState();
    }
    
    class _WebViewContainerState extends State<WebViewContainer> {
      final controller = WebViewController();
    
      @override
      Widget build(BuildContext context) {
        controller
          ..setJavaScriptMode(JavaScriptMode.unrestricted)
          ..loadRequest(Uri.parse(widget.websiteURL));
    
        return Scaffold(
          appBar: AppBar(title: Text("My Web View")),
          body: WebViewWidget(controller: controller),
        );
      }
    }
    

    Then call it whenever you want from your code

     Navigator.push(context,
         MaterialPageRoute(builder: (context) =>
             WebViewContainer(
                websiteURL:"https://stackoverflow.com")
     ));
    

    Don’t forget to set minSdkVersion in your android/app/build.gradle if your version was previously was under 19.

    android {
        defaultConfig {
            minSdkVersion 19
        }
    }
    

    After all these is configured, you should open any HTTPS website.
    However, for HTTP sites there are some extra steps.
    You can read about them in this StackOverflow post.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search