[flutter (플루터 앱 개발)]Flutter - InAppWebview Communication (인앱웹뷰로 웹과 앱 양방향 통신하기, 자바스크립트 커뮤니케이션)


 
 

1. Overview

이번 포스팅에서는...

InAppWebview Package를 이용하여 구성된 웹 페이지에서 자바스크립트를 통해

  1. 웹에서 앱으로 데이터를 전달하고 (web -> app)
  2. 앱에서 웹으로 데이터를 전달하고 (웹에서 데이터를 요청하면, app -> web)
  3. 웹과 앱 서로 데이터를 양방향으로 주고 받는 (web <-> app)

방법에 대해서 포스팅합니다.

 

이 포스팅에서는 InAppWebview의 기본 사용 방법은 설명하지 않습니다.
웹 페이지 구성 및 기본 사용 방법에 대한 포스팅은 아래의 포스팅을 참고해주세요.

 

inAppWebview에서 팝업은 기본적으로 보여지지 않기 때문에 따로 구현해야 합니다.
팝업 구현에 대한 포스팅은 아래의 포스팅을 참고해주세요.

 

포스팅에서 설명하는 프로젝트는 아래의 깃허브 주소에서 다운로드 가능합니다.


2. InAppWebview 기본 구성

아래는 포스팅에서 설명할 InAppWebview의 기본 구성이다.

이해가 쉽도록 가능한 main.dart 파일 하나에 구성하였다.

이 구성을 기준으로 양방향 통신 사용 방법과 설명을 진행하도록 한다.

