Android Oreo

Android Oreo(Android 8.0 API 26)

Android 8.0的别名:曲奇饼干

1.Android 8.0的新特性


Android 8.0 是全新版本,它优化了电源及性能,并提供了多种全新方式来扩展您的应用

  • 通知
  • 自动填充框架
  • 画中画模式
  • 自适应图标
  • 自动调整 TextView 的大小
  • WebView API
    Android 8.0新特性远远不只以上这些,想了解更多,请点击“Android 8.0 功能和 API

2.WebView API


本编文章主要围绕WebView的新特性展开介绍,要想了解其他的特性的详细介绍,请点击以上的“Android 8.0 功能和API”的介绍。

好了,经过简短的铺垫之后,正式进入到正题——WebView API

Android 8.0 提供多种 API,帮助您管理在应用中显示网页内容的 WebView 对象。这些 API 可增强应用的稳定性和安全性,它们包括:

  • Version API
  • Google SafeBrowsing API
  • Termination Handle API
  • Renderer Importance API

下面将Android 8.0针对WebView提供的多种API进行介绍:
Managing WebViews (WebViews 管理)
Android提供了几个API来帮助您管理在您的应用中显示Web内容的WebView对象。
本页介绍如何使用这些API更有效地处理WebView对象,从而提高应用程序的稳定性和安全性。
(1)Version API
从Android 7.0(API级别24)开始,用户可以选择几个不同的包来显示WebView对象中的Web内容。 Android 8.0(API级别26)及更高版本包含一个API,用于获取与在应用中显示Web内容的包相关的信息。此API在分析仅在您的应用尝试使用特定包的WebView实现显示Web内容时发生的错误时特别有用。
要使用此API,请添加以下代码片段中显示的逻辑:

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

注意:如果设备没有正确设置,则WebView.getCurrentWebViewPackage()方法可以返回null。如果您在不支持WebView的设备上运行应用(例如Android Wear设备),它也会返回null。
(2)Google Safe Browsing API(Google安全浏览API)
为了向用户提供更安全的浏览体验,您可以配置应用的WebView对象以使用Google安全浏览来验证网址。启用此安全措施后,您的应用会在用户尝试导航到可能不安全的网站时向用户显示警告。
要选择加入您的WebView对象来检查针对Google安全浏览的不安全网站列表的URL,请将以下元素添加到您应用的清单文件中:

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

(3)Defining programmatic actions(行为程序化的定义)
当WebView实例尝试加载Google分类为已知威胁的页面时,默认情况下,WebView将显示一个插页式广告,用于警告用户已知的威胁。该屏幕允许用户选择加载URL,或返回到安全的上一页。
如果您的目标是Android 8.1(API等级27)或更高,您可以通过编程定义您的应用程序如何响应已知的威胁:

  • 您可以控制您的应用是否将已知威胁报告给安全浏览。
  • 您可以让您的应用程序自动执行特定的操作(例如回到安全状态),每次遇到归类为已知威胁的URL。

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

    以下代码片段显示了如何指示应用程序的WebView实例在遇到已知威胁后始终返回安全状态:
    MyWebActivity.java:

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!");
            }
        }
    });
}

MyWebViewClient.java:

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();
    }
}

(4)Termination Handle API(中止处理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;
    }
}

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

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

在这个特定片段中,渲染器的优先级与应用程序的默认优先级相同(或“绑定到”)。当关联的WebView对象不再可见时,true参数将渲染器的优先级降低到RENDERER_PRIORITY_WAIVED。换句话说,一个真实的参数表明你的应用程序不关心系统是否让渲染器进程保持活动状态。事实上,这个较低的优先级使得渲染器进程可能在内存不足的情况下死亡。
警告:为保持应用程序的稳定性,除非您还使用Termination Handle API来指定WebView在其关联的呈现器消失时如何作出反应,否则不应更改WebView对象的呈现器优先级策略。
要详细了解系统如何处理内存不足的情况,请参阅进程和应用程序生命周期( Processes and Application Life Cycle)。


以下是“Processes and Application Life Cycle”文章的翻译

