티스토리 뷰

Tip and Error

flutter webview로 만들어보기(+ device 정보)

geonwoopaeng@gmail.com 2024. 2. 18. 00:00

flutter webview로 만들어보기

이번에 동료분들과 나누기 위해 글로 정리를 해봤습니다.

우선 기본적인 Flutter SDK 다운로드등과 관련된 완전 기본 세팅 이후 과정입니다.
기본 세팅에 관해서 보고 싶으면 다음 페이지에서 확인 부탁드려요 (코딩애플 짱!)

https://codingapple.com/unit/flutter-install-on-windows-and-mac/

 

Flutter 설치와 개발환경 셋팅 (윈도우 / 맥) - 코딩애플 온라인 강좌

Flutter 개발환경 셋팅하기 위해 설치할 것들이 좀 있습니다. 윈도우 10이상 (64bit) 또는 맥OS 10.14버전 이상이 필요합니다. 1. Flutter SDK 설치 https://flutter.dev/docs/development/tools/sdk/releases?tab=windows 위 사

codingapple.com

 

사용 Tech

  • Android Studio
  • flutter
    • webview_flutter
    • device_info_plus
    • uuid
    • shared_preferences

이제 시작을 해보도록 하겠습니다.

크게 3가지 과정을 거치면 됩니다.

  1. webview_flutter 등 lib 설치
  2. main.dart 수정
  3. AndroidManifest.xml에 값 추가 (Android)
  4. info.plist에 값 추가 (Ios, XCode)

 

1. webview_flutter 등 lib 설치

pubspec.yaml 에서 설치할 lib를 추가해야 합니다.

추가할 lib는 다음과 같습니다.

webview_flutter: ^4.2.2
device_info_plus: ^9.0.3
uuid: ^3.0.7
shared_preferences: ^2.2.0

dependencies에 다음과 같이 넣어주시면 됩니다.
(띄어쓰기 잘 맞추기!!!)

dependencies:
  flutter:
    sdk: flutter

  webview_flutter: ^4.2.2
  device_info_plus: ^9.0.3
  uuid: ^3.0.7
  shared_preferences: ^2.2.0

  # The following adds the Cupertino Icons font to your application.
  # Use with the CupertinoIcons class for iOS style icons.
  cupertino_icons: ^1.0.2

설치 하기 위한 명령어

$ flutter pub get

 

2. main.dart 수정

해당 부분에서는 webview 적용하는 것과 Device 정보를 받아서 
webview 주소에 Device 정보를 parameter로 붙여서 사용했습니다.
즉, url 주소: webview_url?Device_info

import 'dart:convert';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:webview_flutter/webview_flutter.dart';
import 'package:flutter/services.dart';
import 'package:device_info_plus/device_info_plus.dart';
import 'package:uuid/uuid.dart';
import 'package:shared_preferences/shared_preferences.dart';

final String webview_url = "https://paeng.com";
/*
* main 함수는 App을 시작할 때 처음 실행되는 함수
* */
void main() async {
  WidgetsFlutterBinding.ensureInitialized(); //앱 실행할 준비가 완료될 때까지 기다린다.
  runApp(const MyApp());
}

/*
 * StatelessWidget: 상태가 없는 위젯
 * 한번 그려진 후 상태가 변경 X -> UI를 빠르게 그린다.
 */
class MyApp extends StatelessWidget {
  const MyApp({super.key});

  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'PAENG TEA',
      home: const MyHomePage(),
    );
  }
}

/*
 * StatefulWidget: 상태를 가지고 있는 위젯
 * 데이터 변경에 따라 UI 업데이트 할 수 있다.
 */
class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key});

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

/*
* WidgetsBindingObserver: 앱 생명주기 이벤트를 감지하기 위한 인터페이스
* */
class _MyHomePageState extends State<MyHomePage> with WidgetsBindingObserver {
  late WebViewController controller;
  late Future<String> webview_info_url;

  @override
  State<MyHomePage> createState() => _MyHomePageState();

  // State 객체가 최초 생성될 때 호출되는 메소드 (한번만 호출)
  // 초기화 하는 부분 주로 사용
  @override
  void initState() {
    super.initState();
    webview_info_url = getWebViewUrl();
  }

  @override
  Widget build(BuildContext context) {
    // FutureBuilder: 비동기 처리하는 데이터를 처리한 후 위젯을 반환할 때 사용하는 위젯
    return FutureBuilder<String>(
      future: webview_info_url,
      builder: (context, snapshot) {
        if (snapshot.connectionState == ConnectionState.done) {
          controller = WebViewController()
            ..setJavaScriptMode(JavaScriptMode.unrestricted)
            ..loadRequest(Uri.parse(snapshot.data!));

          return Scaffold(
            body: WebViewWidget(
              controller: controller,
            )
          );
        } else {
          return Scaffold(
            body: Center(
              child: CircularProgressIndicator(),
            )
          );
        }
      }
    );
  }

