Taehun Ku
Taehun Ku

Reputation: 21

How can I open new window in flutter inappwebview package?

I am a junior Flutter app programmer! I have a unsolved issue about Flutter inappwebview's open new tab problem. If you know the solution, please share this to me..

Problem:

I want to open phone certification in InAppBroswer. When I operate ‘PASS App’(Phone Certificate Service) , the HTML code’s specific function will be operated.(this function call window.open in HTML) on a new tab page. but, there is a blank page without any information.

Question:

How can I make a new tab on webApp page? I already check the solution that is about making new alert dialog to be a new tab. But I don’t understand why the 'openDRMOKWindow'(it's HTML code) is not working in the webappview. Please read the HTML code… and if you know the solution to open Phone certificate page on a new page, let me know the solution.

Info:

  1. If you press one of blue buttons, the Pass (phone certificate app) will be started

enter image description here

  1. The HTML code of the blue button is

본인인증

  1. openDRMOKWindow function is

    function openDRMOKWindow(type, coworker, service, a_type, kitid, client_key, machine){ window.name = "parentPage"; DRMOK_window = window.open('', 'DRMOKWindow', 'width=425, height=550, resizable=0, scrollbars=no, status=0, titlebar=0, toolbar=0, left=435, top=250' );

         $.ajax({
           url: '/agreements/ctrl/index_session_create.php',
           method : "post",
           dataType : "text",
           data : {
             type : type,
             coworker : coworker,
             service : service,
             a_type : a_type,
             kitid : kitid,
             client_key : client_key,
             machine : machine
           }
         });
    
         document.form1.action = 'https://www.mobile-ok.com/popup/common/hscert.jsp';
         document.form1.target = 'DRMOKWindow';
         document.form1.submit();
       }
    
  2. The pass app looks like this

enter image description here

Package version: flutter_inappwebview: ^5.3.2

Flutter doctor:

Flutter (Channel stable, 2.8.1, on macOS 12.0.1 21A559 darwin-x64, locale ko-KR) • Flutter version 2.8.1 at /Users/taehunku/Downloads/flutter2.2.3 • Upstream repository https://github.com/flutter/flutter.git • Framework revision 77d935af4d (9주 전), 2021-12-16 08:37:33 -0800 • Engine revision 890a5fca2e • Dart version 2.15.1

[✓] Android toolchain - develop for Android devices (Android SDK version 31.0.0) • Android SDK at /Users/taehunku/Library/Android/sdk • Platform android-32, build-tools 31.0.0 • Java binary at: /Applications/Android Studio.app/Contents/jre/Contents/Home/bin/java • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165) • All Android licenses accepted.

[✓] Xcode - develop for iOS and macOS (Xcode 13.2.1) • Xcode at /Users/taehunku/Downloads/Xcode.app/Contents/Developer • CocoaPods version 1.11.2

[✓] Chrome - develop for the web • Chrome at /Applications/Google Chrome.app/Contents/MacOS/Google Chrome

[✓] Android Studio (version 2020.3) • Android Studio at /Applications/Android Studio.app/Contents • Flutter plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: 🔨 https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 11.0.10+0-b96-7281165)

[✓] VS Code (version 1.60.0) • VS Code at /Users/taehunku/Downloads/Visual Studio Code.app/Contents • Flutter extension version 3.27.0

[✓] Connected device (1 available) • Chrome (web) • chrome • web-javascript • Google Chrome 98.0.4758.80

Full HTML Code:

