LoginSignup
71
63

More than 5 years have passed since last update.

Android 7.0でChromeがWebViewを提供するようになった仕組み

Last updated at Posted at 2016-10-07

Android 7.0からはChromeがWebViewを提供する みたいのはあちこちでバズってる割に、中身の仕組みをちゃんと書いた記事は殆ど見ません。
個人的にはとても残念に思います。

ということで、中を見てみました。

まずは、Lollipopまでのおさらい

WebViewのAPIを提供するのが、WebViewFactoryProviderで、
WebViewFactory::getProvider のなかで

  • ネイティブ側の準備:libwebviewchromium.soの探索とロード
    • パッケージ名はgetWebViewPackageName()で取得
  • Java API側の準備:WebviewProviderの生成と初期化
    • WebViewChromiumFactoryProviderが内部でWebViewDelegateを実装する

みたいな流れの処理があります。

ソースレベルで見たければこのへん。

ポイントとしては、端末ベンダーが R.string.config_webViewPackageName をオーバーライドして、
デフォルトは com.android.webview を見にいくのを、ねじ曲げることができるようになっています。

frameworks/base/core/java/android/webkit/WebViewFactory.java
public static String getWebViewPackageName() {
    return AppGlobals.getInitialApplication().getString(
            com.android.internal.R.string.config_webViewPackageName);
}

Marshmallowでどうなった?

AOSPからChromium WebViewのソースが削除されただけで、WebViewのロード自体は同じような仕組みで動いています。

この時期くらいからGoogleがChromeでWebView機能提供することを考え始めたのか、
ネイティブのパスがLollipopでは libwebviewchromium.so ってハードコーディングされてたのが、Marshmallowでは パッケージの meta(com.android.webview.WebViewLibrary)を見るように変わってたりはします。

  

で、Nougatでどう変わった?

結論から言うと、WebViewロードの仕組みは殆ど変わってません。設定の仕組みが追加されただけでした。

NougatではWebViewを提供するパッケージを開発者向けオプションで設定することができます。
ということは、システム設定に持ってるんですね。そこから辿ってみます。

frameworks/base/core/java/android/provider/Settings.java
public static final String ACTION_WEBVIEW_SETTINGS = "android.settings.WEBVIEW_SETTINGS";

なんと、Settings.javaに設定名ではなくて、インテントのアクションの定義が・・・。

設定画面の実装はどこにあるか辿ってみると、

ここです。

    mWebViewUpdateService  =
            IWebViewUpdateService.Stub.asInterface(ServiceManager.getService("webviewupdate"));
    try {
        WebViewProviderInfo[] providers = mWebViewUpdateService.getValidWebViewPackages();
        if (providers == null) {
            Log.e(TAG, "No WebView providers available");
            finish();
            return;
        }

        String currentValue = mWebViewUpdateService.getCurrentWebViewPackageName();
        if (currentValue == null) {
            currentValue = "";
        }

WebViewの機能を提供するパッケージを探索
 ↓
ダイアログ表示
 ↓
Settings.Global.WEBVIEW_PROVIDER の設定値を更新
 ↓
WebViewFactory.onWebViewProviderChanged()

という流れです。
NougatではWebViewを提供するパッケージを設定できる仕組みが加わっただけで、WebViewの初期化部分とかって、Lollipopのときと大きくは変わってないんですね。

もしかすると、Marshmallowでも最近のChromeをプリインストールして、'R.string.config_webViewPackageName' を com.google.android.chrome にして端末を焼けば、NougatみたいにChromeがWebViewを提供するようにできたりするんじゃないかなー、と・・・。(未検証ですw)

ソースレベルで見たければこのへん。

 

ちなみに開発者向けオプションで変えない場合はどう動作してるの?というと、
http://tools.oesf.biz/android-7.0.0_r1.0/xref/frameworks/base/core/res/res/xml/config_webview_packages.xml
このXMLがWebViewUpdateService起動時に読まれて、適切なWebViewがロードされるようになってます。
このXMLは端末ベンダーがオーバーライド可能なので、NexusではAndroid WebViewではなくChromeが指定されてるというがあります。

 

まとめ

NougatではWebViewのProviderを設定できる実装が入っただけで、
WebView実装を含んだAPKを選択的にロードする処理はLollipopからほとんど変わっていませんでした。

 
完全に余談ですが、
らくらくホン みたいに、今まではOSレベルで魔改造が必要だったWebViewも、今後はAPK載せてconfig変えるだけで動くようになるのはいい仕組みですね。万が一バグっててもGoogle Playアップデートもできるし。

71
63
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
71
63