管理WebView对象(三)

Android提供了几个API来帮助您管理在应用程序中显示Web内容的WebView对象。

本页介绍如何使用这些API更有效地使用WebView对象,从而提高应用程序的稳定性安全性

一、版本API

Android 7.0(API级别24)开始,用户可以在几个不同的包中进行选择,以便在WebView对象中显示Web内容。 Android 8.0(API级别26)及更高版本包含一个API,用于获取与在您的应用中显示Web内容的包相关的信息。 在分析仅在您的应用尝试使用特定包的WebView实现显示Web内容时发生的错误时,此API特别有用。

要使用此API,请添加以下代码段中显示的逻辑:

PackageInfo webViewPackageInfo = WebView.getCurrentWebViewPackage();
Log.d("MY_APP_TAG", "WebView version: " + webViewPackageInfo.versionName);

注意:如果尚未正确设置设备,则WebView.getCurrentWebViewPackage()方法可以返回null。 如果您在不支持WebView的设备上运行应用程序(例如Wear OS设备),它也会返回null

二、Google安全浏览API

为了向您的用户提供更安全的浏览体验,您的WebView对象使用Google安全浏览功能验证网址,这样您的应用就可以在用户尝试导航到可能不安全的网站时向用户显示警告。

虽然EnableSafeBrowsing的默认值为true,但偶尔会出现您可能只想有条件地启用安全浏览或禁用安全浏览的情况。Android 8.0(API级别26)以及使用setSafeBrowsingEnabled()的更高支持。 在较低API级别编译的应用程序无法使用setSafeBrowsingEnabled(),并且应将清单中的EnableSafeBrowsing值更改为false以禁用所有WebView实例的功能。

如果您的应用针对Android 7.1(API级别25)或更低版本,则可以通过将以下<meta-data>元素添加到应用的清单文件中来选择WebView对象,而无需检查针对Google Safe Browsing的不安全网站列表的URL

<manifest>
    <application>
        <meta-data android:name="android.webkit.WebView.EnableSafeBrowsing"
                   android:value="false" />
        ...
    </application>
</manifest>
定义程序化操作

WebView实例尝试加载已被Google归类为已知威胁的页面时,默认情况下WebView会显示一个插页式广告,警告用户已知威胁。 此屏幕为用户提供了加载URL或者返回上一页安全的选项。

如果您定位到Android 8.1(API级别27)或更高级别,则可以通过编程方式定义应用程序如何响应已知威胁:

  • 您可以控制应用是否报告安全浏览的已知威胁。
  • 您可以让您的应用自动执行特定操作 - 例如回到安全状态 - 每次遇到被归类为已知威胁的网址时。

注意:为了获得针对已知威胁的最佳保护,请等到您在调用WebView对象的loadUrl()方法之前初始化安全浏览。

以下代码段显示了如何在遇到已知威胁后指示应用程序的WebView实例始终恢复安全:

private WebView mSuperSafeWebView;
private boolean mSafeBrowsingIsInitialized;

// ...

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    mSuperSafeWebView = new WebView(this);
    mSuperSafeWebView.setWebViewClient(new MyWebViewClient());
    mSafeBrowsingIsInitialized = false;

    mSuperSafeWebView.startSafeBrowsing(this, new ValueCallback<Boolean>() {
        @Override
        public void onReceiveValue(Boolean success) {
            mSafeBrowsingIsInitialized = true;
            if (!success) {
                Log.e("MY_APP_TAG", "Unable to initialize Safe Browsing!");
            }
        }
    });
}


public class MyWebViewClient extends WebViewClient {
    // Automatically go "back to safety" when attempting to load a website that
    // Google has identified as a known threat. An instance of WebView calls
    // this method only after Safe Browsing is initialized, so there's no
    // conditional logic needed here.
    @Override
    public void onSafeBrowsingHit(WebView view, WebResourceRequest request,
            int threatType, SafeBrowsingResponse callback) {
        // The "true" argument indicates that your app reports incidents like
        // this one to Safe Browsing.
        callback.backToSafety(true);
        Toast.makeText(view.getContext(), "Unsafe web page blocked.",
                Toast.LENGTH_LONG).show();
    }
}

三、HTML5地理位置API

对于定位到Android 6.0(API级别23)及更高版本的应用,仅在安全来源(例如HTTPS)上支持Geolocation API。 在不调用相应的onGeolocationPermissionsShowPrompt()方法的情况下,将自动拒绝对非安全源上的Geolocation API的任何请求。

四、选择退出指标收集

当用户同意时,WebView可以将匿名诊断数据上传到Google。 对于已实例化WebView的每个应用程序,基于每个应用程序收集数据。 您可以通过在清单的<application>元素中创建以下标记来选择退出此功能:

<manifest>
    <application>
    ...
    <meta-data android:name="android.webkit.WebView.MetricsOptOut"
               android:value="true" />
    </application>
</manifest>

只有在用户同意并且应用尚未选择退出的情况下,才会从应用上传数据。

五、终止处理API

API处理WebView对象的渲染器进程消失的情况,因为系统终止了渲染器以回收急需的内存,或者因为渲染器进程本身崩溃。 通过使用此API,即使呈现器进程已消失,您也可以继续执行应用程序。

警告:如果您的应用程序在渲染器进程消失后继续执行,则无论渲染器进程是否被终止或崩溃,都无法重用关联的WebView实例。 您的应用必须从视图层次结构中删除该实例并销毁该实例以继续执行。 然后,您的应用必须创建一个全新的WebView实例才能继续呈现网页。

请注意,如果渲染器在加载特定网页时崩溃,则尝试再次加载同一页面可能会导致新的WebView对象显示相同的渲染崩溃行为。

以下代码段说明了如何使用此API

public class MyRendererTrackingWebViewClient extends WebViewClient {
    private WebView mWebView;

    @Override
    public boolean onRenderProcessGone(WebView view,
            RenderProcessGoneDetail detail) {
        if (!detail.didCrash()) {
            // Renderer was killed because the system ran out of memory.
            // The app can recover gracefully by creating a new WebView instance
            // in the foreground.
            Log.e("MY_APP_TAG", "System killed the WebView rendering process " +
                    "to reclaim memory. Recreating...");

            if (mWebView != null) {
                ViewGroup webViewContainer =
                        (ViewGroup) findViewById(R.id.my_web_view_container);
                webViewContainer.removeView(mWebView);
                mWebView.destroy();
                mWebView = null;
            }

            // By this point, the instance variable "mWebView" is guaranteed
            // to be null, so it's safe to reinitialize it.

            return true; // The app continues executing.
        }

        // Renderer crashed because of an internal error, such as a memory
        // access violation.
        Log.e("MY_APP_TAG", "The WebView rendering process crashed!");

        // In this example, the app itself crashes after detecting that the
        // renderer crashed. If you choose to handle the crash more gracefully
        // and allow your app to continue executing, you should 1) destroy the
        // current WebView instance, 2) specify logic for how the app can
        // continue executing, and 3) return "true" instead.
        return false;
    }
}

六、渲染器重要性API

现在WebView对象在多进程模式下运行,您可以灵活地处理应用程序处理内存不足的情况。 您可以使用Android 8.0中引入的Renderer重要性API为分配给特定WebView对象的渲染器设置优先级策略。 特别是,当显示应用程序的WebView对象的渲染器被终止时,您可能希望应用程序的主要部分继续执行。 例如,如果您希望不长时间显示WebView对象,以便系统可以回收渲染器正在使用的内存,则可以执行此操作。
以下代码段显示如何为与应用程序的WebView对象关联的呈现器进程分配优先级:

WebView myWebView;
myWebView.setRendererPriorityPolicy(RENDERER_PRIORITY_BOUND, true);

在此特定代码段中,渲染器的优先级与应用程序的默认优先级相同(或“绑定到”)。 当关联的WebView对象不再可见时,true参数会将渲染器的优先级降低为RENDERER_PRIORITY_WAIVED。 换句话说,true参数表示您的应用程序不关心系统是否使渲染器进程保持活动状态。 事实上,这种较低的优先级使得渲染器进程很可能在内存不足的情况下被终止。

警告:为了保持应用程序稳定性,您不应更改WebView对象的呈现器优先级策略,除非您还使用终止句柄API来指定WebView在关联的呈现器消失时的反应方式。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,128评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,316评论 3 388
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 159,737评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,283评论 1 287
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,384评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,458评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,467评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,251评论 0 269
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,688评论 1 306
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,980评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,155评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,818评论 4 337
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,492评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,142评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,382评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,020评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,044评论 2 352

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,094评论 1 32
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 1.ios高性能编程 (1).内层 最小的内层平均值和峰值(2).耗电量 高效的算法和数据结构(3).初始化时...
    欧辰_OSR阅读 29,353评论 8 265
  • 作者 姜苏 37 小裴听大头们说得那么起劲,问大嫂:“你和他们也是一个小学的吧?那到底他们说的是谁呢?” “你指的...
    姜苏阅读 231评论 0 0
  • “喂,我刚下飞机!嗯嗯,西三出口,知道了!赶紧的吧,好了先这样吧!挂了啊!”苏皓抿了抿嘴,将手机塞进口袋,拉着行李...
    红烧东坡肉阅读 334评论 0 1