ウェブ デベロッパー向けの WebView アプリケーション

公開日: 2014 年 2 月 28 日

新しい Android プロジェクトを作成し、WebView を追加して、リモート URL を読み込み、ローカル HTML ページを読み込む方法を学びます。

このチュートリアルは、Android 開発環境の経験がほとんどない、またはまったくないデベロッパーを対象としています。ただし、Kotlin の経験は多少あることを前提としています。Android 向けプログラミングに精通している場合は、Android デベロッパー サイトの WebView でウェブアプリを作成するをご覧ください。

Android Studio をインストールする

このチュートリアルでは、Android 向けの設計とビルドの IDE である Android Studio を使用します。

新しい Android プロジェクトを作成する

Android Studio のインストールが完了すると、セットアップ ウィザードが起動します。

新しいプロジェクトを作成するには:

  1. [新しいプロジェクト] をクリックします。
  2. [Empty Activity] テンプレートをクリックして、プロジェクトに選択します。テンプレートにより、プロジェクトの構造と、Android Studio でプロジェクトをビルドするために必要なファイルを作成します。
  3. [次へ] をクリックして、[新しいプロジェクト] ダイアログを開きます。
  4. プロジェクトを構成します。アプリ名、パッケージ名、ターゲット SDK を入力します。[Next] をクリックします。
  5. [Minimum required SDK] を API 24: Android 7.0(Nougat)に設定します。
  6. [完了] をクリックします。

Android Studio で新しいプロジェクトが開きます。

プロジェクトの構造

Android Studio によって作成された最初のプロジェクトには、アプリをセットアップするためのボイラープレート コードが含まれています。次のようなフォルダは特に重要です。

  • src/main/java。Android Java ソースコード。
  • src/main/res。アプリケーションで使用されるリソース。
  • src/main/res/drawable。アプリで使用される画像リソース。
  • src/main/res/xml。UI コンポーネントの構造を定義する XML レイアウト ファイル。
  • src/main/res/values。ディメンション、文字列、その他の値で、アプリケーションにハードコードしたくない値。
  • src/main/AndroidManifest.xml。マニフェスト ファイルは、アクティビティ、権限、テーマなど、アプリに含まれるものを定義します。

WebView を追加する