<html><head>
        <title>개인정보 수집·이용 동의서</title>
        <meta name="viewport" content="width=device-width, initial-scale=1, minimum-scale=1, maximum-scale=1, user-scalable=no">
        <meta name="apple-mobile-web-app-capable" content="yes">
        <meta name="apple-mobile-web-app-status-bar-style" content="black">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css">
        <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap-theme.min.css">
        <script type="text/javascript" src="//code.jquery.com/jquery-3.5.1.min.js"></script>
        <script src="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/js/bootstrap.min.js"></script>
        <link rel="stylesheet" type="text/css" href="../../css/common.css?ver=3947">
        <script type="text/javascript" src="../../js/sweetalert.min.js?ver=6"></script>
    </head>

    
    <body>
        <nav>
          <img src="../../img/index_logo_macrogen.png" class="index-title-image bestf">
        </nav>
        <form name="form1" method="post">
          <article class="article-index">

            <input type="hidden" name="req_info" value="NS0gn4muoWpx/+mOF6iF4oMWKvd9RjnIPUw7yhb20IcLrt782Bz+vB65Fa8AB1JoCJqgds7jyu5z+7dex4hbr5MNTZ4kvkgxn0b0W5k6o5BYMxTh/cAVZ5DzTE98RlTXmTvEuDQ5oSL7sMmKaC4DKEpHWJbs8rikVeLrB0L1tmRKxaczJK7H2Wjws364okzXL+xqR2h4K/AuFf8Qe2Pr03F4XnarjCkeKG0A76Zl9pSMtCls4E/gfiUhoUO6zCpa/Ehz+EhemqsVnESAN/dS/iy/uXiHLVPhDSNhANO+RQaF+OGyv+9eQ/iSirkydjjo9BPDE+0pdBVyYkH4/bBVqQ==">
            <input type="hidden" name="rtn_url" value="https://www.my-genomestory.com/user/agreement_cert_result.php">
            <input type="hidden" name="cpid" value="macrogenmy">

            <img class="image-coworker mx-auto" src="../../img/logo_macrogen.png"><br>
            <p class="font-size-big font-weight-bold text-center text-0">유전자 검사 동의서</p>
            <p class="font-size-small text-center text-1">본인(보호자) 인증 후<br>유전자 검사 신청이 가능합니다.</p>
              <button type="button" onclick="openDRMOKWindow(this.name, 'bestf', 'genome', 'common', '', 'testcode3', 'app')" name="adult" class="button-blue-big color-white font-weight-bold font-size-normal-more mx-auto button-0">본인인증</button>
                              <button type="button" onclick="openDRMOKWindow(this.name, 'bestf', 'genome', 'common', '', 'testcode3', 'app')" name="minor" class="button-blue-big color-white font-weight-bold font-size-normal-more mx-auto button-1 genome">
                  보호자 본인인증<br>
                  <i>(만 19세 미만)</i>
                </button>
              
                            <a href="/agreements/about_DTC?coworker=bestf" class="color-blue font-size-small font-weight-bold text-center mx-auto text-2">DTC 유전자 검사 소개</a>
              <a href="/agreements/download_pdf_guide" class="download_pdf_guide">📋 제출한 동의서 pdf 파일 다운로드 가이드</a>
              
              
              <p class="text-center text-box">
                <span class="title">[ 안 내 ]</span><span class="content-1">유전자 검사 동의서는 서비스 진행을 위해<br>필수적으로 제출해야 합니다.</span><span class="content-2">최초 제출 후 5일 이내에는 재작성이 가능합니다.</span>              </p>

            </article>
            
  <footer>
    <p class="font-size-mini font-weight-bold">(주) 마크로젠</p>
    <p class="font-size-mini">주소: 서울특별시 금천구 벚꽃로 254 10층(가산동, 월드메르디앙 1차)<br>
      <a href="tel:+82221807220" onclick="gtag('event','index_footer_전화연결_ko')">02-2180-7220</a> |
      <a href="mailto:[email protected]" onclick="gtag('event','index_footer_메일보내기_ko')">[email protected]</a><br>
        카카오톡 ID: <a class="kakao_id" href="http://pf.kakao.com/_xlTEQxl" onclick="gtag(\'event\',\'footer_카카오플러스친구_클릭_ko\')" target="_blank">마이지놈스토리</a></p>
    <p class="font-size-mini font-weight-bold">개인정보처리방침</p>
    <p class="font-size-mini">대표: 이수강 | 사업자등록번호: 208-81-24115</p>
    <p class="font-size-mini color-blue">COPYRIGHT © Macrogen, Inc. ALL RIGHTS RESERVED.</p>
  </footer>

        </form>
    

    <script language="javascript">

      $(document).ready(function(){
        if('1' == 1 && 'genome' == 'genome'){
          swal({
            icon: 'warning',
            text: "검사 대상자가 19세 이상일 경우 ‘본인인증’을,\n19세 미만일 경우 ‘보호자 본인인증’을 눌러\n유전자 검사 동의서 작성 및 신청을 진행해 주세요."
          })
        }
      })

      function openDRMOKWindow(type, coworker, service, a_type, kitid, client_key, machine){
        window.name = "parentPage";
        DRMOK_window = window.open('', 'DRMOKWindow', 'width=425, height=550, resizable=0, scrollbars=no, status=0, titlebar=0, toolbar=0, left=435, top=250' );

        $.ajax({
          url: '/agreements/ctrl/index_session_create.php',
          method : "post",
          dataType : "text",
          data : {
            type : type,
            coworker : coworker,
            service : service,
            a_type : a_type,
            kitid : kitid,
            client_key : client_key,
            machine : machine
          }
        });

        document.form1.action = 'https://www.mobile-ok.com/popup/common/hscert.jsp';
        document.form1.target = 'DRMOKWindow';
        document.form1.submit();
      }

    </script>


