포스트

chatgpt로 simple flutter code 만들기(15) - Dynamic content loading을 사용하는 사이트 대응

만들고 있는 '즐겨찾기' 앱으로 외부에서 Sharing기능으로 홈페이지 url을 전달할 때, 잘 안되는 경우가 있습니다.

sticker

대표적인 예시가 바로 네이버 카페입니다.

예를 들어서 다음과 같은 title을 가지는 카페 페이지가 있습니다.

[초저렴/프리미엄] 갤럭시S9플러스 라벤더 64기가 10만 판매해요! : 네이버 카페

그런데 저의 앱에서 공유받는 url을 플러터의 http.get(uri)를 사용해서 html을 읽어오게 되면

네이버 카페

라고 읽어오게 됩니다.

원인은 네이버 카페 웹페이지는 자바스크립트가 동적으로 컨텐츠를 로딩하지만 플러터의 http 패키지는 정적으로만 불러올 수 있기 때문이라고 합니다.

그래서 해결책을 찾다가 webview_flutter 패키지를 사용하면 동적으로 웹페이지를 읽어올 수 있다는 사실을 알게되었습니다! https://pub.dev/packages/webview_flutter

webview_flutter | Flutter Package A Flutter plugin that provides a WebView widget on Android and iOS. A Flutter plugin that provides a WebView widget on Android and iOS.

1
2
3
4
  webview_flutter: ^4.4.4 # New Added for dynamic html parsing
  webview_flutter_android: ^3.13.2 # New Added for android dynamic html parsing
  webview_flutter_wkwebview: ^3.10.1 # New Added for ios dynamic html parsing

sticker

제가 만든 webViewHelper클래스의 loadPageAndGetTitle()함수를 사용하면 동적인 웹페이지의 Title을 불러올 수 있습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
class WebViewHelper {
  late final WebViewController _controller;
  bool _isControllerInitialized = false;

  Future initController() async {
    // #docregion platform_features
    late final PlatformWebViewControllerCreationParams params;
    if (WebViewPlatform.instance is WebKitWebViewPlatform) {
      params = WebKitWebViewControllerCreationParams(
        allowsInlineMediaPlayback: true,
        mediaTypesRequiringUserAction: const {},
      );
    } else {
      params = const PlatformWebViewControllerCreationParams();
    }

    final WebViewController controller =
    WebViewController.fromPlatformCreationParams(params);
    // #enddocregion platform_features

    controller
      ..setJavaScriptMode(JavaScriptMode.unrestricted)
      ..setBackgroundColor(const Color(0x00000000))
      ..loadRequest(Uri.parse('about:blank'));

    _controller = controller;

    _isControllerInitialized = true;
  }

  Future loadPage(Uri url) async {
    if (!_isControllerInitialized) {
      await initController();
    }
    await _controller.loadRequest(url);

    // Wait for page to finish loading
    await Future.delayed(const Duration(seconds: 1)); // Adjust delay as needed
  }

  Future loadPageAndGetTitle(Uri url) async {
    await loadPage(url);
    // Get the page title
    String title = await _controller.runJavaScriptReturningResult('document.title') as String;
    printDebug('Page title: $title');

    return title;
  }
}

sticker

저는 Refresh(새로고침) 버튼을 누르면 동적 웹사이트의 title을 다시 읽어서 제 UI에 반영할 수 있도록 했습니다.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
IconButton(
  icon: Icon(Icons.refresh),
  onPressed: () async {
    // Add your refresh logic here
    Uri uri = Uri.parse(siteUrlController.text);
    final webViewHelper = WebViewHelper();
    String pageTitle = await webViewHelper.loadPageAndGetTitle(uri);
    // Update the siteNameController's text with the fetched page title
    siteNameController.text = pageTitle;
    // snack bar
    ScaffoldMessenger.of(context).showSnackBar(
      SnackBar(
        content: Text(
            'Page Title: $pageTitle \n URL: $uri',
            style: const TextStyle(color: Colors.white)),
        backgroundColor: Colors.black,
      ),
    );
  },
),

[영상]

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.