美文网首页
WebView实例化的问题

WebView实例化的问题

作者: 钦_79f7 | 来源:发表于2019-12-18 11:24 被阅读0次

    由于WebView直接在XML中生成会使得WebView直接强引用了当前Activity的对象,易于引起Activity的leak,故将WebView对象的创建修改为如下:

    // 此处应用 Application的Context并自行构造WebView的对象会导致兼容性问题,在部分手机上会出现 实例化问题 java.lang.reflect.InvocionTargetException
    private void setContentView() {
        LinearLayout rootLinear = (LinearLayout) LayoutInflater.from(getApplicationContext()).inflate(R.layout.layout_no_reload_web, new FrameLayout(getApplicationContext()), false);
        progressBar = ButterKnife.findById(rootLinear, R.id.progressBar);
        webView = new WebView(getApplicationContext());
        rootLinear.addView(webView, new LinearLayout.LayoutParams(-1, -1));
        setView(rootLinear);
    }
    

    但是这样操作之后,在线上运行之后爆出了大量的.RuntimeException 异常

    0.  java.lang.RuntimeException: Unable to start activity ComponentInfo{com.jiedai.loan/com.jiedai.loan.ui.activity.WebActivity}: android.util.AndroidRuntimeException: java.lang.reflect.InvocionTargetException
    1.  android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2793)
    2.  android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2864)
    3.  android.app.ActivityThread.-wrap12(ActivityThread.java)
    4.  android.app.ActivityThread$H.handleMessage(ActivityThread.java:1567)
    5.  android.os.Handler.dispchMessage(Handler.java:105)
    6.  android.os.Looper.loop(Looper.java:156)
    7.  android.app.ActivityThread.main(ActivityThread.java:6523)
    8.  java.lang.reflect.Method.invoke(Nive Method)
    9.  com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:941)
    10. com.android.internal.os.ZygoteInit.main(ZygoteInit.java:831)
    

    经查阅资料,说是WebView的构造器本身存在部分机型的兼容性问题。

    开始的时候,猜测是由于上述改动造成的:在此之前从未出现这个报错,但是仅仅是此次修改如上代码之后才出现并且是大量的。

    但是在新的版本上线后,将上述代码复原后,仍然会有同样的crash出现,故上述说法不成立,就追着兼容性问题方向qu去探索。

    在Stack Overflow上找到同样的问题:

    Android NoSuchMethodException: callDrawGLFunction

    根据堆栈信息的对应,上述堆栈信息代码不全,全部堆栈信息在结尾处会贴出。

    "Api21CompatibilityDelegate means webview believes it's running on 21. Renaming callDrawGLFunction happened after API21, hence webview is trying look for the old name."

    上述对应的意思就是,API 21之后的系统做了一个方法的重命名,由callDrawGLFunction改为callDrawGLFunction2,并且针对这个重命名做了低版本的兼容,也就是Api21CompatibilityDelegate这个类用于版本兼容的,当属于低版本时会匹配低版本相对应的方法来处理。

    故,在Google官方层面实际上是做了这个的兼容处理的,会出现如此的bug,也是定制化ROM未做兼容处理,导致找寻不到方法。

    com.android.webview.chromium.WebViewDelegateFactory$Api21CompatibilityDelegate 兼容源码
    查看源码

    在实例化内部类Api21CompatibilityDelegate的过程中,通过反射调用了HardwareCanvas的callDrawGLFunction方法,由于此方法在21+的系统中更名为callDrawGLFunction2,导致反射不到此方法,抛出异常。

    Api21CompatibilityDelegate() {
        try {
            // Important: This reflection essentially defines a snapshot of some hidden APIs
            // at version 21 of the framework for compatibility reasons, and the reflection
            // should not be changed even if those hidden APIs change in future releases.
            mIsTagEnabledMethod = Trace.class.getMethod("isTagEnabled", long.class);
            mAddChangeCallbackMethod = Class.forName("android.os.SystemProperties")
                                               .getMethod("addChangeCallback", Runnable.class);
            mGetViewRootImplMethod = View.class.getMethod("getViewRootImpl");
            mInvokeFunctorMethod =
                    Class.forName("android.view.ViewRootImpl")
                            .getMethod("invokeFunctor", long.class, boolean.class);
            mDetachFunctorMethod = Class.forName("android.view.ViewRootImpl")
                                           .getMethod("detachFunctor", long.class);
            //在此处调用callDrawGLFunction方法
            mCallDrawGLFunctionMethod = Class.forName("android.view.HardwareCanvas")
                                                .getMethod("callDrawGLFunction", long.class);
            mGetAssignedPackageIdentifiersMethod =
                    AssetManager.class.getMethod("getAssignedPackageIdentifiers");
            mAddAssetPathMethod = AssetManager.class.getMethod("addAssetPath", String.class);
            mCurrentApplicationMethod =
                    Class.forName("android.app.ActivityThread").getMethod("currentApplication");
            mGetStringMethod = Class.forName("android.net.http.ErrorStrings")
                                       .getMethod("getString", int.class, Context.class);
            mGetLoadedPackageInfoMethod = Class.forName("android.webkit.WebViewFactory")
                                                  .getMethod("getLoadedPackageInfo");
        } catch (Exception e) {
            throw new RuntimeException("Invalid reflection", e);
        }
    }
    

    android.view.HardwareCanvas

    查看源码

    在这里我们可以明显看到HardwareCanvas的源码中只有callDrawGLFunction2方法

    /**
     * Hardware accelerated canvas.
     *
     * @hide
     */
    public abstract class HardwareCanvas extends Canvas {
       
        ...
        /**
         * Calls the function specified with the drawGLFunction function pointer. This is
         * functionality used by webkit for calling into their renderer from our display lists.
         * This function may return true if an invalidation is needed after the call.
         *
         * @param drawGLFunction A native function pointer
         *
         * @return {@link RenderNode#STATUS_DONE}
         *
         * @hide
         */
        public abstract int callDrawGLFunction2(long drawGLFunction);
        ...
    }
    

    com.android.webview.chromium.WebViewDelegateFactory

    通过 WebViewDelegateFactory 的静态方法来实例化 其内部类 Api21CompatibilityDelegate

    /**
     * Creates a {@link WebViewDelegate com.android.webview.chromium.WebViewDelegate} compatible
     * with the API 21 version of the framework in which
     * {@link android.webkit.WebViewDelegate android.webkit.WebViewDelegate} had not yet been
     * introduced.
     *
     * @return the created delegate
     */
    static WebViewDelegate createApi21CompatibilityDelegate() {
        return new Api21CompatibilityDelegate();
    }
    

    com.android.webview.chromium.WebViewChromiumFactoryProvider

    在构造方法中调用了上一步的方法,来实例化Api21CompatibilityDelegate;

    并且从注释中可以看出,下面两个构造方法分别用于不同系统下(21作为分界线)进行实例化

    /**
     * Constructor called by the API 21 version of {@link WebViewFactory} and earlier.
     */
    public WebViewChromiumFactoryProvider() {
        initialize(WebViewDelegateFactory.createApi21CompatibilityDelegate());
    }
    
     /**
     * Constructor called by the API 22 version of {@link WebViewFactory} and later.
     */
    public WebViewChromiumFactoryProvider(android.webkit.WebViewDelegate delegate) {
        initialize(WebViewDelegateFactory.createProxyDelegate(delegate));
    }
    

    android.webkit.WebViewFactory

    在getProviderClass()中通过反射的方式实现了对WebViewChromiumFactoryProvider的实例化,然后对外开放包权限的静态方法getProvider()方法供WebView调用。

    /**
     * Top level factory, used creating all the main WebView implementation classes.
     *
     * @hide
     */
    @SystemApi
    public final class WebViewFactory {
    
        private static final String CHROMIUM_WEBVIEW_FACTORY =
                "com.android.webview.chromium.WebViewChromiumFactoryProvider";
        
        private static Class<WebViewFactoryProvider> getProviderClass() {
            Context webViewContext = null;
            Application initialApplication = AppGlobals.getInitialApplication();
    
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW,
                        "WebViewFactory.getWebViewContextAndSetProvider()");
                try {
                    webViewContext = getWebViewContextAndSetProvider();
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
                Log.i(LOGTAG, "Loading " + sPackageInfo.packageName + " version " +
                        sPackageInfo.versionName + " (code " + sPackageInfo.versionCode + ")");
    
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getChromiumProviderClass()");
                try {
                    initialApplication.getAssets().addAssetPathAsSharedLibrary(
                            webViewContext.getApplicationInfo().sourceDir);
                    ClassLoader clazzLoader = webViewContext.getClassLoader();
    
                    Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
                    loadNativeLibrary(clazzLoader);
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
    
                    Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "Class.forName()");
                    try {
                        //在此处通过反射获取WebViewChromiumFactoryProvider的Class实例
                        return (Class<WebViewFactoryProvider>) Class.forName(CHROMIUM_WEBVIEW_FACTORY,
                                true, clazzLoader);
                    } finally {
                        Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                    }
                } catch (ClassNotFoundException e) {
                    Log.e(LOGTAG, "error loading provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
            } catch (MissingWebViewPackageException e) {
                // If the package doesn't exist, then try loading the null WebView instead.
                // If that succeeds, then this is a device without WebView support; if it fails then
                // swallow the failure, complain that the real WebView is missing and rethrow the
                // original exception.
                try {
                    return (Class<WebViewFactoryProvider>) Class.forName(NULL_WEBVIEW_FACTORY);
                } catch (ClassNotFoundException e2) {
                    // Ignore.
                }
                Log.e(LOGTAG, "Chromium WebView package does not exist", e);
                throw new AndroidRuntimeException(e);
            }
        }
        
        static WebViewFactoryProvider getProvider() {
            synchronized (sProviderLock) {
                // For now the main purpose of this function (and the factory abstraction) is to keep
                // us honest and minimize usage of WebView internals when binding the proxy.
                if (sProviderInstance != null) return sProviderInstance;
    
                final int uid = Process.myUid();
                if (uid == Process.ROOT_UID || uid == Process.SYSTEM_UID) {
                    throw new UnsupportedOperationException(
                            "For security reasons, WebView is not allowed in privileged processes");
                }
    
                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
                try {
                    //在此处调用了getProviderClass()方法
                    Class<WebViewFactoryProvider> providerClass = getProviderClass();
    
                    Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
                    try {
                        //在此处将WebViewFactoryProvider最终实例化出来,21+的通过此构造方法实例化,,21及以下通过无参的构造实例化
                        sProviderInstance = providerClass.getConstructor(WebViewDelegate.class)
                                .newInstance(new WebViewDelegate());
                        if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                        return sProviderInstance;
                    } catch (Exception e) {
                        Log.e(LOGTAG, "error instantiating provider", e);
                        throw new AndroidRuntimeException(e);
                    } finally {
                        Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                    }
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                    StrictMode.setThreadPolicy(oldPolicy);
                }
            }
        }
    }
    

    其中 getProvider() 在不同系统下 通过不同的 WebViewFactoryProvider的构造器进行实例化

    上文代码中是通过有参构造实例化WebViewFactoryProvider,在API 21 以上的版本;
    下文代码中是通过无参构造实例化WebViewFactoryProvider,在API 21 及以下的版本。

    static WebViewFactoryProvider getProvider() {
        synchronized (sProviderLock) {
            // For now the main purpose of this function (and the factory abstraction) is to keep
            // us honest and minimize usage of WebView internals when binding the proxy.
            if (sProviderInstance != null) return sProviderInstance;
    
            Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getProvider()");
            try {
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.loadNativeLibrary()");
                loadNativeLibrary();
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
    
                Class<WebViewFactoryProvider> providerClass;
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "WebViewFactory.getFactoryClass()");
                try {
                    providerClass = getFactoryClass();
                } catch (ClassNotFoundException e) {
                    Log.e(LOGTAG, "error loading provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                }
    
                StrictMode.ThreadPolicy oldPolicy = StrictMode.allowThreadDiskReads();
                Trace.traceBegin(Trace.TRACE_TAG_WEBVIEW, "providerClass.newInstance()");
                try {
                    sProviderInstance = providerClass.newInstance();
                    if (DEBUG) Log.v(LOGTAG, "Loaded provider: " + sProviderInstance);
                    return sProviderInstance;
                } catch (Exception e) {
                    Log.e(LOGTAG, "error instantiating provider", e);
                    throw new AndroidRuntimeException(e);
                } finally {
                    Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
                    StrictMode.setThreadPolicy(oldPolicy);
                }
            } finally {
                Trace.traceEnd(Trace.TRACE_TAG_WEBVIEW);
            }
        }
    }
    

    android.webkit.WebView

    在WebView的源码中可以看到一些未被开放到SDK的方法,其中,WebView的隐藏构造器,其余构造器都是通过此构造方法来实例化WebView,那么在此方法中就调用 ensureProviderCreated(),而 ensureProviderCreated 中就调用了 WebViewFactory 的getFactory()方法

    @Widget
    public class WebView extends AbsoluteLayout
            implements ViewTreeObserver.OnGlobalFocusChangeListener,
            ViewGroup.OnHierarchyChangeListener, ViewDebug.HierarchyHandler {
        
        /**
         * WebView隐藏构造器,其余构造器都是通过此构造方法来实例化WebView,那么在此方法中就调用ensureProviderCreated()
         * @hide
         */
        @SuppressWarnings("deprecation")  // for super() call into deprecated base class constructor.
        protected WebView(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes,
                Map<String, Object> javaScriptInterfaces, boolean privateBrowsing) {
            super(context, attrs, defStyleAttr, defStyleRes);
            if (context == null) {
                throw new IllegalArgumentException("Invalid context argument");
            }
            sEnforceThreadChecking = context.getApplicationInfo().targetSdkVersion >=
                    Build.VERSION_CODES.JELLY_BEAN_MR2;
            checkThread();
    
            ensureProviderCreated();
            mProvider.init(javaScriptInterfaces, privateBrowsing);
            // Post condition of creating a webview is the CookieSyncManager.getInstance() is allowed.
            CookieSyncManager.setGetInstanceIsAllowed();
        } 
        
        private void ensureProviderCreated() {
                checkThread();
                if (mProvider == null) {
                    // As this can get called during the base class constructor chain, pass the minimum
                    // number of dependencies here; the rest are deferred to init().
                    //在此处调用WebViewFactory的getFactory()方法
                    mProvider = getFactory().createWebView(this, new PrivateAccess());
                }
        }
                
    }
    

    那么到了这里就可以看到整个源码的执行逻辑了。在WebView的整个代理工厂的逻辑中,通过 Api21CompatibilityDelegate 来做21及以下版本的方法兼容,21+ 的正常调用更名后的 callDrawGLFunction2()方法,而低版本的会通过反射来调用方法 callDrawGLFunction()。并且在 Api21CompatibilityDelegate 的兼容逻辑中做了异常处理逻辑,出现反射异常时会抛出 new RuntimeException("Invalid reflection", e)。而这一系列的逻辑又都是在WebView的实例化的过程就会执行。

    其实,由上述的一系列逻辑中,我们可以看到实际上Google官方对针对 callDrawGLFunction 的更名做了低版本的兼容处理的

    那么问题如何出现的呢?也很显然的,系统ROM做定制化处理时导致官方的这套逻辑在运行时出现了额外的异常case,如定制ROM将21-的callDrawGLFunction方法直接给更名了 callDrawGLFunction2 那么在运行到 低版本兼容逻辑时 就会自动寻找 callDrawGLFunction() ,然后找不到并抛出异常

    故,此异常的出现 并非Goggle官方的bug,而是手机厂商ROM的bug。

    crash堆栈信息

    05-18 15:23:51.738  22422-22422/com.example.abdulmoeed.webviewtest E/WebViewFactory﹕ error instantiating provider
        java.lang.RuntimeException: Invalid reflection
                at com.android.webview.chromium.WebViewDelegateFactory$Api21CompatibilityDelegate.<init>(WebViewDelegateFactory.java:223)
                at com.android.webview.chromium.WebViewDelegateFactory.createApi21CompatibilityDelegate(WebViewDelegateFactory.java:97)
                at com.android.webview.chromium.WebViewChromiumFactoryProvider.<init>(WebViewChromiumFactoryProvider.java:97)
                at java.lang.reflect.Constructor.newInstance(Native Method)
                at java.lang.Class.newInstance(Class.java:1606)
                at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:124)
                at android.webkit.WebView.getFactory(WebView.java:2194)
                at android.webkit.WebView.ensureProviderCreated(WebView.java:2189)
                at android.webkit.WebView.setOverScrollMode(WebView.java:2248)
                at android.view.View.<init>(View.java:3588)
                at android.view.View.<init>(View.java:3682)
                at android.view.ViewGroup.<init>(ViewGroup.java:497)
                at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55)
                at android.webkit.WebView.<init>(WebView.java:544)
                at android.webkit.WebView.<init>(WebView.java:489)
                at android.webkit.WebView.<init>(WebView.java:472)
                at android.webkit.WebView.<init>(WebView.java:459)
                at java.lang.reflect.Constructor.newInstance(Native Method)
                at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
                at android.view.LayoutInflater.createView(LayoutInflater.java:607)
                at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
                at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
                at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
                at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
                at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
                at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:684)
                at android.view.LayoutInflater.inflate(Unknown Source)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
                at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(ActionBarActivityDelegateBase.java:240)
                at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:102)
                at com.example.abdulmoeed.webviewtest.MainActivity.onCreate(MainActivity.java:14)
                at android.app.Activity.performCreate(Activity.java:5990)
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
                at android.app.ActivityThread.access$800(ActivityThread.java:151)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:135)
                at android.app.ActivityThread.main(ActivityThread.java:5254)
                at java.lang.reflect.Method.invoke(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:372)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
                at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:117)
         Caused by: java.lang.NoSuchMethodException: callDrawGLFunction [long]
                at java.lang.Class.getMethod(Class.java:664)
                at java.lang.Class.getMethod(Class.java:643)
                at com.android.webview.chromium.WebViewDelegateFactory$Api21CompatibilityDelegate.<init>(WebViewDelegateFactory.java:211)
                at com.android.webview.chromium.WebViewDelegateFactory.createApi21CompatibilityDelegate(WebViewDelegateFactory.java:97)
                at com.android.webview.chromium.WebViewChromiumFactoryProvider.<init>(WebViewChromiumFactoryProvider.java:97)
                at java.lang.reflect.Constructor.newInstance(Native Method)
                at java.lang.Class.newInstance(Class.java:1606)
                at android.webkit.WebViewFactory.getProvider(WebViewFactory.java:124)
                at android.webkit.WebView.getFactory(WebView.java:2194)
                at android.webkit.WebView.ensureProviderCreated(WebView.java:2189)
                at android.webkit.WebView.setOverScrollMode(WebView.java:2248)
                at android.view.View.<init>(View.java:3588)
                at android.view.View.<init>(View.java:3682)
                at android.view.ViewGroup.<init>(ViewGroup.java:497)
                at android.widget.AbsoluteLayout.<init>(AbsoluteLayout.java:55)
                at android.webkit.WebView.<init>(WebView.java:544)
                at android.webkit.WebView.<init>(WebView.java:489)
                at android.webkit.WebView.<init>(WebView.java:472)
                at android.webkit.WebView.<init>(WebView.java:459)
                at java.lang.reflect.Constructor.newInstance(Native Method)
                at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
                at android.view.LayoutInflater.createView(LayoutInflater.java:607)
                at com.android.internal.policy.impl.PhoneLayoutInflater.onCreateView(PhoneLayoutInflater.java:55)
                at android.view.LayoutInflater.onCreateView(LayoutInflater.java:682)
                at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:741)
                at android.view.LayoutInflater.rInflate(LayoutInflater.java:806)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:504)
                at de.robv.android.xposed.XposedBridge.invokeOriginalMethodNative(Native Method)
                at de.robv.android.xposed.XposedBridge.handleHookedMethod(XposedBridge.java:684)
                at android.view.LayoutInflater.inflate(Unknown Source)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:414)
                at android.view.LayoutInflater.inflate(LayoutInflater.java:365)
                at android.support.v7.app.ActionBarActivityDelegateBase.setContentView(ActionBarActivityDelegateBase.java:240)
                at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:102)
                at com.example.abdulmoeed.webviewtest.MainActivity.onCreate(MainActivity.java:14)
                at android.app.Activity.performCreate(Activity.java:5990)
                at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
                at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2278)
                at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2387)
                at android.app.ActivityThread.access$800(ActivityThread.java:151)
                at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1303)
                at android.os.Handler.dispatchMessage(Handler.java:102)
                at android.os.Looper.loop(Looper.java:135)
                at android.app.ActivityThread.main(ActivityThread.java:5254)
                at java.lang.reflect.Method.invoke(Native Method)
                at java.lang.reflect.Method.invoke(Method.java:372)
                at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:903)
                at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:698)
                at de.robv.android.xposed.XposedBridge.main(XposedBridge.java:117)
    

    方案处理(有待验证)

    经过上述分析,定位了属于ROM的Chrome模块出现问题。并对照网上处理方案,属于Android System WebView的兼容问题。也就是厂商系统升级或者单独针对System WebView升级了,由于并未做CPU arm64架构下的兼容处理,导致APP在arm64架构下运行WebView底层的so文件时,出现兼容问题并发生Crash。由此解决方案就是针对APP手动配置其支持的CPU架构。

            ndk {
                //为了处理Chrome的bug:在arm64 cpu架构下的Android System WebView Crash的问题,去除64位的ABIS的so文件(注意:如此会导致64位下的优化无法作用,会影响部分性能以及兼容性隐患)
                abiFilters 'armeabi', 'armeabi-v7a', 'x86', 'mips'//, 'mips64','arm64-v8a', 'x86_64'
            }
    

    这样APP就手动指定了能够的适配的CPU架构。那么,未指定的CPU架构还支持么?既然是Crash的处理方案,肯定是让这部分用户可以使用的。64位架构的也是可以运行32位so文件的,也就是说因为原属于64位的so文件存在问题,故抛弃其专属的so文件,让其运行能够兼容的32位的so文件。缺点就是,会导致64位架构做的相应的性能优化以及兼容处理丢失掉。

    相关文章

      网友评论

          本文标题:WebView实例化的问题

          本文链接:https://www.haomeiwen.com/subject/cmnynctx.html