Flutter webView config 및 사용법

강정우·2023년 10월 10일
0

Flutter&Dart

목록 보기
66/87

Flutter webView 환경 세팅

  • 시간이 곧 돈인 기업에서 특히 중소규모의 기업에서 목업 디스플레이를 일일이 flutter 코드로 바꾸는 것은 쉽지 않다. 물론 숙련된 개발자와 함께 오랫동안 쌓아온 보일러 코드가 있다면 금방 개발하겠지만
    현재 우리 사내 app을 도입하는 것은 처음이고 나에게 준 시간을 그리 많지 않았다.
    그래서 생각한 것이 바로 webview이다.

  • 그래서 이번에는 web view와 왼쪽에선 front-end frame-work 서버를 돌리고 오른쪽에서는 flutter 앱을 돌려서 바로바로 확인할 수 있는 환경을 구성해보자.

1. web project 실행하기

  • 우선 webview중에 web을 담당하는 web project를 localhost로 실행해주면 된다.
    참고로 여기에 나오는 react는 3000, vue.js는 5173 포트 번호를 밑에 실행할 url값 뒤에 붙여줘야한다.

2. WebView 위젯에 초기 url 작성하기

  • 이제 webview중 view를 만들어봐.
    이때 예제들을 보면 통상 youtube url을 넣거나 그렇지만 우리는 localhost의 주소값을 넣을 것이다.
    localhost의 주소값을 가져오는 방법은 매우 간단하다.

우선 노트북이 유선 Lan에 연결되어있다면 wi-fi로 바꿔주자. 왜냐하면 pc, 폰이 같은 망을 공유해야하기 때문이다.

  • 다음 cmd에서 ipconfig 를 치면 위 사진처럼 IPv4에 대한 주소값을 얻어올 수 있는데 이 뒤에 포트번호까지 넣어주면 된다.
class HomeScreen extends StatefulWidget {
  const HomeScreen({required this.token, Key? key}) : super(key: key);

  
  State<HomeScreen> createState() => _HomeScreenState();
}

class _HomeScreenState extends State<HomeScreen> {
  WebViewController? webViewController;
  Set<JavascriptChannel>? channel;
  final homeUrl = 'http://주소값/:포트번호';

  
  void initState() {
    super.initState();
  }

  
  void dispose() {
    super.dispose();
  }

  
  Widget build(BuildContext context) {
    final appDir = syspaths.getApplicationDocumentsDirectory();

    return WebView(
    		initialUrl: homeUrl,
            onWebViewCreated: (WebViewController webViewController) {
            	this.webViewController = webViewController;
            },
            javascriptMode: JavascriptMode.unrestricted,
            javascriptChannels: <JavascriptChannel>{
            	JavascriptChannel(
            		name: 'flutterGetImage',
            		onMessageReceived: (JavascriptMessage message) {
            			_getImage();
            		},
            	),
            },
    	);
  }
}
  • 참고로 지금은 4.x.x 버전이라 작성법이 조금 바뀌었다. 이때 버전은 3.x.x 버전이다.

3. AndroidMainfest.xml 파일 세팅 (net::ERR_CLEARTEXT_NOT_PERMITTED)

  • 마지막으로 configure이다. 이 에러는 http로 호출했을 때 나는 에러이다.

이때 android => app => src => main => AndroidManifest.xml 에 application tag안에

<application
        android:label="test"
        android:name="${applicationName}"
        android:icon="@mipmap/ic_launcher"
        android:usesCleartextTraffic="true"      	<= 이부분
        >
        <activity
	...

를 넣어주면 해결된다.

+ 23/10/25

  • 우선 2가지 문제가 생겼다. 우선 특정 안드로이드 핸드폰에서 동작을 하지 않는다. 두번째로 AnroidManifest에서 그냥 usercleartextTraffic만 넣어주면 모든 http 트레픽을 허용하기 때문에 보안성이 심각하게 떨어진다. 이를 해결하기위해 webview 버전 업과 AndroidManifest 추가 설정을 해보자.

1. webview 4.x.x

