Reputation: 21
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:
본인인증
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();
}
The pass app looks like this
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
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