준코딩

플러터 웹뷰 Javascript <-> 앱 통신 본문

프로그래밍/플러터(Flutter)

플러터 웹뷰 Javascript <-> 앱 통신

Ljunhyeob - App Dev 2024. 4. 4. 17:45

플러터 하이브리드 앱을 제작하고 있습니다.

 

하이브리드 앱에서 거의 필수로 해야 하는 게 웹페이지와 앱 간의 통신입니다.

 

어떻게 하는지 정리 해보겠습니다.

 

pubspec.yaml 파일에  webview_flutter: ^4.7.0을 추가하였습니다.

(이게 예전 버전은 웹뷰를 생성할 때 WebView를 했는데, 최신버전에서는 WebViewWidget으로 바뀌었다고 합니다. 몇 버전부터인진 안 찾아봐서 모르겠습니다. )

 

lib/main.dart 파일입니다.

import 'package:flutter/material.dart';
import 'package:flutter_webview_example/webview_page.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: const WebviewPage(),
    );
  }
}

 

2번째 import는 아직 생성하지 않은 파일이라 에러 나는 게 정상입니다.  아래에서 파일을 생성하면 해결됩니다.

 

 

lib폴더 안에 webview_page.dart 파일을 생성해 주었습니다. 

 

//설명은 주석으로 달아두었습니다.

 

import 'dart:convert'; // json 형식을 디코딩하기 위해 선언.
import 'package:flutter/material.dart'; 
import 'package:webview_flutter/webview_flutter.dart'; 

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

  @override
  State<WebviewPage> createState() => _WebviewPageState(); 
}

class _WebviewPageState extends State<WebviewPage> { 
  WebViewController? _controller; 

  @override
  void initState() { 
    super.initState(); 
    _controller = WebViewController() 
      ..setJavaScriptMode(JavaScriptMode.unrestricted) // 자바스크립트 실행 모드를 설정합니다.
      ..setBackgroundColor(const Color(0x00000000)) // 배경색을 투명으로 설정합니다.
      ..setNavigationDelegate( 
        NavigationDelegate( // 네비게이션 이벤트를 처리하는 콜백을 설정합니다.
          onProgress: (int progress) {}, // 페이지 로딩 진행도 이벤트 핸들러를 설정합니다.
          onPageStarted: (String url) {}, // 페이지 로딩 시작 이벤트 핸들러를 설정합니다.
          onPageFinished: (String url) {}, // 페이지 로딩 완료 이벤트 핸들러를 설정합니다.
          onWebResourceError: (WebResourceError error) {}, // 웹 리소스 에러 핸들러를 설정합니다.
          onNavigationRequest: (NavigationRequest request) { //페이지 이동할때 호출됩니다.
            return NavigationDecision.navigate; //페이지 이동 항상 허용 , 특정 url경우 허용 불가하게 할 수 있습니다.
          },
        ),
      )
      ..addJavaScriptChannel('Test', onMessageReceived: (JavaScriptMessage message) { // JavaScript 채널을 추가하고 메시지 수신 이벤트 핸들러를 설정합니다.
        Map<String, dynamic> data = json.decode(message.message); // 수신된 메시지를 JSON 디코딩하여 Map으로 파싱합니다.
        print("javascript func message: " + data['action'].toString()); // 메시지의 'action' 키 값을 출력합니다.
        if(data['action'] == "download"){ // 'action' 값이 'download'인 경우에 대한 조건문을 추가합니다.
          print("javascript func download 실행"); // 'download' 실행 메시지를 출력합니다.
          print("value: " + data['value'].toString()); // 'value' 값을 출력합니다.
        }
      })
      ..loadRequest(Uri.parse('https://leejhjava.tistory.com')); // 웹뷰에 특정 URL을 로드합니다.
  }

  @override
  Widget build(BuildContext context) { 
    return Scaffold( 
      body: SafeArea( 
        child: WebViewWidget(controller: _controller!), 
      ),
    );
  }
}

 

 

이렇게 코드를 작성하면 웹 <-> 앱 간에 통신이 완료됩니다!

 

Javascript 에서 앱으로 데이터를 보내려면

window.flutter_inappwebview.callHandler(‘Test, {action: 'download', value: 123});

 

이런 식으로 보내면 됩니다!

 

만약 값은 보내고 싶지 않다면

window.flutter_inappwebview.callHandler('Test', {action: 'download'});

 

이렇게 하시면 됩니다

Comments