Android WebView没有权限修改给定的线程,我应该声明哪个权限?

时间:2012-11-06 09:34:50

标签: android permissions webview

崩溃日志:

    java.lang.SecurityException: No permission to modify given thread
android.os.Process.setThreadPriority(Native Method)
android.webkit.WebViewCore$WebCoreThread$1.handleMessage(WebViewCore.java:764)
android.os.Handler.dispatchMessage(Handler.java:99)
android.os.Looper.loop(Looper.java:137)
android.webkit.WebViewCore$WebCoreThread.run(WebViewCore.java:829)
java.lang.Thread.run(Thread.java:856)

我应该申报哪个权限? http://developer.android.com/reference/android/Manifest.permission.html

编辑:

我在WebView java.lang.SecurityException: No permission to modify given thread

中发现了类似的问题

答案说“这是氰化物的错”。

然而,在线程http://code.google.com/p/cyanogenmod/issues/detail?id=5656&thanks=5656&ts=1341224425中,cm menbers似乎否认它是CM的错误

最重要的是,我的问题是: 如何从我的应用中修复它?

2 个答案:

答案 0 :(得分:0)

  

我应该声明哪个权限?

此AFAIK没有相关许可。不幸的是,setThreadPriority()的实现是在本机代码中,这使我很难弄清楚发生了什么。

  

cm menbers似乎否认这是CM的错误

不,他们没有。没有人发布证据证明这是CM9或更高版本的问题,这就是为什么他们将问题标记为陈旧。如果你在CM9或更高版本上看到这个,我建议你更新这个问题。如果您在标准Android上看到这一点,请创建一个可以重现错误的示例项目。

  

如何从我的应用中修复它?

你很可能没有。您可以尝试在WebView上运行一些实验,以查看是否存在触发此异常的特定内容,并尝试修改或删除该内容。

答案 1 :(得分:0)

我从我的应用程序中获得了这个异常导致的数十个崩溃日志(这取决于webview严重),涉及的ROM版本是4.0.4和4.0.3。

似乎没有正常的方法来修复它,所以我尝试了遵循黑客攻击的方法。

代码snipet 4.0.4:

private static Handler sWebCoreHandler;
// Class for providing Handler creation inside the WebCore thread.
private static class WebCoreThread implements Runnable {
    // Message id for initializing a new WebViewCore.
    private static final int INITIALIZE = 0;
    private static final int REDUCE_PRIORITY = 1;
    private static final int RESUME_PRIORITY = 2;

    public void run() {
        Looper.prepare();
        Assert.assertNull(sWebCoreHandler);
        synchronized (WebViewCore.class) {
            sWebCoreHandler = new Handler() {
                @Override
                public void handleMessage(Message msg) {
                    // ...
                    // Process.setPriority(...)
                }
            };
        // ...
        }
        // ...
    }
}

我认为这个异常是从sWebCoreHandler.handleMessage()抛出的,如果我们可以在handleMessage()上包装try / catch,那么问题就可以解决了。

Handler类有四个成员:

final MessageQueue mQueue;
final Looper mLooper;
final Callback mCallback;
IMessenger mMessenger;

mQueue设置为mLooper.mQueue,mCallback在sWebCoreHandler中为null,因此我们只需要在sWebCoreHandler中设置mLooper和mMessenger值。

static Handler sProxyHandler = null;

static void tryTweakWebCoreHandler() {
    // 4.0.3/4.0.4 rom
    if (Build.VERSION.SDK_INT == Build.VERSION_CODES.ICE_CREAM_SANDWICH_MR1) {
        tweakWebCoreHandle();
    }
}

static private void tweakWebCoreHandle() {
    if (sProxyHandler != null)
        return;
    try {
        Field f = Class.forName("android.webkit.WebViewCore").getDeclaredField("sWebCoreHandler");
        f.setAccessible(true);
        Object h = f.get(null);
        Object mMessenger = null;
        Method m = Handler.class.getDeclaredMethod("getIMessenger", (Class<?>[])null);
        m.setAccessible(true);
        mMessenger = m.invoke(h, (Object[])null);
        sProxyHandler = new WebCoreProxyHandler((Handler)h);
        if (mMessenger != null) {
            Field f1 = Handler.class.getDeclaredField("mMessenger");
            f1.setAccessible(true);
            f1.set(sProxyHandler, mMessenger);
        }
        f.set(null, sProxyHandler);
        // Log.w(TAG,  "sWebCoreHandler: " + h);
    } catch (Throwable e) {
        Log.w(TAG, "exception: " + e);
    }
    if (sProxyHandler == null)
        sProxyHandler = new Handler();
}

static class WebCoreProxyHandler extends Handler {
    final Handler handler;
    public WebCoreProxyHandler(Handler handler) {
        super(handler.getLooper());
        this.handler = handler;
    }

    public void handleMessage(Message msg) {
        // Log.w("WebCoreProxyHandler", "handle msg: " + msg.what);
        try {
            handler.handleMessage(msg);
        } catch (Throwable tr) {
            Log.w("WebCoreProxyHandler", "exception: " + tr);
        }
    }
}

遗留问题是何时调用tryTweakWebCoreHandler()。在某些设备上创建并测试WebView实例后,我尝试调用它,可以调用WebCoreProxyHandler.handleMessage()。

注意:我刚做了一些简单的测试,我不确定这个问题是否已经解决,因为原点异常无法可靠地再现。

如果您决定尝试这种方法,请进行足够的测试。