class _MyHomePageState extends State<MyHomePage> {
  WebViewController controller = WebViewController()
    ..setJavaScriptMode(JavaScriptMode.unrestricted)
    ..setBackgroundColor(const Color(0x00000000))
    ..loadRequest(Uri.parse('http를 허용하고 싶은 url'));

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        body: WebViewWidget(
      controller: controller,
    ));
  }
}
  • 뭐 사실 대단히 바뀐건 없다. pub.dev에 나와있는 예제 코드는
controller = WebViewController()
  ..setJavaScriptMode(JavaScriptMode.unrestricted)
  ..setBackgroundColor(const Color(0x00000000))
  ..setNavigationDelegate(
    NavigationDelegate(
      onProgress: (int progress) {
        // Update loading bar.
      },
      onPageStarted: (String url) {},
      onPageFinished: (String url) {},
      onWebResourceError: (WebResourceError error) {},
      onNavigationRequest: (NavigationRequest request) {
        if (request.url.startsWith('https://www.youtube.com/')) {
          return NavigationDecision.prevent;
        }
        return NavigationDecision.navigate;
      },
    ),
  )
  ..loadRequest(Uri.parse('https://flutter.dev'));
  • 이렇게 생겼는데 뭐 3.x.x 버전과 매우 흡사하다. 다만 JavaScriptMode, Channel 과 initUrl 모두 controller의 속성으로써 들어갔다는 것이다. 대충 한 번 훑어보자.
  1. WebViewController: 웹뷰의 컨트롤러이고 이 객체를 통해 웹뷰의 동작을 제어한다.
  2. setJavaScriptMode(JavaScriptMode.unrestricted): JavaScript 실행 모드를 설정한다. unrestricted는 JavaScript가 제한 없이 실행될 수 있음을 의미한다.
  3. setBackgroundColor(const Color(0x00000000)): 웹뷰의 배경색을 설정한다. 참고로 저 값은 투명을 뜻한다.
  4. setNavigationDelegate(NavigationDelegate(...)): 네비게이션 동작에 대한 위임자(delegate)를 설정한다.
  5. onProgress: 페이지 로딩 진행률이 변경될 때 호출되는 콜백 함수.
  6. onPageStarted: 페이지 로딩이 시작될 때 호출되는 콜백 함수.
  7. onPageFinished: 페이지 로딩이 완료될 때 호출되는 콜백 함수.
  8. onWebResourceError: 웹 리소스 로딩 중 에러가 발생했을 때 호출되는 콜백 함수.
  9. onNavigationRequest: 네비게이션 요청이 발생했을 때 호출되는 콜백 함수이다.
    위 예제코드에서는 요청된 URL이 https://www.youtube.com/로 시작하는 경우 네비게이션을 방지하도록 되어있다. 즉, YouTube 링크 클릭 시 해당 링크로 이동하지 않도록 하는 기능을 제공한다.
  10. loadRequest(Uri.parse('https://flutter.dev')): 주어진 URL의 웹 페이지를 로드한다.
  • 이렇게 간단하게 webview 4.x.x에 대해 설명을 끝냈고 이제 AndroidManifest.xml에 대해 알아보자.

2. AndroidMinifest.xml

* 우선 앞서 .xml 파일에 넣은 android:usesCleartextTraffic="true" 이 설정은 앱이 평문 네트워크 트래픽 즉, HTTP을 사용할 수 있도록 한다.

* 하지만 이 설정은 전체 앱에 적용되므로, 가능한 한 구체적인 도메인에 대해서만 예외를 설정하는 것이 좋다. 그러기 위해서는 networkSecurityConfig 리소스를 사용하여 더 세밀한 제어를 할 수 있다.

1. res/xml/ path에 network_security_config.xml 파일을 만들어준다. 만약에 res에 xml 폴더가 없다면 생성하면 된다.

2. 코드생성

<network-security-config>
    <domain-config cleartextTrafficPermitted="true">
        <domain includeSubdomains="true">http를 허용할 url</domain>
    </domain-config>
</network-security-config>

3. AndroidMinifest.xml에 설정 잡기

<application
    ...
    android:networkSecurityConfig="@xml/network_security_config"
    ...>
   ...
</application> 
  • 이렇게 설정하면 특정 도메인에서만 HTTP 요청이 가능하다. => 그래서 이 설정을 넣으면 안 된다.
profile
智(지)! 德(덕)! 體(체)!

0개의 댓글