WebView实例化的问题

2019-12-18  本文已影响0人  钦_79f7

由于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位架构做的相应的性能优化以及兼容处理丢失掉。

上一篇下一篇

猜你喜欢

热点阅读