<div class="swal-overlay" tabindex="-1">
  <div class="swal-modal" role="dialog" aria-modal="true"><div class="swal-icon swal-icon--warning">
    <span class="swal-icon--warning__body">
      <span class="swal-icon--warning__dot"></span>
    </span>
  </div><div class="swal-text" style="">검사 대상자가 19세 이상일 경우 ‘본인인증’을,<br>19세 미만일 경우 ‘보호자 본인인증’을 눌러<br>유전자 검사 동의서 작성 및 신청을 진행해 주세요.</div><div class="swal-footer"><div class="swal-button-container">

    <button class="swal-button swal-button--confirm">OK</button>

    <div class="swal-button__loader">
      <div></div>
      <div></div>
      <div></div>
    </div>

  </div></div></div></div></body></html>

Dart Code:

import 'dart:async';
import 'dart:collection';
import 'dart:convert';
import 'dart:io';
import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
import 'package:url_launcher/url_launcher.dart';

Future main() async {
  WidgetsFlutterBinding.ensureInitialized();

  if (Platform.isAndroid) {
    await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
  }

  runApp( const MyApp());
}

class MyApp extends StatefulWidget {
  const MyApp({Key? key}) : super(key: key);

  @override
  _MyAppState createState() => new _MyAppState();
}

class _MyAppState extends State<MyApp> {

  final GlobalKey webViewKey = GlobalKey();

  InAppWebViewController? webViewController;


    InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
      crossPlatform: InAppWebViewOptions(

        javaScriptCanOpenWindowsAutomatically: true,
        javaScriptEnabled: true,
        useOnDownloadStart: true,
        useOnLoadResource: true,
        cacheEnabled: true,
        preferredContentMode: UserPreferredContentMode.MOBILE,
        useShouldInterceptAjaxRequest: true,
        useShouldOverrideUrlLoading: true,
        mediaPlaybackRequiresUserGesture: true,
        allowFileAccessFromFileURLs: true,
        allowUniversalAccessFromFileURLs: true
      ),
      android: AndroidInAppWebViewOptions(
        useHybridComposition: true,
      ),
      ios: IOSInAppWebViewOptions(
        allowsAirPlayForMediaPlayback: true,
        suppressesIncrementalRendering: true,
        ignoresViewportScaleLimits: true,
        selectionGranularity: IOSWKSelectionGranularity.DYNAMIC,
        isPagingEnabled: true,

        enableViewportScale: true,
        sharedCookiesEnabled: true,
        automaticallyAdjustsScrollIndicatorInsets: true,
        useOnNavigationResponse: true,

        allowsInlineMediaPlayback: true,
      ));

  late PullToRefreshController pullToRefreshController;
  String url = "";
  double progress = 0;
  final urlController = TextEditingController();

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

    pullToRefreshController = PullToRefreshController(
      options: PullToRefreshOptions(
        color: Colors.blue,
      ),
      onRefresh: () async {
        if (Platform.isAndroid) {
          webViewController?.reload();
        } else if (Platform.isIOS) {
          webViewController?.loadUrl(
              urlRequest: URLRequest(url: await webViewController?.getUrl()));
        }
      },
    );
  }

  @override
  void dispose() {
    super.dispose();
  }

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
          appBar: AppBar(title: Text("Official InAppWebView website")),
          body: SafeArea(
              child: Column(children: <Widget>[
                TextField(
                  decoration: InputDecoration(
                      prefixIcon: Icon(Icons.search)
                  ),
                  controller: urlController,
                  keyboardType: TextInputType.url,
                  onSubmitted: (value) {
                    var url = Uri.parse(value);
                    if (url.scheme.isEmpty) {
                      url = Uri.parse("https://www.google.com/search?q=" + value);
                    }
                    webViewController?.loadUrl(
                        urlRequest: URLRequest(url: url));
                  },
                ),
                Expanded(
                  child: Stack(
                    children: [
                      InAppWebView(
                        key: webViewKey,
                        initialUrlRequest:
                        URLRequest(url: Uri.parse("https://www.my-genomestory.com/agreements/index/bestf/?service=genome&clientKey=abcd12345&machine=app")),
                        initialOptions: options,
                        pullToRefreshController: pullToRefreshController,
                        onWebViewCreated: (controller) {
                          webViewController = controller;
                        },
                      onCreateWindow: (InAppWebViewController,createWindowRequest)async{
                   
                          InAppWebViewController.addJavaScriptHandler(handlerName: 'openDRMOKWindow', callback: (args){
                            print(args);
                          });
                        showDialog(
                          context: context,
                          builder: (context) {
                            return AlertDialog(
                              content: Container(
                                width: MediaQuery.of(context).size.width,
                                height: 400,
                                child: InAppWebView(
                                  // Setting the windowId property is important here!
                                  windowId: createWindowRequest.windowId,
                                  initialUrlRequest:
                                  URLRequest(url: Uri.parse("https://www.mobile-ok.com/popup/common/hscert.jsp")),
                                  initialOptions: InAppWebViewGroupOptions(
                                    crossPlatform: InAppWebViewOptions(

                                    ),
                                  ),
                                  onWebViewCreated: ( controller) {

                                  },

                                ),
                              ),
                            );
                          },
                        );
                      },

                        onLoadStart: (controller, url) {
                          setState(() {
                            this.url = url.toString();
                            urlController.text = this.url;
                          });
                        },
                        androidOnPermissionRequest: (controller, origin, resources) async {
                          return PermissionRequestResponse(
                              resources: resources,
                              action: PermissionRequestResponseAction.GRANT);
                        },
                        shouldOverrideUrlLoading: (controller, navigationAction) async {
                          var uri = navigationAction.request.url!;

                          if (![ "http", "https", "file", "chrome",
                            "data", "javascript", "about"].contains(uri.scheme)) {
                            if (await canLaunch(url)) {
                              // Launch the App
                              await launch(
                                url,
                              );
                              // and cancel the request
                              return NavigationActionPolicy.CANCEL;
                            }
                          }

                          return NavigationActionPolicy.ALLOW;
                        },
                        onLoadStop: (controller, url) async {
                          pullToRefreshController.endRefreshing();
                          setState(() {
                            this.url = url.toString();
                            urlController.text = this.url;
                          });
                        },
                        onLoadError: (controller, url, code, message) {
                          pullToRefreshController.endRefreshing();
                        },
                        onProgressChanged: (controller, progress) {
                          if (progress == 100) {
                            pullToRefreshController.endRefreshing();
                          }
                          setState(() {
                            this.progress = progress / 100;
                            urlController.text = this.url;
                          });
                        },
                        onUpdateVisitedHistory: (controller, url, androidIsReload) {
                          setState(() {
                            this.url = url.toString();
                            urlController.text = this.url;
                          });
                        },
                        onConsoleMessage: (controller, consoleMessage) {
                          print(consoleMessage);
                        },
                      ),
                      progress < 1.0
                          ? LinearProgressIndicator(value: progress)
                          : Container(),
                    ],
                  ),
                ),
                ButtonBar(
                  alignment: MainAxisAlignment.center,
                  children: <Widget>[
                    ElevatedButton(
                      child: Icon(Icons.arrow_back),
                      onPressed: () {
                        webViewController?.goBack();
                      },
                    ),
                    ElevatedButton(
                      child: Icon(Icons.arrow_forward),
                      onPressed: () {
                        webViewController?.goForward();
                      },
                    ),
                    ElevatedButton(
                      child: Icon(Icons.refresh),
                      onPressed: () {
                        webViewController?.reload();
                      },
                    ),
                  ],
                ),
              ]))),
    );
  }
}

Upvotes: 1

Views: 7265

Answers (1)

Omatt
Omatt

Reputation: 10473

You should use the InAppWebView shouldOverrideUrlLoading property. This allows the WebView to open the url in a browser.

shouldOverrideUrlLoading: (controller, shouldOverrideUrlLoadingRequest) async {
  var url = shouldOverrideUrlLoadingRequest.url;
  var uri = Uri.parse(url);

  if ((uri.toString()).contains('YOUR_URL')) {
    return NavigationActionPolicy.ALLOW;
  } else {
    launchURL(uri.toString());
    return NavigationActionPolicy.CANCEL;
  }
}

Upvotes: 2

Related Questions