在大多数情况下,每个Android应用程序都在其自己的Linux进程中运行。当需要运行某些代码时,会为应用程序创建此进程,并且该进程将保持运行状态,直到不再需要它为止,并且系统需要回收其内存供其他应用程序使用。
Android的一个不寻常的基本特征是应用程序的生命周期不是由应用程序本身直接控制的。相反,它是由系统通过将系统知道正在运行的应用程序的各个部分,这些东西对用户的重要程度以及系统中可用的整体内存的组合来确定的。
应用程序开发人员了解不同应用程序组件(特别是Activity,Service和BroadcastReceiver)是如何影响应用程序进程的生命周期非常重要。如果不正确使用这些组件,可能会导致系统在执行重要工作的同时终止应用程序的进程。
流程生命周期错误的一个常见示例是BroadcastReceiver,它在其BroadcastReceiver.onReceive()方法中接收到Intent时启动线程,然后从该函数返回。一旦它返回,系统将认为BroadcastReceiver不再处于活动状态,因此,不再需要其宿主进程(除非其他应用程序组件处于活动状态)。因此,系统可能会随时终止进程以回收内存,并且这样做会终止进程中运行的衍生线程。此问题的解决方案通常是安排来自BroadcastReceiver的JobService,以便系统知道进程中仍有活动正在进行。
要确定哪些进程在内存不足时应该被终止,Android会根据其中运行的组件以及这些组件的状态将每个进程置于“重要性层次结构”中。这些流程类型(按重要性排序):

1.前台进程是用户目前正在做的事情所需要的进程。各种应用程序组件可以使其包含的过程以不同的方式被视为前景。如果满足以下任何条件,则认为过程处于前景中:

  • 它在用户正在与之交互的屏幕顶部运行一个Activity(其onResume()方法已被调用)。
  • 它有一个当前正在运行的BroadcastReceiver(它的BroadcastReceiver.onReceive()方法正在执行)。
  • 它有一个服务当前正在其回调(Service.onCreate(),Service.onStart()或Service.onDestroy())中执行代码。

系统中只会有一些这样的进程,如果内存太低,甚至这些进程无法继续运行,这些进程只会作为最后的手段被杀死。通常,此时设备已达到内存分页状态,因此需要执行此操作以保持用户界面的响应。

2.一个可见的过程正在做用户当前意识到的工作,所以杀死它会对用户体验产生显着的负面影响。在下列情况下,流程被视为可见:

  • 它正在屏幕上运行一个对用户可见的Activity,但不在前台(它的onPause()方法已被调用)。例如,如果前景活动显示为允许在其后面看到先前活动的对话框,则可能发生这种情况。
  • 它有一个作为前台服务运行的服务,通过Service.startForeground()(这是要求系统将服务视为用户知道的事情,或者对他们来说基本可见)。
  • 它正在托管系统正在使用的用于用户知晓的特定功能的服务,例如动态壁纸,输入法服务等。

在系统中运行的这些进程的数量比前台进程的限制更少,但仍然相对受控。这些进程被认为是非常重要的,并且不会被杀死,除非需要这样做才能保持所有前台进程运行。

3.服务进程是一个持有已使用startService()方法启动的服务的进程。虽然这些过程对用户来说不是直接可见的,但他们通常在做用户关心的事情(如后台网络数据上传或下载),所以除非没有足够的内存来保存所有内容前景和可见过程。

长时间运行(例如30分钟或更长时间)的服务可能被降级为重要的,以允许它们的进程下降到下面描述的缓存的LRU列表。这有助于避免长时间运行的服务出现内存泄漏或其他问题会消耗大量内存,导致系统无法有效使用缓存进程。

4.高速缓存的进程是当前不需要的进程,因此当其他地方需要内存时,系统可以根据需要自由地终止进程。在正常运行的系统中,这些是内存管理中唯一涉及的过程:运行良好的系统将始终有多个高速缓存的进程可用(以便在应用程序之间进行更高效的切换),并根据需要定期清除最旧的进程。只有在非常危急的情况下(也就是不希望出现的情况),系统才能达到所有高速缓存进程都被终止的程度,并且它必须开始查杀服务进程。

这些进程通常保存一个或多个用户当前不可见的Activity实例(onStop()方法已被调用并返回)。如果他们正确地实施他们的活动生命周期(请参阅活动以获取更多详细信息),那么当系统终止此类流程时,它不会影响用户在返回到该应用程序时的体验:当相关活动重新创建时,它可以恢复先前保存的状态一个新的过程。

这些进程保存在一个伪LRU列表中,列表中的最后一个进程首先被杀死以回收内存。在此列表中排序的确切策略是平台的实现细节,但通常它会尝试在其他类型的进程之前保留更多有用的进程(一个托管用户的home应用程序,他们看到的最后一个活动等)。还可以应用其他杀死进程的策略:对所允许的进程数量进行严格限制,限制进程可以连续缓存的时间量等。

在决定如何对流程进行分类时,系统将根据在流程中当前活跃的所有组件中找到的最重要级别来决定其决策。请参阅Activity,Service和BroadcastReceiver文档,以获取有关每个组件如何影响流程整个生命周期的更多详细信息。每个类的文档都会更详细地描述它们如何影响其应用程序的整个生命周期。

流程的优先级也可以基于流程对其的其他依赖性来增加。例如,如果流程A通过Context.BIND_AUTO_CREATE标志绑定到服务,或者正在流程B中使用ContentProvider,那么流程B的分类至少与流程A一样重要。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值