  // webview 주소를 가져오는 곳
  Future<String> getWebViewUrlAddInfo() async {
    String OS_TYPE = "";
    String OS_VERSION = "";
    String DEVICE_MODEL = "";
    String UDID = "";
    String WIDTH = "";
    String HEIGHT = "";

    DeviceInfoPlugin deviceInfo = DeviceInfoPlugin();
    if (Platform.isAndroid) {
      AndroidDeviceInfo info = await deviceInfo.androidInfo;

      OS_TYPE = "Android";
      OS_VERSION = info.version.release;
      DEVICE_MODEL = info.model;

      /*
      * UDID(Unique Device Identifier)
      * : 각 기기에 부여되는 고유한 디바이스 식별값 (앱을 삭제해도 유지)
      *
      * UUID(Universally Unique Identifier)
      * : 앱마다 가지고 있는 식별값
      */
      final SharedPreferences sp = await SharedPreferences.getInstance();
      String? uuid_sp = sp.getString("UUID");
      if(uuid_sp == null || uuid_sp == "") {
        var uuid = Uuid();
        UDID = uuid.v4();
        await sp.setString("UUID", UDID);
      } else {
        UDID = uuid_sp.toString();
      }

      final device_info = await deviceInfo.deviceInfo;
      WIDTH  = device_info.data["displayMetrics"]["widthPx"].toString();
      HEIGHT = device_info.data["displayMetrics"]["heightPx"].toString();

    } else if (Platform.isIOS) {
      IosDeviceInfo info = await deviceInfo.iosInfo;

      OS_TYPE = "iOS";
      OS_VERSION = info.systemVersion.toString();
      UDID = info.identifierForVendor.toString();
      DEVICE_MODEL = info.model;
    }

    // 주소 return 해주는 부분
    return '$webview_url?uuid=$UDID&deviceVersion=$OS_VERSION&os_kind=$OS_TYPE&deviceModel=$DEVICE_MODEL&width=$WIDTH&height=$HEIGHT';
  }
}

 

3. AndroidManifest.xml에 값 추가 (Android)

해당 파일 경로: android > app > src > main 내부에 있는 AndroidManifest.xml 입니다.

빨간색 부분을 추가해야 됩니다.
android:usesCleartextTraffic="true"

이유:
안드로이드에서 Http 접근을 허용하지 않는다는 의미 입니다.
즉, Http를 사용한 웹을 사용할때 발생할 수 있는 문제를 없애기 위해 적용했습니다.

Android Studio에서 Emulator을 켜고 실행하면 됩니다.

3. info.plist에 값 추가 (Ios, XCode)

해당 파일 경로: ios > Runner 내부에 있는 info.plist파일(ios 설정하는 부분) 입니다.

NSAllowsArbitraryLoads

  • http 통신 허용 (ATS(App Trasport Security)정책에서 기본적으로 https 통신을 유도하고 있기 때문)

NSAllowsArbitraryLoadsInWebContent

  • 웹뷰내에서 이루어지는 호출에 대한 ATS 제한을 설정
<plist>
<dict>
    ...
    <key>NSAppTransportSecurity</key>
        <dict>
            <key>NSAllowsArbitraryLoads</key>
            <true/>
            <key>NSAllowsArbitraryLoadsInWebContent</key>
            <true/>
        </dict>
</dict>
</plist>

cocopod을 설치하여 pod file을 실행해야 합니다.
https://points.tistory.com/69

 

[Flutter] CocoaPods 설치 및 사용

CacaoPods는 Swift 혹은 Object-C 프로젝트에서 사용할 수 있는 의존성 관리도구입니다. .NET 진영의 Nuget이나 Node 진영의 NPM과 동일한 역할을 담당하게 됩니다. 애플에서 공식 개발한 것은 아니고, 2011년

points.tistory.com

$ flutter clean
$ flutter create ios
$ flutter pub get
$ cd ios
$ pod install

XCode에서 실행을 하면 됩니다.

 

마무리

저번에 flutter을 급하게 도입하고 구현하여 정리가 잘 되지 않았습니다.
그래서 동료들에게 잘 나누지 못해서 아쉬운 마음이 있었는데 이번 기회에 나누게 되어서 다행입니다.
긴 글 읽어주셔서 감사합니다. :) 

반응형
공지사항
최근에 올라온 글