반응형
Overview
이번 포스팅에서는...
- 웹 페이지에서 앱에 데이터를 보내고,
- 앱에서 웹 페이지에 데이터를 보내는
방법을 설명합니다.
웹 뷰의 기본 사용 방법은 아래의 포스팅을 확인해주세요.
기본 웹뷰 소스 코드
해당 포스팅에서 사용할 기본 웹뷰만 구현한 소스 코드입니다.
이 소스 코드를 이용하여 웹 페이지와 앱간의 데이터를 교환하는 방법을 설명합니다.
- 기본 웹뷰를 실행한 화면
- 기본 소스 코드
더보기
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
// Import for Android features.
import 'package:webview_flutter_android/webview_flutter_android.dart';
// Import for iOS features.
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
void main() => runApp(const MaterialApp(home: MyWebView()));
class MyWebView extends StatefulWidget {
const MyWebView({super.key});
@override
State<MyWebView> createState() => _MyWebViewState();
}
class _MyWebViewState extends State<MyWebView> {
late WebViewController _controller;
@override
initState() {
super.initState();
// 플랫폼별 웹 뷰 컨트롤러 생성에 필요한 매개변수
late final PlatformWebViewControllerCreationParams params;
// 디바이스가 iOS일 경우
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
params = WebKitWebViewControllerCreationParams(
allowsInlineMediaPlayback: true,
mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
);
}
// 디바이스가 Android일 경우
else if (WebViewPlatform.instance is AndroidWebViewPlatform) {
params = const PlatformWebViewControllerCreationParams();
}
// 플랫폼에 맞는 컨트롤러 생성
final WebViewController controller =
WebViewController.fromPlatformCreationParams(params);
if (controller.platform is AndroidWebViewController) {
AndroidWebViewController.enableDebugging(true);
(controller.platform as AndroidWebViewController)
.setMediaPlaybackRequiresUserGesture(false);
}
// 컨트롤러 설정
controller
// 웹뷰에서 자바스크립트 코드 실행 여부 : 제한없이 사용
..setJavaScriptMode(JavaScriptMode.unrestricted)
// 웹 뷰 배경색 설정 : 투명 배경
..setBackgroundColor(const Color(0x00000000))
// 웹 뷰 이벤트 및 요청을 처리할 대리자 설정
..setNavigationDelegate(
NavigationDelegate(
// 페이지 로딩 진행률 표시
onProgress: (int progress) {
//print('Update loading bar : $progress');
},
// 새 페이지가 로드 될 때 실행되는 코드
onPageStarted: (String url) {
//print('onPageStarted : $url');
},
// 페이지 로드가 완료 될 때 실행되는 코드
onPageFinished: (String url) {
//print('onPageFinished : $url');
},
// 웹 리소스 로드 오류 시 실행 되는 코드
onWebResourceError: (WebResourceError error) {
//print('WebResourceError : $error');
},
),
)
// 보여줄 페이지 URL
..loadRequest(Uri.parse('https://luvris2.tistory.com/'));
_controller = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('WebView Example'),
),
body: WebViewWidget(
controller: _controller,
),
);
}
}
페이지를 보여줄 HTML 파일 정의
앱 자체에 HTML 파일을 넣어 해당 파일을 불러오는 구조로 합니다.
- 프로젝트 디렉토리에 'assets' 폴더 생성
- 생성된 폴더에 html 파일 생성 (포스팅에서는 testpage.html)
디자인
- Web To App
- 버튼을 누를 경우 : 왼쪽 텍스트의 내용을 앱으로 전달
- App To Web
- 앱에서 플로팅 액션 버튼을 누를 경우 : 내용을 웹 페이지로 전달하여 텍스트 필드에 입력
HTML 전체 소스 코드
- ChannelName.postMessage
- ChannelName : 앱에서 추가한 자바스크립트 채널 이름을 의미, 웹은 채널 이름으로 앱에 접근
- postMessage : 앱에 메시지 전달
- 그 외는 기본적인 자바스크립트 소스 코드입니다.
<!DOCTYPE html>
<html lang="ko">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
<script>
// 웹에서 앱으로 데이터를 전달하는 함수
// 앱에서 자바스크립트 채널 이름(Print)을 사용하여 앱으로 데이터를 전달한다.
function webToApp() {
var obj = document.getElementById("web2app");
var data = obj.value;
// 앱의 자바스크립트 채널명을 이용하여 데이터 전달
Print.postMessage(data);
}
// 앱에서 웹으로 데이터를 전달하는 함수
// 앱에서 이 함수를 실행하여 데이터를 전달한다.
function appToWeb(data) {
var obj = document.getElementById("app2web");
obj.value = data;
}
</script>
</head>
<body>
<div style="font-size: 15px;">
<h1> Web To App </h1>
웹에서 앱에게 데이터 보내기<br>
<input id="web2app" value="WebData">
<input id="btn" type="button" value="앱에 데이터 전달" onclick=webToApp()>
<hr>
<h2> App To Web</h2>
앱에서 웹에게 데이터 보내기<br>
<input id="app2web">
</div>
</body>
</html>
앱 내의 HTML 파일 설정
프로젝트 내에서 HTML 파일이 있다는 것을 명시해줘야합니다.
위에서 만든 'assets/파일이름' 을 pubspec.yaml 파일에 추가해줍니다.
- pubspec.yaml 파일 열기
- 'flutter:' 하단에 아래의 코드를 작성해줍니다. 반드시 들여쓰기 규칙을 지켜야합니다.
flutter:
assets:
- assets/
웹 뷰 코드
앱 내부의 HTML파일로 웹 페이지 표시하기
위에서 제공한 기본 웹뷰 코드에서 loadRequest 메서드를 loadFlutterAsset 메서드로 변경합니다.
컨트롤러가 내부의 HTML 파일을 표시하도록 설정하는 메서드입니다.
- 기존 : loadRequest > 변경 : loadFlutterAsset('경로')
// 컨트롤러 설정
controller
/* 코드 생략 */
// 보여줄 페이지 URL
//..loadRequest(Uri.parse('https://luvris2.tistory.com/'));
..loadFlutterAsset('assets/testpage.html');
_controller = controller;
}
웹에서 앱으로 데이터 받기
데이터를 받으면 출력될 다이얼로그를 정의합니다.
- 디자인
- 다이얼로그 정의 코드
- _showDialog 라는 함수로 정의
void _showDialog(BuildContext context, String data) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('웹으로부터 받은 데이터'),
content: Text(data), // 웹으로 받은 데이터를 저장하는 변수 : data
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // 다이얼로그 닫기
},
child: const Text('Close'),
),
],
);
},
);
자바스크립트 채널을 추가하여 웹에서 접근할 수 있도록 설정합니다.
- 자바스크립트 채널 추가 설정 코드
- 웹에서 보낸 데이터는 message.message로 확인 가능
// 컨트롤러 설정
controller
// 자바스크립트 채널 추가 : Print
..addJavaScriptChannel('Print',
onMessageReceived: (JavaScriptMessage message) {
// 웹에서 보낸 데이터를 콘솔에 출력
print(
'########## onMessageReceived ########## ===>>> ${message.message}');
setState(() {
// 다이얼로그에 웹에서 보낸 데이터를 보여주기
_showDialog(context, message.message);
});
})
/* 코드 생략 */
// 보여줄 페이지 URL
..loadFlutterAsset('assets/testpage.html');
_controller = controller;
}
앱에서 웹으로 데이터 보내기
HTML 파일에서 정의한 appToWeb 함수를 이용하여 데이터를 전달합니다.
예제에서는 플로팅 액션 버튼을 클릭하면 미리 정의해둔 메시지를 웹으로 전달하게끔 구현하였습니다.
- 자바스크립트 appToWeb 함수 코드
<!-- HTML 파일 내용 중 앱에서 웹으로 데이터를 전달하는 함수 -->
function appToWeb(data) {
var obj = document.getElementById("app2web");
obj.value = data;
}
- 플로팅 액션 버튼 정의 코드
- 컨트롤러의 runJavaScript 메서드를 이용하여 웹으로 메시지 전달
- 전달 내용 : 앱에서 보낸 메시지
floatingActionButton: FloatingActionButton(
// 버튼 클릭 시 웹에서 정의한 함수(appToWeb) 실행
onPressed: () {
_controller.runJavaScript("appToWeb('앱에서 보낸 메시지')");
},
),
웹뷰 전체 소스 코드
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
// Import for Android features.
import 'package:webview_flutter_android/webview_flutter_android.dart';
// Import for iOS features.
import 'package:webview_flutter_wkwebview/webview_flutter_wkwebview.dart';
void main() => runApp(const MaterialApp(home: MyWebView()));
class MyWebView extends StatefulWidget {
const MyWebView({super.key});
@override
State<MyWebView> createState() => _MyWebViewState();
}
class _MyWebViewState extends State<MyWebView> {
late WebViewController _controller;
@override
initState() {
super.initState();
// 플랫폼별 웹 뷰 컨트롤러 생성에 필요한 매개변수
late final PlatformWebViewControllerCreationParams params;
// 디바이스가 iOS일 경우
if (WebViewPlatform.instance is WebKitWebViewPlatform) {
params = WebKitWebViewControllerCreationParams(
allowsInlineMediaPlayback: true,
mediaTypesRequiringUserAction: const <PlaybackMediaTypes>{},
);
}
// 디바이스가 Android일 경우
else if (WebViewPlatform.instance is AndroidWebViewPlatform) {
params = const PlatformWebViewControllerCreationParams();
}
// 플랫폼에 맞는 컨트롤러 생성
final WebViewController controller =
WebViewController.fromPlatformCreationParams(params);
if (controller.platform is AndroidWebViewController) {
AndroidWebViewController.enableDebugging(true);
(controller.platform as AndroidWebViewController)
.setMediaPlaybackRequiresUserGesture(false);
}
// 컨트롤러 설정
controller
// 웹뷰에서 자바스크립트 코드 실행 여부 : 제한없이 사용
..setJavaScriptMode(JavaScriptMode.unrestricted)
// 웹 뷰 배경색 설정 : 투명 배경
..setBackgroundColor(const Color(0x00000000))
..addJavaScriptChannel('Print',
onMessageReceived: (JavaScriptMessage message) {
print(
'########## onMessageReceived ########## ===>>> ${message.message}');
setState(() {
_showDialog(context, message.message);
});
})
// 웹 뷰 이벤트 및 요청을 처리할 대리자 설정
..setNavigationDelegate(
NavigationDelegate(
// 페이지 로딩 진행률 표시
onProgress: (int progress) {
//print('Update loading bar : $progress');
},
// 새 페이지가 로드 될 때 실행되는 코드
onPageStarted: (String url) {
//print('onPageStarted : $url');
},
// 페이지 로드가 완료 될 때 실행되는 코드
onPageFinished: (String url) {
//print('onPageFinished : $url');
},
// 웹 리소스 로드 오류 시 실행 되는 코드
onWebResourceError: (WebResourceError error) {
//print('WebResourceError : $error');
},
),
)
// 보여줄 페이지 URL
//..loadRequest(Uri.parse('https://luvris2.tistory.com/'));
..loadFlutterAsset('assets/testpage.html');
_controller = controller;
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: const Text('WebView Example'),
),
body: WebViewWidget(
controller: _controller,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
_controller.runJavaScript("appToWeb('앱에서 보낸 메시지')");
},
),
);
}
void _showDialog(BuildContext context, String data) {
showDialog(
context: context,
builder: (BuildContext context) {
return AlertDialog(
title: const Text('웹으로부터 받은 데이터'),
content: Text(data),
actions: [
TextButton(
onPressed: () {
Navigator.of(context).pop(); // 다이얼로그 닫기
},
child: const Text('Close'),
),
],
);
},
);
}
}
반응형