如何从不在 Android 的 API 26 上的 WebView 获取 WebviewClient 实例?

Posted

技术标签:

【中文标题】如何从不在 Android 的 API 26 上的 WebView 获取 WebviewClient 实例?【英文标题】:How to get WebviewClient instance from WebView not on API 26 in Android? 【发布时间】:2018-04-11 12:25:06 【问题描述】:

我正在开发适用于 android 的 SDK。作为此 SDK 的一部分,我需要将自己的 WebViewClient 设置为应用程序的 WebView,其中集成了 WebView 和 SDK(这意味着不是我的 SDK 的一部分)。

出于这个原因,这个WebView 可能已经设置了一个WebViewClient,在这种情况下,我需要从WebView 中获取这个WebViewClient 的实例,并将我自己的WebViewClient 设置为它并将我的WebViewCleint的回调方法转发到应用开发者设置的最初配置的回调方法。

我注意到,从 API V26 开始,WebView 类有一个 getWebViewClient 方法。但显然,我也在寻找一种在以前的版本上执行此操作的方法。也许有某种方法可以使用支持库来做到这一点?

有人知道如何在旧版本的 WebView 中获取 set WebViewClient 的实例吗?使用反射或任何其他方法?

【问题讨论】:

【参考方案1】:

我设法使用反射获取 WebViewClient 的实例,如下所示:

Object providerInstance = getProviderInstance();
Object contentsClientAdapter = getContentsClientAdapter(providerInstance);
Object webViewClient = getWebViewClientFromClientAdapter(contentsClientAdapter);
if (webViewClient instanceof WebViewClient) 
    mPreviousWebViewClient = (WebViewClient) webViewClient;

这些是深入WebView 对象以获取WebViewClient 对象的三种方法:

public Object getProviderInstance() 
    Object returnValue = null;
    try 
        Class<? extends WebView> mWebViewClass = mWebView.getClass();
        Field providerField = mWebViewClass.getDeclaredField("mProvider");
        providerField.setAccessible(true);
        Object mProvider = providerField.get(mWebView);
        returnValue = mProvider;

     catch (NoSuchFieldException aE) 
        aE.printStackTrace();
     catch (IllegalAccessException aE) 
        aE.printStackTrace();
    

    return returnValue;



private Object getContentsClientAdapter(Object aProviderInstance) 
    Object returnValue = null;
    try 
        Class<?> aClass = aProviderInstance.getClass();
        Field contentsClientAdapterField = aClass.getDeclaredField("mContentsClientAdapter");
        contentsClientAdapterField.setAccessible(true);
        Object mContentsClientAdapter = contentsClientAdapterField.get(aProviderInstance);
        returnValue = mContentsClientAdapter;

     catch (NoSuchFieldException aE) 
        aE.printStackTrace();
     catch (IllegalAccessException aE) 
        aE.printStackTrace();
    

    return returnValue;



private Object getWebViewClientFromClientAdapter(Object aContentsClientAdapter) 
    Object returnValue = null;
    try 
        Class<?> aClass = aContentsClientAdapter.getClass();
        Field WebViewClientField = aClass.getDeclaredField("mWebViewClient");
        WebViewClientField.setAccessible(true);
        Object mWebViewClient = WebViewClientField.get(aContentsClientAdapter);
        returnValue = mWebViewClient;

     catch (NoSuchFieldException aE) 
        aE.printStackTrace();
     catch (IllegalAccessException aE) 
        aE.printStackTrace();
    

    return returnValue;

但我真的希望能找到另一种方法来做同样的事情。不易破损的东西。

【讨论】:

以上是关于如何从不在 Android 的 API 26 上的 WebView 获取 WebviewClient 实例?的主要内容,如果未能解决你的问题,请参考以下文章

Android Oreo (API 26) - 在外部存储中创建目录

如何修复 Android 中的“调用需要 API 级别 26(当前最低为 25)”错误

如何在 26 以下的 Android API 上使用 StorageManager 获取目录的 uuid?

如何更改 Android O / Oreo / api 26 应用程序语言

Android 9应用程序菜单是深色背景上的暗文本

如果 Android API 级别低于 26,如何将存储访问框架与 MediaMuxer 一起使用