次に、メイン アクティビティのレイアウトに WebView を追加します。

  1. src/main/res/xml ディレクトリの activity_main.xml ファイルを開きます(まだ開いていない場合)。(fragment_main.xml ファイルが表示されることもあります。このチュートリアルでは不要なため、無視してください)。

    activity_main.xml エディタの下部にある [Text] タブを選択して、XML マークアップを表示します。

    このファイルはメイン アクティビティのレイアウトを定義します。[プレビュー] ペインには、アクティビティのプレビューが表示されます。[空のアクティビティ] レイアウトには子要素が含まれていません。WebView を追加する必要があります。

  2. XML ペインで、FrameLayout 要素の末尾からセルフクローズ スラッシュを削除し、<WebView> 要素と新しい終了タグを追加します。

    <FrameLayout xmlns:android="https://schemas.android.com/apk/res/android"
        xmlns:tools="https://schemas.android.com/tools"
        android:id="@+id/container"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        tools:context=".MainActivity">
        tools:ignore="MergeRootFrame">
    
        <WebView
          android:id="@+id/activity_main_webview"
          android:layout_width="match_parent"
          android:layout_height="match_parent" />
    </FrameLayout>
    
  3. WebView を使用するには、アクティビティで参照する必要があります。src/main/java/<PackageName> ディレクトリにあるメイン アクティビティの Java ソースファイル MainActivity.java を開きます。

    太字で示されている行を追加します。

    public class MainActivity extends Activity {
    
        private WebView mWebView;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            mWebView = (WebView) findViewById(R.id.activity_main_webview);
    

    onCreate メソッドの既存のコードは、アクティビティとレイアウトを接続する処理を行います。追加された行は、ウェブビューを参照する新しいメンバー変数 mWebView を作成します。

    次のコードを削除します。

    if (savedInstanceState == null) {
      getSupportFragmentManager().beginTransaction()
        .add(R.id.container, new PlaceholderFragment())
        .commit();
    }
    

    WebView はリソース ID で識別されます。この ID は、レイアウト ファイルの次の行で指定します。

    android:id="@+id/activity_main_webview"
    

    コードを追加すると、エディタの余白に警告メッセージが表示されます。これは、WebView に適切なクラスをインポートしていないためです。幸い、Android Studio では不足しているクラスを補充できます。最も簡単な方法は、不明なクラス名をクリックしてホバーし、モジュールに「クイック修正」が表示されるのを待つことです。この場合は、WebView クラスに import ステートメントを追加します。

    Alt+Enter(Mac の場合は Option+Enter)を押して、クイック修正を承認します。

    WebView を用意したら、セットアップして魅力的なウェブ コンテンツを読み込みましょう。

JavaScript を有効にする

WebView では、デフォルトで JavaScript が許可されていません。WebView でウェブ アプリケーションを実行するには、onCreate メソッドに次の行を追加して、JavaScript を明示的に有効にする必要があります。

// Enable Javascript
WebSettings webSettings = mWebView.getSettings();
webSettings.setJavaScriptEnabled(true);

リモート URL を読み込む

リモート URL からデータを読み込む場合は、インターネットにアクセスするための権限がアプリに必要です。この権限は、アプリのマニフェスト ファイルに追加する必要があります。

  1. src/res ディレクトリの AndroidManifest.xml ファイルを開きます。太字の行を閉じ </manifest> タグの前に追加します。

    <?xml version="1.0" encoding="utf-8"?>
    <manifest ...>
    ...
     
      </application>
      <uses-permission android:name="android.permission.INTERNET" />
    </manifest>
    
  2. 次のステップは、WebView で loadUrl メソッドを呼び出すことです。onCreate メソッドの末尾に次の行を追加します。

    mWebView.loadUrl("[https://beta.html5test.com/][8]");
    

    プロジェクトを実行してみてください。デバイスが手元にない場合は、[Tools] > [Android] > [AVD Manager] に移動して、エミュレータ(AVD、Android Virtual Device)を作成できます。

ナビゲーションを処理する

読み込む URL を https://www.css-tricks.com/ に変更して、アプリを再実行してみてください。何かおかしげな物が見つかりました。

css-tricks.com などのリダイレクトがあるサイトを使用してアプリケーションを実行すると、アプリは WebView ではなく、デバイス上のブラウザでサイトを開きます。これは想定どおりではありません。これは、WebView がナビゲーション イベントを処理する方法によるものです。

イベントの順序は次のとおりです。

  1. WebView はリモート サーバーから元の URL を読み込もうとして、新しい URL へのリダイレクトを取得します。
  2. WebView は、システムが URL のビュー インテントを処理できるかどうかを確認します。可能であれば、システムが URL ナビゲーションを処理します。そうでない場合は、WebView が内部でナビゲートします(たとえば、ユーザーのデバイスにブラウザがインストールされていない場合など)。
  3. https:// URL スキームを処理するユーザーの優先アプリ(ユーザーのデフォルト ブラウザ)が選択されます。複数のブラウザがインストールされている場合は、この時点でダイアログが表示されることがあります。

Android アプリ内で WebView を使用してコンテンツ(ヘルプページなど)を表示する場合は、これがまさに目的の動作です。ただし、より高度なアプリの場合は、ナビゲーション リンクを自分で処理することをおすすめします。

WebView 内のナビゲーションを処理するには、WebView によって生成されたさまざまなイベントを処理する WebView の WebViewClient をオーバーライドする必要があります。これを使用して、WebView がリンクのクリックとページのリダイレクトを処理する方法を制御できます。

WebViewClient のデフォルト実装では、WebView で任意の URL を開くことができます。

// Force links and redirects to open in the WebView instead of in a browser
mWebView.setWebViewClient(new WebViewClient());

これは良い進歩ですが、サイトのリンクのみを処理し、他の URL はブラウザで開きたい場合はどうすればよいでしょうか。

そのためには、WebViewClient クラスを拡張して shouldOverrideUrlLoading メソッドを実装する必要があります。このメソッドは、WebView が別の URL に移動しようとするたびに呼び出されます。false が返された場合、WebView は URL 自体を開きます。(デフォルトの実装は常に false を返します。そのため、前の例で機能します)。

新しいクラスを作成します。

  1. アプリのパッケージ名を右クリックし、[新規] > [Java クラス] を選択します。
  2. クラス名として「MyAppWebViewClient」と入力し、[OK] をクリックします。
  3. 新しい MyAppWebViewClient.java ファイルに、次のコードを追加します(変更点は太字で示されています)。

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().endsWith("css-tricks.com")) {
          return false;
        }
                   
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

    新しいコードでは、MyAppWebViewClientWebViewClient のサブクラスとして定義し、shouldOverrideUrlLoading メソッドを実装します。

    shouldOverrideUrlLoading メソッドは、WebView が URL を読み込む直前に呼び出されます。この実装では、URL のホスト名の末尾に「css-tricks.com」という文字列が含まれているかを確認します。文字列が存在する場合、メソッドは false を返します。これは、URL をオーバーライドしないで、WebView に読み込むようにプラットフォームに指示します。

    他のホスト名の場合は、このメソッドは URL を開くようシステムにリクエストします。これは、新しい Android インテントを作成し、それを使用して新しいアクティビティを起動することで行われます。メソッドの最後に true を返すと、URL が WebView に読み込まれなくなります。

  4. 新しいカスタム WebViewClient を使用するには、MainActivity クラスに次の行を追加します。

    // Stop local links and redirects from opening in browser instead of WebView
    mWebView.setWebViewClient(new MyAppWebViewClient());
    

    これで、ユーザーは CSS Tricks のリンクをクリックしてもアプリ内から離れず、外部サイトへのリンクはブラウザで開くことができます。

