【Android】WebViewのボタンタップイベント処理の備忘

# はじめに
Androidアプリの画面は、主にXMLやJetpack Composeによって構築されますが、HTMLファイルを画面として表示させることも可能です。
そのため、HTML画面の表示とボタンタップ処理の制御方法を、本記事に備忘として記載してみました。

# やりたいこと
実装する処理の順序は以下です。
[1. HTML画面のボタンタップでURLスキームが発火される](https://qiita.com/tsuna_san/items/4cbdb63cf3b0b50d6247#1-html%E7%94%BB%E9%9D%A2%E3%81%AE%E3%83%9C%E3%82%BF%E3%83%B3%E3%82%BF%E3%83%83%E3%83%97%E3%81%A7url%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%A0%E3%81%8C%E7%99%BA%E7%81%AB%E3%81%95%E3%82%8C%E3%82%8B)
[2. 発火されたスキームをアプリで検知してダイアログを表示する](https://qiita.com/tsuna_san/items/4cbdb63cf3b0b50d6247#2-%E7%99%BA%E7%81%AB%E3%81%95%E3%82%8C%E3%81%9F%E3%82%B9%E3%82%AD%E3%83%BC%E3%83%A0%E3%82%92%E3%82%A2%E3%83%97%E3%83%AA%E3%81%A7%E6%A4%9C%E7%9F%A5%E3%81%97%E3%81%A6%E3%83%80%E3%82%A4%E3%82%A2%E3%83%AD%E3%82%B0%E3%82%92%E8%A1%A8%E7%A4%BA%E3%81%99%E3%82%8B)

:::note info
使用するHTMLファイルはアプリ内に配置します。
以降、***ローカルHTML***と記載します。
:::
:::note info
***URLスキームとは***
URLの先頭の箇所。（`http://xxxxxx.com`でいうと`http`の部分）
別アプリに値を渡し、渡した値を元に別アプリ上で処理を実施することが可能。
:::

ここからは処理順にコードと説明を記載していきます。

## 実装

### 1. HTML画面のボタンタップでURLスキームが発火される
まずは画面として使用するHTMLとCSSのファイルをそれぞれ用意します。
```sample_html_view.html
<html>
    <link rel="stylesheet" href="sample_css.css">
    <body>
        <h1 class=sampleTitle>HTML画面</h1>
        <br/>
        <a class=sampleButton type="button" href="event://start_scheme/">Start Scheme</a>
    </body>
</html>
```

```sample_css.css
.sampleTitle{
    margin: auto;
    text-align:center;
}

.sampleButton {
    display: block;
    margin: auto;
    text-align: center;
    width: 100px;
    border: 0;
    border-radius: 5px;
    background: #4676D7;
    color: #fff;
    padding: 10px 20px;
    font-size: 16px;
    text-decoration: none;
}
```
HTMLに`<a>`タグがありますが、こちらがダイアログ表示させるボタンとなります。この`href`に今回使用するURLスキームを記載します。（event://~）
ボタンタップすると、このURLスキームが発火され、アプリ上で検知されます。
```html
<a class=sampleButton type="button" href="event://start_scheme/">Start Scheme</a>
```
作成したHTML・CSSファイルは、app/src/main直下にassetsフォルダを作成し、その配下に設置します。
<img width="350" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308202/50ecc282-76c0-c043-04b0-4ba264854842.png">


### 2. 発火されたスキームをアプリで検知してダイアログを表示する
作成したHTML画面をアプリで表示させるための処理を、XMLおよびActivityに追記していきます。

```activity_main.xml
    <WebView
        android:id="@+id/webViewTest"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
```

```MainActivity.kt
class MainActivity : AppCompatActivity() {
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.activity_main)

        // activity_main.xmlのWebViewに記載したidを指定
        val webView: WebView = findViewById(R.id.webViewTest)

        // WebViewClientを設定
        val customWebViewClient = SampleWebViewClient(this)
        webView.webViewClient = customWebViewClient

        // assets配下に設置したHTMLの読み込み
        webView.loadUrl("file:///android_asset/sample_html_view.html")
    }
}
```

`loadUrl`でHTMLを読み込み表示させます。`android_asset`とパスに記載することで、作成したassetsフォルダ配下のファイルが読み込まれます。

```kotlin
webView.loadUrl("file:///android_asset/sample_html_view.html")
```
<br>

次に`MainActivity`で設定する`WebViewClient`クラスを作成します。
```SampleWebViewClient.kt
class SampleWebViewClient(private val activity: Activity) : WebViewClient() {

    override fun shouldOverrideUrlLoading(view: WebView, request: WebResourceRequest): Boolean {
        val url = request.url.toString()

        // URLスキームを検知して、ダイアログ表示を実施
        if (url == "event://start_scheme/") {
            Log.d("MyApp", "スキーム発火");
            showDialog(activity)
            return true
        }

        return false
    }

    // ダイアログ表示処理
    private fun showDialog(context: Context) {
        AlertDialog.Builder(context)
            .setTitle("スキーム発火テスト")
            .setMessage("スキーム発火されました。")
            .setPositiveButton("OK") { dialog, _ ->
                dialog.dismiss()
            }
            .show()
    }
}
```
<br>

WebViewのURLスキーム発火時のダイアログ表示処理を`shouldOverrideUrlLoading`の↓で制御します。

```kotlin
        // URLスキームを検知して、ダイアログ表示を実施
        if (url == "event://start_scheme/") {
            Log.d("MyApp", "スキーム発火");
            showDialog(activity)
            return true
        }
```
:::note warn
***注意***
shouldOverrideUrlLoadingでは、そのままだとURL読み込みが継続して読み込み失敗画面が表示されるため、trueをreturnして防止させる必要があります。
:::

# 動作確認
以下、アプリの動作確認の画面です。

通常時
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308202/49855f35-b43c-7c45-3098-2091eecefef7.png">

ボタンタップ時
<img width="250" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/308202/bd0d4f26-c164-8d36-92c1-3f2f9d7dc3f5.png">



# 所感
応用すれば、ローカルHTMLからのイベントで、カメラ起動などの端末機能を制御できそう。
いずれ、その辺りも確かめてみたいですね🤔

# 参考
今回参考にした記事は以下。
[Android FragmentにローカルHTMLファイルからWebViewを表示（Kotlin）](https://qiita.com/kokogento/items/18b311528f3869536d9a)
[Android WebViewのリンクのクリックをアプリケーション側で検出する](https://www.ipentec.com/document/android-webview-detect-link-click-and-cancel-page-load)
[Android FragmentにローカルHTMLファイルからWebViewを表示（Kotlin）](https://qiita.com/kokogento/items/18b311528f3869536d9a)

勝手ながら参考にさせていただきました。
ありがとうございました🙇‍♂️