웹뷰와 네이티브 간 직접적인 데이터 전달이 가능할까?

웹뷰를 이용한 하이브리드 앱을 개발하던 도중에 궁금한 게 생겼습니다. 만약 웹뷰로 띄운 페이지에서 우리가 만든 앱(네이티브)으로 데이터를 전달하거나, 반대로 네이티브 앱에서 웹뷰로 데이터를 직접 전달하는 게 가능할까?

결론부터 말하자면 가능하고, 지금부터 이런 궁금증을 해결한 과정을 소개합니다.

 

Case 1. 웹뷰 to 네이티브

예를 들어 웹뷰에 등록된 html/javaScript 다음과 같이 있다고 합시다.

버튼을 누르면 sendBack() 함수가 호출되고, sendBack() 함수는 JavaScriptChannel 이라는 객체(?)에 접근하여 postMessage 메서드를 실행합니다.

 

  <body>
  <h1 id="title">This is web title</h1>
  <button type="button" onclick="sendBack()">send message to flutter</button>
    ...
  </body>
  <script type="text/javascript">
  	...

   function sendBack() {
      JavaScriptChannel.postMessage("Hello from JS");
   }

 

위를 돌려보면 아래와 같은 모양이 나오겠습니다.

 

그리고 플러터에서는 다음과 같은 코드를 입력해줍니다.

 

import 'package:flutter/material.dart';

import 'package:webview_flutter/webview_flutter.dart';

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

  @override
  _FlutterWebViewDataState createState() => _FlutterWebViewDataState();
}

class _FlutterWebViewDataState extends State<FlutterWebViewData> {
  WebViewController? _controller;

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
            title: ElevatedButton(
          child: Text('send to javascript'),
          onPressed: () {
            if (_controller != null) {
              _controller!.evaluateJavascript(
                  'window.fromFlutter("this is title from Flutter")');
            }
          },
        )),
        body: WebView( // 여기부터 주목
          initialUrl: "http://192.168.0.104:8080/kchoiCustomUploadTest",
          onWebViewCreated: (WebViewController webviewController) {
            _controller = webviewController;
          },
          javascriptMode: JavascriptMode.unrestricted,
          javascriptChannels: Set.from([
            JavascriptChannel(
                name: 'JavaScriptChannel',
                onMessageReceived: (JavascriptMessage message) {
                  print(message.message);
                })
          ]),
        ));
  }
}

 

위 코드를 보면, WebViewController를 생성하고, JavaScriptMode를 unrestricted로 줘서 웹뷰와 통신할 준비를 마칩니다.

그리고 JavaScriptChannel 부분에서 Message를 받아 출력하도록 만들고 있습니다.

여기까지 하고 플러터 앱을 실행시켜서 웹뷰로 띄워진 창의 Send Message to Flutter를 클릭해보면

Hello from JS라는 문구가 클릭할 때마다 로그로 찍힙니다.

 

Case 2. 네이티브 to 웹뷰

이번에는 네이티브에서 웹뷰로 데이터를 전달해봅시다.

플러터 코드는 그대로 두고 html 코드만 수정해줍시다. 함수 하나만 추가하면 됩니다.

<script>
	function fromFlutter(newTitle) {
		document.getElementById("title").innerHTML = newTitle;
	}
    
    function sendBack() {
    	...
</script>

 

위 코드가 의미하는 바는 웹뷰 안에서 fromFlutter(string) 을 호출하면 들어온 문자열로 제목이 바뀐다는 것입니다.

플러터 코드에서는 아래 코드가 그 역할을 합니다.

 

	appBar: AppBar(
            title: ElevatedButton(
          child: Text('send to javascript'),
          onPressed: () {
            if (_controller != null) {
              _controller!.evaluateJavascript(
                  'window.fromFlutter("this is title from Flutter")');
            }
          },
        )),

 

위 코드를 잘 살펴봅시다. send To javascript라는 텍스트가 적힌 버튼을 누르면 onPressed 함수가 실행됩니다. onPressed 함수는 WebViewController 형태로 선언한 _controller 객체의 evaluateJavaScript라는 메서드를 통해 자바스크립트 함수를 실행할 수 있게 만들고, 'window.fromFlutter("문자열")'을 통해 제목을 바꾸도록 지시하고 있습니다.

한번 실행해볼까요?

 

  • 네이버 블러그 공유하기
  • 네이버 밴드에 공유하기
  • 페이스북 공유하기
  • 카카오스토리 공유하기
// custom