Android の戻るボタンを処理する

CSS Tricks の記事を操作して移動し始めると、Android の戻るボタンをクリックするとアプリが終了します。

WebView メソッド canGoBack は、ページスタックにポップできるものがないかを通知します。戻るボタンの押下を検出して、WebView の履歴を遡るべきか、プラットフォームに正しい動作を判断させるかを判断するには、MainActivityonBackPressed() メソッドを追加します。

public class MainActivity extends Activity {

 private WebView mWebView;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
     ...
 }

    @Override
    public void onBackPressed() {
      if(mWebView.canGoBack()) {
        mWebView.goBack();
      } else {
        super.onBackPressed();
      }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
       ...
    }
}

ファイル システムから HTML を読み込む

インストール可能なアプリ内で WebView を使用する大きなメリットの 1 つは、アプリ内にアセットを保存できることです。これにより、アプリをオフラインで動作させることができ、WebView がローカル ファイル システムからアセットを直接取得できるため、読み込み時間が短縮されます。

HTML、JavaScript、CSS などのファイルをローカルに保存するには、assets ディレクトリに保存します。これは、Android が未加工ファイルに使用する予約済みディレクトリです。特定のファイルを最小化または圧縮する必要があるため、アプリはこのディレクトリにアクセスする必要があります。

  1. main(src/main/assets/www)に assets/www ディレクトリを作成します。

    • ウェブファイルは /assets のサブディレクトリに保存することをおすすめします。
  2. すべてのファイルをディレクトリにアップロードします。

  3. 適切なファイルを読み込みます。

    mWebView.loadUrl("file:///android_asset/www/index.html");
    
  4. shouldOverrideUrlLoading メソッドを更新して、ローカル以外のページのブラウザを開きます。

    public class MyAppWebViewClient extends WebViewClient {
      @Override
      public boolean shouldOverrideUrlLoading(WebView view, String url) {
        if(Uri.parse(url).getHost().length() == 0) {
          return false;
        }
    
        Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));
        view.getContext().startActivity(intent);
        return true;
      }
    }
    

これで、優れた WebView アプリを作成できるようになりました。

ビジュアルを適切に表示するヒントについては、WebView の Pixel-Perfect UI をご覧ください。

問題が発生した場合は、Chrome デベロッパー ツールが役に立ちます。利用を開始するには、Android でのリモート デバッグをご覧ください。