如何从 WebView 获取 WebViewClient 实例,而不是在 Android 中的 API 26 上



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

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

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

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

我设法使用反射获取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;
}

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

最新更新