2

我在 Android 应用程序中使用反射来改变 WebView 的行为。通过浏览 Android 源代码,每个 WebView 通过一系列对象都有一个处理程序,它告诉本机代码获取资源等等。

我想做的是用我自己的处理程序替换这个处理程序,这会改变它收到的一些消息,然后将消息传递给原始处理程序。具体来说,我需要重写一些 URL,以便为代理配置它们。

这是一个虚拟方法来证明这一点:

private static boolean relayWebViewHandler( WebView webView ) {
    Log.d(LOG_TAG, "Attempting");

    try {
        Class classWV = Class.forName( "android.webkit.WebView" );
        Field mProviderField = classWV.getDeclaredField( "mProvider" );
        Object webViewClassic = getFieldValueSafely( mProviderField, webView );

        Class classWVCl = Class.forName( "android.webkit.WebViewClassic" );
        Field mWebViewCoreField = classWVCl.getDeclaredField( "mWebViewCore" );
        Object webViewCore = getFieldValueSafely( mWebViewCoreField, webViewClassic );

        Class classWVCo = Class.forName( "android.webkit.WebViewCore" );
        Field mEventHubField = classWVCo.getDeclaredField( "mEventHub" );
        Object eventHub = getFieldValueSafely( mEventHubField, webViewCore );

        Class classEH = Class.forName( "android.webkit.WebViewCore$EventHub" );
        Field mHandlerField = classEH.getDeclaredField( "mHandler" );
        final Handler handler = (Handler) getFieldValueSafely( mHandlerField, eventHub );

        Handler relayHandler = new Handler() {
            @Override
            public void handleMessage( Message msg ) {
                Log.d( LOG_TAG, "Relayed a message!" );
                handler.handleMessage( msg );
            }
        };
        setFieldValueSafely( mHandlerField, eventHub, relayHandler );
    } catch (Exception e) {
        Log.e( LOG_TAG, "Failed with error: " + e.getMessage() );
        return false;
    }

    Log.d( LOG_TAG, "Successful!" );
    return true;
}

private static Object getFieldValueSafely( Field field, Object classInstance ) throws IllegalArgumentException, IllegalAccessException {
    boolean oldAccessibleValue = field.isAccessible();
    field.setAccessible( true );
    Object result = field.get( classInstance );
    field.setAccessible( oldAccessibleValue );
    return result;
}

private static void setFieldValueSafely( Field field, Object classInstance, Object value ) throws IllegalArgumentException, IllegalAccessException {
    boolean oldAccessibleValue = field.isAccessible();
    field.setAccessible( true );
    field.set( classInstance, value );
    field.setAccessible( oldAccessibleValue );
}

当我在 4.3 模拟器上运行它时,LogCat 显示一些“Relayed a message!” 通知,然后是致命信号 11 (SIGSEGV) 错误,每次都在不同的地址。

我知道这意味着一个段错误,但我不确定替换 WebViewCore 使用的 Handler 对象会如何导致这种情况。有没有人有这方面的知识或经验?本机代码是否无法访问我创建的对象?我是不是在插手不该插手的事情?

4

0 回答 0