Sibainu Relax Room

愛犬の柴犬とともに過ごす部屋

Android javascriptを使ってウェブアプリを作成

今日も12月の中旬とは思えないような暖かい日です。気持ちがいいので眠たいなという顔している柴犬です。

概要

公式HPで下記の「WebView でのウェブアプリの作成」を基に試みました。

https://developer.android.com/guide/webapps/webview?hl=ja

かなり悪戦苦闘しましたので記録します。

次の図は私の理解です。正しいのか間違っているか分かりません。

次に紹介する本はちょっと過激な表紙ですが、本の内容はまじめてよく理解できる書き方をしています。先の「Androidアプリ開発」で飛ばしているところを丁寧に説明しているので、これで理解が早まりました。お勧めです。

しかもこれが100円で買え、ボリュームがすごい量です。なので著者に感謝です。

MainActivity.java

copy

package siba.inu.android.js1;

import android.content.Context;
import android.os.Bundle;

import android.webkit.JavascriptInterface;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {

    Context context;

    WebView myWebView;
    WebView wv;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        context = this;
        myWebView = (WebView) findViewById(R.id.webView);

        // デフォルトでは、JavaScript は WebView で無効になっています。有効にします。
        //WebSettings webSettings = myWebView.getSettings();
        //webSettings.setJavaScriptEnabled(true);
        //myWebView.setWebViewClient(new WebViewClient());
        // JavaScript コードを Android コードにバインドする(キーAndroid)
        //myWebView.addJavascriptInterface(new WebAppInterface(context), "Android");
        //myWebView.loadUrl("file:///android_asset/index.html");

        WebView wv = new WebView(context);

        // デフォルトでは、JavaScript は WebView で無効になっています。有効にします。
        wv.getSettings().setJavaScriptEnabled(true);
        wv.setWebViewClient(new WebViewClient());
        // JavaScript コードを Android コードにバインドする(キーAndroid)
        wv.addJavascriptInterface(new JavaScript(context), "Android");
        setContentView(wv);
        wv.loadUrl("file:///android_asset/index.html");
    }

    // JavaScript.javaを作らない場合、これを作ります。
    public class WebAppInterface {
        Context _context;

        /** Instantiate the interface and set the context */
        WebAppInterface(Context c) {
            _context = c;
        }

        /** Show a toast from the web page */
        @JavascriptInterface
        public void showToast(String toast) {
            Toast.makeText(_context, toast, Toast.LENGTH_SHORT).show();
        }
    }

}

JavaScript.java

copy

package siba.inu.android.js1;

import android.content.Context;
import android.webkit.JavascriptInterface;
import android.widget.Toast;

public class JavaScript {
    private Context _context;

    public JavaScript(Context context) {
        this._context = context;
    }

    @JavascriptInterface
    public void showToast(String s) {
        Toast toast = Toast.makeText(_context, s, Toast.LENGTH_LONG);
        toast.show();
    }
}

assets/index.html

copy

<html lang="ja">
<head>
    <title>sample</title>
    <meta charset="UTF-8">
    <script src="./js/common.js"></script>
</head>
<body>
    <div>
        <input type="button" id="callButton" value="Say hello" onClick="showAndroidToast('Hello Android!')" />
    </div>
    <script type="text/javascript">
        function showAndroidToast(toast) {
            <!--キーAndroid-->
            Android.showToast(toast);
        }
    </script>
</body>
</html>

AndroidManifest.xml

copy

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:dataExtractionRules="@xml/data_extraction_rules"
        android:fullBackupContent="@xml/backup_rules"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/Theme.Js1"
        tools:targetApi="31">
        <activity
            android:name=".MainActivity"
            android:exported="true">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

res/layout/activity_main.xml

copy

<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Hello World!"/>

    <WebView
        android:id="@+id/webView"
        android:layout_width="0dp"
        android:layout_height="0dp"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toBottomOf="@+id/textView" />

</androidx.constraintlayout.widget.ConstraintLayout>

Say hello ボタンをタップした結果

次の画像は AndroidStudio でエミュレートした結果の画像です。想定通りにトーストが表示されました。

左が上の MainActivity.java を実行しています。

右は上の MainActivity.java を変更して実行しています。変更箇所は画像の下にあります。

MainActivity.java の変更箇所です。

        WebSettings webSettings = myWebView.getSettings();
        webSettings.setJavaScriptEnabled(true);
        myWebView.setWebViewClient(new WebViewClient());
        myWebView.addJavascriptInterface(new WebAppInterface(context), "Android");
        myWebView.loadUrl("file:///android_asset/index.html");

        //WebView wv = new WebView(context);
        //wv.getSettings().setJavaScriptEnabled(true);
        //wv.setWebViewClient(new WebViewClient());
        //wv.addJavascriptInterface(new JavaScript(context), "Android");
        //setContentView(wv);
        //wv.loadUrl("file:///android_asset/index.html");

assets フォルダーの作成

assets フォルダーの作成とその直下の js フォルダーの作成に手間取りましたので記録します。

Project タブの app を選択 → メインタブメニュー File → リスト New → リスト Folder
→ リスト Assets Folder とクリックします。

New Android Component フォームが開きますので、初めての場合はこのままでボタン Finish を押下します。

assets が作成されているはずです。

js フォルダーを作成します。

assets の作成を繰り返します。2回目になると次のようになります。

赤線の2を js に変えてボタン Finish を押下します。

assets の直下に js フォルダーが作成されます。