당연하게도 아래의 코드는 빈 깡통 인앱웹뷰 코드이므로 실행하면, 아무것도 나오지 않는다.

 
 
 
import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; Future main() async { // 위젯 바인딩 초기화 : 웹뷰와 플러터 엔진과의 상호작용을 위함 WidgetsFlutterBinding.ensureInitialized(); if (Platform.isAndroid) { await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true); } runApp( const MaterialApp(home: MyApp()), ); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { // 인앱웹뷰 컨트롤러 InAppWebViewController? webViewController; InAppWebViewGroupOptions options = InAppWebViewGroupOptions( // 플랫폼 상관없이 동작하는 옵션 crossPlatform: InAppWebViewOptions( useShouldOverrideUrlLoading: true, // URL 로딩 제어 mediaPlaybackRequiresUserGesture: false, // 미디어 자동 재생 javaScriptEnabled: true, // 자바스크립트 실행 여부 javaScriptCanOpenWindowsAutomatically: true, // 팝업 여부 ), // 안드로이드 옵션 android: AndroidInAppWebViewOptions( useHybridComposition: true, // 하이브리드 사용을 위한 안드로이드 웹뷰 최적화 ), // iOS 옵션 ios: IOSInAppWebViewOptions( allowsInlineMediaPlayback: true, // 웹뷰 내 미디어 재생 허용 )); @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Column( children: <Widget>[ Expanded( child: Stack( children: [ InAppWebView( // 시작 페이지 initialData: InAppWebViewInitialData(data: """ """), // 코드 작성 // 초기 설정 initialOptions: options, // 인앱웹뷰 생성 시 컨트롤러 정의 onWebViewCreated: (controller) { webViewController = controller; }, ), ], ), ), ], ), ), ); } }

3. 웹-앱 통신 방법

 

우선 웹과 앱의 통신 방법에 대해서 집고 넘어가자.

 

1. 앱의 InAppWebview에서 자바스크립트 핸들러를 추가하여 정의한다.

  • 핸들러는 onWebViewCreated 부분에 작성한다.
 
 
 
 
<dart />

InAppWebView( onWebViewCreated: (controller) { /* 웹에서 앱과 통신할 수 있는 핸들러를 정의 * handlerName : 핸들러명 * callback : 웹에서 보낸 데이터 * return : 웹으로 보낼 데이터 */ controller.addJavaScriptHandler( handlerName: '핸들러명', callback: (args) { // 수행 코드 작성 }); }, )

 

2. 웹에서 앱의 해당 자바스크립트 핸들러를 찾아서 호출한다.

 
  • 웹에서 앱의 자바스크립트 핸들러를 찾아 호출 할 때, 파라미터에 값을 넣어 데이터를 전달할 수도 있다.
  • 자바스크립트에서 다른 프레임워크에 접근하기 위해 명시적으로 window 객체를 사용하여 접근한다.
    포스팅에서의 자바스크립트에 대한 자세한 설명은 생략한다.
 
 
 
 
<javascript />

<script> window.addEventListener("flutterInAppWebViewPlatformReady", function(event) { /* 웹에서 앱에게 데이터를 보내고 받는 핸들러 * APP : onWebViewCreated에서 addJavaScriptHandler를 정의 * WEB : window.flutter_inappwebview.callHandler를 사용하여 APP에서 정의한 핸들러 이름 호출 * 두번째 파라미터부터는 앱으로 보낼 데이터들을 나열 * callHandler ( 핸들러이름, 데이터1, 데이터2, ...) */ // 웹에서 앱의 핸들러를 호출하고 데이터 보내기 window.flutter_inappwebview.callHandler('핸들러명', '데이터1', ['배열데이터1', '배열데이터2']); </script>

 

3. 호출된 핸들러를 통해 앱에서 정의된 기능을 수행한다.

 
  • 정의된 기능을 처리하고 return 키워드를 통해 다시 웹으로 처리되거나 혹은 필요한 데이터를 보낼 수 있다.
 
 
 
 
<dart />

controller.addJavaScriptHandler( handlerName: '핸들러명', callback: (args) { // 수행 코드 작성 // return으로 JSON(키[result]와 밸류[ok]) 데이터 리턴 return 'result' : 'ok'; }); },


4. 웹에서 앱으로 데이터 전달하기

 

웹에서 앱으로 데이터를 보내보자.

  • 문자열 데이터 : 'Hello World!'
  • 사람의 정보가 담긴 배열 : ['Eunbyeol Ko', 33]

 

웹 코드

 
 
 
 
<javascript />

window.addEventListener("flutterInAppWebViewPlatformReady", function(event) { // 웹에서 앱으로 데이터 보내기 window.flutter_inappwebview.callHandler('web2app', 'Hello World!', ['Eunbyeol Ko', 33]); });

 

앱 코드

 
 
 
 
<dart />

controller.addJavaScriptHandler( handlerName: 'web2app', callback: (args) { // 수행 코드 작성 : 예시 코드에서는 단순히 print로 받은 데이터를 콘솔에 출력함 print('web2app : recieve data ===> $args'); });

 

앱 코드에서는 웹에서 받은 데이터를 볼 수 있도록 print로 콘솔에 출력하였다.

5. 앱에서 웹으로 데이터 전달하기

 

이번엔 앱에서 웹으로 데이터를 전달해보자.

제약사항이 존재하는데, 웹에서 앱의 핸들러를 호출할 경우 데이터를 전달할 수 있다.

경축! 아무것도 안하여 에스천사게임즈가 새로운 모습으로 재오픈 하였습니다.
어린이용이며, 설치가 필요없는 브라우저 게임입니다.
https://s1004games.com

말장난이긴한데... 결국은 웹에서 호출한 핸들러의 반환 값을 주는 것이다.

  • 앱에서 웹으로 전달할 데이터 : (문자열) 'Hello World!'

 

웹 코드

 
 
 
 
<javascript />

window.addEventListener("flutterInAppWebViewPlatformReady", function(event) { // 앱 데이터 웹으로 받기 window.flutter_inappwebview.callHandler('app2web') .then(function(result) { // 코드 작성 : 예시 코드에서는 앱에서 받은 데이터를 alert로 보여주도록 함 alert(result); }); });

 

앱 코드

 
 
 
 
<dart />

controller.addJavaScriptHandler( handlerName: 'app2web', callback: (args) { return 'Hello World!'; });

 

앱의 핸들러를 호출 후 반환 받은 데이터를 웹 페이지에서 alert를 통해 출력하도록 하였다.

 

6. 웹-앱 양방향 통신하기

위의 두 개의 방법을 다 정의하면된다.

웹에서 앱의 핸들러 호출 시, 두번째 파라미터부터 데이터를 기재하여 앱으로 데이터를 전달하고

앱에서 호출된 핸들러의 기능을 수행 후, 반환 값을 주면된다.

  • 웹에서 보낼 데이터 : 숫자 1
  • 앱에서 처리할 로직 : 숫자가 1이면 'success' 반환, 아니면 'failed' 반환
  • 앱에서 반환할 데이터 : JSON 형식의 데이터

 

웹 코드

 
 
 
 
<javascript />

window.addEventListener("flutterInAppWebViewPlatformReady", function(event) { // 웹과 앱 양방향 통신하기 window.flutter_inappwebview.callHandler('WebAppDataExchange', 1) .then(function(result) { // 코드 작성 : 예시 코드에서는 앱에서 받은 데이터를 alert로 보여주도록 함 // JSON 타입으로 반환하였기 때문에 JSON.stringify를 이용하여 JSON 타입으로 변환 alert(JSON.stringify(result['result'])); }); });

 

앱 코드

 
 
 
 
<dart />

controller.addJavaScriptHandler( handlerName: 'WebAppDataExchange', callback: (args) { // 수행 코드 작성 : 예시 코드에서는 단순히 print로 받은 데이터를 콘솔에 출력함 // Web-App Data Exchange : recieve data print( 'Web-App Data Exchange : recieve data ===> $args'); // 받는 값에 따른 로직 처리 : 예시 코드에서는 값이 1이면 result 성공값 반환 if (args[0] == 1) { return { 'result': 'success' }; // Web-App Data Exchange : send data } else { return {'result': 'failed'}; } });

 

웹에서 보낸 데이터를 앱이 받을 때 : 콘솔에 받은 데이터를 출력하도록 함

 

 

 

앱에서 웹으로 데이터를 반환할 때 : 웹 페이지에서 반환 받은 값을 alert로 출력하도록 함

 

 


7. 전체 소스 코드

 
 
 
 
<dart />

import 'dart:async'; import 'dart:io'; import 'package:flutter/material.dart'; import 'package:flutter_inappwebview/flutter_inappwebview.dart'; Future main() async { // 위젯 바인딩 초기화 : 웹뷰와 플러터 엔진과의 상호작용을 위함 WidgetsFlutterBinding.ensureInitialized(); if (Platform.isAndroid) { await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true); } runApp( const MaterialApp(home: MyApp()), ); } class MyApp extends StatefulWidget { const MyApp({super.key}); @override _MyAppState createState() => _MyAppState(); } class _MyAppState extends State<MyApp> { // 인앱웹뷰 컨트롤러 InAppWebViewController? webViewController; InAppWebViewGroupOptions options = InAppWebViewGroupOptions( // 플랫폼 상관없이 동작하는 옵션 crossPlatform: InAppWebViewOptions( useShouldOverrideUrlLoading: true, // URL 로딩 제어 mediaPlaybackRequiresUserGesture: false, // 미디어 자동 재생 javaScriptEnabled: true, // 자바스크립트 실행 여부 javaScriptCanOpenWindowsAutomatically: true, // 팝업 여부 ), // 안드로이드 옵션 android: AndroidInAppWebViewOptions( useHybridComposition: true, // 하이브리드 사용을 위한 안드로이드 웹뷰 최적화 ), // iOS 옵션 ios: IOSInAppWebViewOptions( allowsInlineMediaPlayback: true, // 웹뷰 내 미디어 재생 허용 )); @override Widget build(BuildContext context) { return Scaffold( body: SafeArea( child: Column( children: <Widget>[ Expanded( child: Stack( children: [ InAppWebView( // 시작 페이지 initialData: InAppWebViewInitialData(data: """ <!DOCTYPE html> <html lang="ko"> <head> <meta charset="UTF-8"> <meta name="viewport" content="width=device-width, initial-scale=1.0"> <title>InAppWebview Web-App Communication Test</title> <script> window.addEventListener("flutterInAppWebViewPlatformReady", function(event) { /* 웹에서 앱에게 데이터를 보내고 받는 핸들러 * APP : onWebViewCreated에서 addJavaScriptHandler를 정의 * WEB : window.flutter_inappwebview.callHandler를 사용하여 APP에서 정의한 핸들러 이름 호출 * 두번째 파라미터부터는 앱으로 보낼 데이터들을 나열 * callHandler ( 핸들러이름, 데이터1, 데이터2, ...) */ // 웹에서 앱으로 데이터 보내기 window.flutter_inappwebview.callHandler('web2app', 'Hello World!', ['Eunbyeol Ko', 33]); // 앱 데이터 웹으로 받기 window.flutter_inappwebview.callHandler('app2web') .then(function(result) { // 코드 작성 : 예시 코드에서는 앱에서 받은 데이터를 alert로 보여주도록 함 alert(result); }); // 웹과 앱 양방향 통신하기 window.flutter_inappwebview.callHandler('WebAppDataExchange', 1) .then(function(result) { // 코드 작성 : 예시 코드에서는 앱에서 받은 데이터를 alert로 보여주도록 함 // JSON 타입으로 반환하였기 때문에 JSON.stringify를 이용하여 JSON 타입으로 변환 alert(JSON.stringify(result['result'])); }); }); </script> </head> <body> <center> <h2>InAppWebview</h2> <h4>Web-App Data Exchange Test</h4> </body> </html> """), // 초기 설정 initialOptions: options, // 인앱웹뷰 생성 시 컨트롤러 정의 onWebViewCreated: (controller) { /* 웹에서 앱과 통신할 수 있는 핸들러를 정의 * handlerName : 핸들러명 * callback : 웹에서 보낸 데이터 * return : 웹으로 보낼 데이터 */ controller.addJavaScriptHandler( handlerName: 'app2web', callback: (args) { return 'Hello World!'; }); controller.addJavaScriptHandler( handlerName: 'web2app', callback: (args) { // 수행 코드 작성 : 예시 코드에서는 단순히 print로 받은 데이터를 콘솔에 출력함 print('web2app : recieve data ===> $args'); }); controller.addJavaScriptHandler( handlerName: 'WebAppDataExchange', callback: (args) { // 수행 코드 작성 : 예시 코드에서는 단순히 print로 받은 데이터를 콘솔에 출력함 // Web-App Data Exchange : recieve data print( 'Web-App Data Exchange : recieve data ===> $args'); // 받는 값에 따른 로직 처리 : 예시 코드에서는 값이 1이면 result 성공값 반환 if (args[0] == 1) { return { 'result': 'success' }; // Web-App Data Exchange : send data } else { return {'result': 'failed'}; } }); webViewController = controller; }, ), ], ), ), ], ), ), ); } }


8. 참고

출처: https://luvris2.tistory.com/818 [고은별의 기술 공유 연구소:티스토리]

 

 

 

 

본 웹사이트는 광고를 포함하고 있습니다.
광고 클릭에서 발생하는 수익금은 모두 웹사이트 서버의 유지 및 관리, 그리고 기술 콘텐츠 향상을 위해 쓰여집니다.
번호 제목 글쓴이 날짜 조회 수
45 [게임 일반] 선택 기반 게임의 표준 패턴 : Standard Patterns in Choice-Based Games 졸리운_곰 2025.01.13 236
44 [게임 일반] SharpMoku a Gomoku/Five in a Row Written in C# : SharpMoku a Gomoku/Five in a Row C#로 작성됨 : 오목게임 개발 file 졸리운_곰 2024.10.31 311
43 [게임 마켓플레이스] 스팀에 ‘게임’을 출시하고 싶다면? file 졸리운_곰 2024.09.07 316
42 [게임 일반] 카드 덱 이미지 (트럼프 카드) 졸리운_곰 2024.05.27 224
41 [게임 개발 일반] 콘솔은 어려울수록, 모바일은 쉬울수록 '돈' 쓴다 file 졸리운_곰 2023.10.30 264
40 [게임 개발 일반] 게임 초기 기획서 작성 방법 졸리운_곰 2023.07.16 250
39 [게임 일반] 하이퍼 캐주얼 모바일 게임 퍼블리셔가 말하는 개발자의 필수 역량은? file 졸리운_곰 2023.02.08 245
38 [게임 일반] 외신, 2D 게임 개발에 적합한 엔진 10종 선정 file 졸리운_곰 2023.01.15 206
37 [게임 일반] 성공적인 하이퍼 캐주얼 게임 제작을 위해 알아야 할 모든 것 졸리운_곰 2023.01.11 192
36 [게임 일반] 게임의 정의와 요소 file 졸리운_곰 2023.01.02 185
35 [게임 일반] 게임(Game), 일상에서 만드는 놀이의 즐거움 file 졸리운_곰 2023.01.02 205
34 [게임 일반] 우리는 왜 게임에 빠지는가 - 게임의 요소와 게임 변천의 역사 졸리운_곰 2023.01.02 250
33 [게임 일반] 재미있는 게임이란? 10부. 게임의 6단계 file 졸리운_곰 2023.01.02 194
32 [게임 일반] 재미있는 게임이란? 9부 -스타2의 패턴전략- file 졸리운_곰 2023.01.02 214
31 [게임 일반] 재미있는 게임이란? 8부 -블리자드의 패턴전략- file 졸리운_곰 2023.01.02 265
30 [게임 일반] 재미있는 게임이란? 7부 -Wow의 패턴전략- file 졸리운_곰 2023.01.02 162
29 [게임 일반] 재미있는 게임이란? 6부 -패턴과 리소스- file 졸리운_곰 2023.01.02 228
28 [게임 일반] 재미있는 게임이란? 5부 -카오스 시스템- file 졸리운_곰 2023.01.02 266
27 [게임 일반] 재미있는 게임이란? 4부 -패턴과 상호작용-' file 졸리운_곰 2023.01.02 186
26 [게임 일반] 재미있는 게임이란? 3부 '게임이 나아가야 할 방향' file 졸리운_곰 2023.01.02 162
대표 김성준 주소 : 경기 용인 분당수지 U타워 등록번호 : 142-07-27414
통신판매업 신고 : 제2012-용인수지-0185호 출판업 신고 : 수지구청 제 123호 개인정보보호최고책임자 : 김성준 sjkim70@stechstar.com
대표전화 : 010-4589-2193 [fax] 02-6280-1294 COPYRIGHT(C) stechstar.com ALL RIGHTS RESERVED