🦨

WebViewを表示する

2023/03/06に公開

便利なパッケージがあった!

Webviewの仕組みを使って、Flutterでプライバシーポリシーと利用規約を表示して、Notionの画面を表示したのですが、表示速度が遅いのと、外部サイトにアクセスするリンクが表示されてボタンを押してもすぐに表示できないのが、UI/UX的によろしくないと思い、Reactのパッケージを使用して、マークダウンで記述されたプライバシーポリシーと利用規約を表示する方法に変更したところ問題点が改善されたので、記事にしようと思いました。

そもそもWebviewとは?
WebViewは、アプリにブラウザのようなものを埋め込む機能であり、実装すると指定したウェブページを表示することができます。

  • やること
    • マークダウンを表示するアプリを作成する
    • マークダウンを表示するパッケージを追加する
    • Netlifyにホスティングする
    • Flutterで画面に表示する

https://deha.co.jp/magazine/webview-pros-cons/

今回使用したnpmのパッケージ
https://www.npmjs.com/package/react-markdown

使用したホスティングサービス
https://www.netlify.com/

Reactのコード

利用規約とプライバシーポリシーを表示するコンポーネントを作成して、画面に表示するように設定する。一つのアプリでページを複数作ってやってみたのですが、Netlifyにホスティングしたときに、urlを変更すると映らなくなったので、もったいないですがふたつプロジェクトを作成しました。
プロジェクトを作成して必要なパッケージを追加する。
以下のコードを参考にマークダウンを表示するページを作成する

npm i react-markdown

マークダウンを表示する例

表示する画面のコンポートントを作成してimportするだけ。

App.tsx
import "./App.css";
import Home from "./pages/Home";

function App() {

  return (
    <div className="App">
      <Router>
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</Router>
    </div>
  )
}

export default App
Home.tsx
import React from "react";
import { Link } from "react-router-dom";
import PrivacyComponent from "../components/PrivacyComponent";

function Home() {
return (
< div className="home">
<PrivacyComponent />
</ div>
);
}

export default Home;
PrivacyComponent.tsx
import ReactMarkdown from 'react-markdown'

const PrivacyComponent = () => {
  // 変数の中に``で囲んだマークダウンを配置する。
  const privacyMarkdown =
  `
  # プライバシーポリシー

**ご利用条件**

アプリをダウンロードまたは使用することにより、これらの条件が自動的に適用されます。したがって、アプリを使用する前に、これらの条件をよく読む必要があります。お客様は、本アプリ、本アプリの一部、または当社の商標をいかなる方法によってもコピーまたは変更することはできません。また、アプリを他の言語に翻訳したり、派生バージョンを作ったりすることもできません。本アプリ自体、および本アプリに関連する商標権、著作権、データベース権、その他の知的財産権は、現在もJUNICHI HASHIMOTOに帰属しています。

JUNICHI HASHIMOTOは、アプリが可能な限り便利で効率的であるように努めています。そのため、当社は、いつでも、いかなる理由でも、アプリを変更したり、そのサービスに課金したりする権利を有します。また、アプリやそのサービスに対して、お客様が何を支払っているのかを明確にすることなく、料金を請求することは決してありません。

SugaryMapアプリは、私のサービスを提供するために、お客様が当社に提供した個人データを保存し、処理します。お客様の携帯電話およびアプリへのアクセスを安全に保つことは、お客様の責任です。したがって、私たちは、あなたのデバイスの公式オペレーティングシステムによって課されたソフトウェアの制限や制約を取り除くプロセスである、あなたが電話を解約または変更しないことをお勧めします。

JUNICHI HASHIMOTOが責任を負わないものがあることをご承知おきください。本アプリの一部の機能では、本アプリがアクティブなインターネット接続を有することが要求されます。接続はWi-Fiまたはモバイルネットワークプロバイダによって提供されますが、JUNICHI HASHIMOTOは、お客様がWi-Fiにアクセスできず、データ容量が残っていない場合、アプリがフル機能で動作しないことについて責任を負いかねます。

ある時点で、私たちはアプリを更新することを望むかもしれません。このアプリは現在、AndroidとiOSで提供されていますが、両システム(および当社がアプリの提供を拡大することを決定したその他のシステム)の要件が変更される可能性があり、アプリの使用を継続したい場合は、更新をダウンロードする必要があります。JUNICHI HASHIMOTOは、本アプリが常にお客様にとって適切なものとなるよう、また、お客様の端末にインストールされているAndroidおよびiOSのバージョンに対応するよう更新することを約束するものではありません。また、当社は、本アプリの提供を中止することができるものとし、お客様に中止の通知をすることなく、いつでも本アプリの使用を中止することができるものとします。当社が別途通知しない限り、終了時には、(a)本規約でお客様に付与された権利およびライセンスは終了し、(b)お客様はアプリの使用を停止し、(必要に応じて)お客様のデバイスからアプリを削除しなければなりません。

**本規約の変更**について

私は、当社の利用規約を随時更新することがあります。従って、お客様はこのページを定期的にご覧になり、変更を確認されることをお勧めします。私は、このページに新しい利用規約を掲載することにより、変更内容を通知します。

本規約は、2023-03-05より有効となります。
  `

  return (
    <div className='PrivacyComponentText'>
      <ReactMarkdown children={privacyMarkdown}></ReactMarkdown>
    </div>
  )
}

export default PrivacyComponent

レイアウトの設定をするCSS

App.css
body {
  margin: 20px 20px 20px 20px;
}

Flutter側の設定

Webページを表示するために便利なパッケージであるurl_launcherを追加しましょう。

設定が必要なので、こちらの記事を参考に設定してください
https://zenn.dev/flutteruniv_dev/articles/ee377ae7f1fe05

Flutter側のコード
このコード使って利用規約とプライバシーポリシーを表示します。他にもWebページで、アプリの説明書を作ってて、表示するなど使い道が色々とありそうです。

使用例

main.dart
import 'package:flutter/material.dart';
import 'package:font_awesome_flutter/font_awesome_flutter.dart';
import 'package:url_launcher/url_launcher.dart';

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

class MyApp extends StatelessWidget {
  const MyApp({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: const MyHomePage(),
    );
  }
}

class MyHomePage extends StatelessWidget {
  const MyHomePage({Key? key}) : super(key: key);

  
  Widget build(BuildContext context) {
    const privacyUrl = 'https://regal-conkies-8c51fb.netlify.app/';
    const termsUrl = 'https://chipper-dodol-e61ef8.netlify.app/';

    return Scaffold(
      appBar: AppBar(
        title: const Text('URL Launcher'),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: [
            Column(
              children: [
                TextButton(onPressed: () async {
                  final url = Uri.parse(
                        privacyUrl,
                      );
                      if (await canLaunchUrl(url)) {
                        launchUrl(url);
                      } else {
                        // ignore: avoid_print
                        print("Can't launch $url");
                      }
                }, child: Text('プライバシーポリシー')),
                TextButton(onPressed: () async {
                  final url = Uri.parse(
                        termsUrl,
                      );
                      if (await canLaunchUrl(url)) {
                        launchUrl(url);
                      } else {
                        // ignore: avoid_print
                        print("Can't launch $url");
                      }
                }, child: Text('利用規約'))
              ],
            ),
          ],
        ),
      ),
    );
  }
}

こんな感じで、Webページを簡単に表示することができます。


まとめ

モバイルアプリで、Webページの解説や利用規約を表示するのはよく見かけるので、機能を実装してみたいと思い作ってみました。

Discussion