我在 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 对象会如何导致这种情况。有没有人有这方面的知识或经验?本机代码是否无法访问我创建的对象?我是不是在插手不该插手的事情?