
こんにちは。開発部第 1 グループの坪倉です。
Android アプリで Web ページを表示する手段は、大きく分けて次の 3 つがあります。
- WebView:アプリ内に Web ページを埋め込む
- Custom Tabs:ブラウザが提供する「アプリ内ブラウザ」を呼び出す
- 外部ブラウザ:Chrome などのブラウザを起動して URL を渡す
なお Compose で WebView を使う場合は AndroidView で包む必要があります。Custom Tabs と外部ブラウザは Compose でも同じコードで使えます。
仕様を決めるときに「どれを使えばいいんだっけ?」と迷いやすい部分なので、3 つの違いと使い分けの目安をまとめました。
背景
WebView、Custom Tabs、外部ブラウザは、それぞれユーザー体験や対応端末、実装コストなどが大きく異なります。 特に Custom Tabs は対応ブラウザや OS バージョン、端末によって挙動が変わることがあるため、案件によっては採用しづらいケースもあります。
比較表
ユーザー体験
| 観点 | WebView | Custom Tabs | 外部ブラウザ |
|---|---|---|---|
| 見た目 | 完全にアプリの中 | アプリ内に近い体験 | ブラウザに遷移 |
| ブラウザのログイン共有 | 共有しない | 共有する | 共有する |
| アプリへの戻り | 自然(同じ画面内) | 戻る操作でアプリへ戻れる | 別途導線が必要 |
| UI のカスタマイズ | 自由 | 限定的(色・メニュー程度) | 不可 |
実装・運用
| 観点 | WebView | Custom Tabs | 外部ブラウザ |
|---|---|---|---|
| 実装コスト | 表示だけなら低、本格運用は高(履歴・エラー・Cookie・ダウンロード等を自前で扱う) | 低 | 最低 |
| 追加依存 | なし | androidx.browser:browser |
なし |
| セキュリティ更新 | WebView 本体の更新に依存 | 既定ブラウザの更新で追従 | 既定ブラウザの更新で追従 |
| OAuth / OIDC のログイン | 非推奨 | 推奨 | 推奨 |
各方式の特徴
WebView
- アプリ内の HTML 表示に最適。ヘルプ、利用規約、キャンペーンページなど、自社で完全に制御したいページ向き。
- ブラウザのログイン状態は引き継げないため、ユーザーは再ログインが必要になりがち。
- セキュリティを自前で担保する必要がある。特に
addJavascriptInterface(JS から Java/Kotlin を呼べる仕組み)は過去に脆弱性の温床になった経緯があるため、信頼できるページ(自社管理のページなど)でだけ使う。 - ネイティブと Web を密に連携させたい場合は WebView が向いている。
val webView = WebView(context).apply { settings.javaScriptEnabled = true webViewClient = WebViewClient() } webView.loadUrl("<https://example.com>")

Custom Tabs
- ブラウザが提供する「アプリ内ブラウザ」を呼び出す。見た目はアプリ内遷移に近く、戻る操作で元のアプリに戻れる。
- ブラウザのログイン状態・保存パスワード・自動入力をそのまま使える。
- ツールバーの色、閉じるボタンのアイコン、開始・終了アニメ、メニュー項目の追加など、UI のカスタマイズが可能。一方で、フィッシング防止のため URL バーは消せないといった制約もある。
- 使えるカスタマイズ API は
androidx.browserのバージョンや、ユーザーが使うブラウザ(Chrome / Edge / Samsung Internet / Firefox など)の実装によって差があるため、装飾は 「できなくても困らない範囲」に留めておく のが安全。
CustomTabsIntent.Builder()
.setShowTitle(true)
.build()
.launchUrl(context, "<https://example.com>".toUri())

外部ブラウザ
- 実装が最もシンプル(Intent を投げるだけ)。
- 決済、銀行、行政サイトなど、ユーザー自身のブラウザで開かせたい ページに向いている。技術的には Custom Tabs でも動くことが多いが、URL バーを全表示できるため信頼感を出しやすい。
- アプリから離脱するため、戻ってこない前提で後続フローを設計する。
startActivity(Intent(Intent.ACTION_VIEW, "<https://example.com>".toUri()))

なぜ OAuth / OIDC で WebView を避けるのか
ログイン画面に WebView を使うと、次の 2 つの問題があります。
- ポリシー違反になる:Google や Microsoft などの主要 ID プロバイダは、embedded WebView での OAuth ログインを規約で禁止している。技術的に動かせるケースがあっても、規約違反であり、将来の仕様変更で動かなくなるリスクがある。
- フィッシングのリスク:WebView はアプリ側から自由に JS を流し込めるため、ユーザーが入力したパスワードを抜き取れてしまう。さらにアドレスバーが無いので、ユーザーは本物のログイン画面か確認できない。
Custom Tabs はブラウザの UI ごと呼び出すので、URL も確認でき、ログイン状態もそのまま使えます。OAuth / OIDC の認証画面は Custom Tabs を使うのが基本です。
注意点
3 方式とも、OS バージョンや端末・既定ブラウザの違いで見た目や挙動が変わります。
- WebView は本体のバージョンや端末メーカーのカスタマイズで、フォントやスクロール、ダークモードの効き方が変わる。
- Custom Tabs はツールバーやメニューがブラウザごとに異なる。また、Custom Tabs 非対応のブラウザしか入っていない端末では外部ブラウザを起動した場合と同じ挙動になり、ログイン状態の共有や戻り動線が想定通りにならないことがある。
- 外部ブラウザは既定ブラウザの仕様にそのまま依存する。
端末やブラウザによって見た目の細部は変わるため、「機能が使えるか」「導線がつながっているか」を基準に仕様を決める と運用しやすくなります。
おすすめ
仕様を決めるときの参考に、よくあるアプリ機能と推奨パターンをまとめました。
| 機能 / 画面 | 使うもの |
|---|---|
| ヘルプ・FAQ・利用規約など(自社管理のページ) | WebView |
| アプリ内キャンペーン・チュートリアル | WebView |
| お知らせや外部記事へのリンク | Custom Tabs |
| パスワード再設定 | Custom Tabs |
| OAuth ログイン(Google / Apple など) | Custom Tabs |
| クレジットカード決済 | Custom Tabs / 外部ブラウザ |
| 銀行・行政(マイナポータル等) | 外部ブラウザ |
まとめ
Web ページを開く手段には WebView / Custom Tabs / 外部ブラウザの 3 つがあり、それぞれユーザー体験や対応環境、実装コストが大きく異なります。 要件に合わせて選び分けが必要なので、仕様を決める段階で「どれを使うか」「対応端末で想定通りに動くか」を意識しておくと、後からの作り直しを防げます。