AndroidのWebViewでBASIC認証ダイアログを表示する

プログラミング

普段はインフラ系のタスクが多く、スクリプトを組む場合もPerlやRubyが中心ですが、知識の幅を広げるためにJavaでのAndroidアプリ開発も試しています。

WebViewでBASIC認証をする際に、ダイアログを表示してユーザー入力を受け付ける方法の情報を探すのに手間取ったのでメモします。

処理の流れ

  1. getHttpAuthUsernamePassword で保存済みのID/PWを取得
  2. 保存済みの認証情報があればそのまま proceed で認証
  3. なければダイアログを表示して入力→ setHttpAuthUsernamePassword で保存

handler.useHttpAuthUsernamePassword は、次ページ以降で認証を継続するために必要です。これを書いておかないとページ遷移のたびに認証ダイアログが出てしまいます。

実装

private class MyWebClient extends WebViewClient {
  @Override
  public void onReceivedHttpAuthRequest(WebView view,
      final HttpAuthHandler handler, final String host, final String realm) {

    String userName = null;
    String userPass = null;

    if (handler.useHttpAuthUsernamePassword() && view \!= null) {
      String[] haup = view.getHttpAuthUsernamePassword(host, realm);
      if (haup \!= null && haup.length == 2) {
        userName = haup[0];
        userPass = haup[1];
      }
    }

    if (userName \!= null && userPass \!= null) {
      handler.proceed(userName, userPass);
    } else {
      showHttpAuthDialog(handler, host, realm, null, null, null);
    }
  }
}


private void showHttpAuthDialog(final HttpAuthHandler handler,
          final String host, final String realm, final String title,
          final String name, final String password) {

  LayoutInflater factory = LayoutInflater.from(activity);
  final View textEntryView = factory.inflate(
      R.layout.basicauth_entry, null);

  mHttpAuthDialog = new AlertDialog.Builder(activity);
  mHttpAuthDialog.setTitle("Enter the password")
    .setView(textEntryView)
    .setCancelable(false);
  mHttpAuthDialog.setPositiveButton("OK", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
      EditText etUserName = (EditText) textEntryView.findViewById(R.id.username_edit);
      String userName = etUserName.getText().toString();
      EditText etUserPass = (EditText) textEntryView.findViewById(R.id.password_edit);
      String userPass = etUserPass.getText().toString();

      webview.setHttpAuthUsernamePassword(host, realm, userName, userPass);

      handler.proceed(userName, userPass);
      mHttpAuthDialog = null;
    }
  });
  mHttpAuthDialog.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
    public void onClick(DialogInterface dialog, int whichButton) {
      handler.cancel();
      mHttpAuthDialog = null;
    }
  });

  mHttpAuthDialog.create().show();
}

ハマった点

HttpAuthHandlerproceed()cancel() のいずれかで認証リクエストを完了させる必要があります。cancel() を呼ばないと、認証失敗時にダイアログが1回しか表示されない状態になります。リファレンスをよく読めば書いてあるのですが、最初気づかずハマりました。

Related Posts