当前位置:   article > 正文

Android7.0 webview android.content.res.Resources$NotFoundException_1515seⅹ

1515seⅹ

Android7.0 webview android.content.res.Resources$NotFoundException

0x01. 崩溃日志

首先从崩溃日志的信息上就能看出来不是应用层的资源问题。
1.source id: 0x20b00000
2.崩溃栈的记录是在chromium创建Actionmenu的时候(长按webview中的一段文本)

09-15 15:22:25.072  3841  3841 W ResourceType: No known package when getting value for resource number 0x020b0000
09-15 15:22:25.073  3841  3841 W ResourceType: No known package when getting value for resource number 0x020b0000
09-15 15:22:25.076  3841  3841 W System.err: android.content.res.Resources$NotFoundException: Resource ID #0x20b0000
09-15 15:22:25.077  3841  3841 W System.err:    at android.content.res.ResourcesImpl.getValue(ResourcesImpl.java:242)
09-15 15:22:25.077  3841  3841 W System.err:    at android.content.res.Resources.loadXmlResourceParser(Resources.java:2149)
09-15 15:22:25.077  3841  3841 W System.err:    at android.content.res.Resources.getLayout(Resources.java:1152)
09-15 15:22:25.077  3841  3841 W System.err:    at android.view.MenuInflater.inflate(MenuInflater.java:108)
09-15 15:22:25.077  3841  3841 W System.err:    at org.chromium.content.browser.WebActionModeCallback.createActionMenu(WebActionModeCallback.java:174)
09-15 15:22:25.077  3841  3841 W System.err:    at org.chromium.content.browser.WebActionModeCallback.onCreateActionMode(WebActionModeCallback.java:145)
09-15 15:22:25.077  3841  3841 W System.err:    at org.chromium.content.browser.FloatingWebActionModeCallback.onCreateActionMode(FloatingWebActionModeCallback.java:31)
09-15 15:22:25.077  3841  3841 W System.err:    at com.android.internal.policy.DecorView$ActionModeCallback2Wrapper.onCreateActionMode(DecorView.java:2311)
09-15 15:22:25.077  3841  3841 W System.err:    at com.android.internal.policy.DecorView.startActionMode(DecorView.java:885)
09-15 15:22:25.077  3841  3841 W System.err:    at com.android.internal.policy.DecorView.startActionModeForChild(DecorView.java:841)
09-15 15:22:25.077  3841  3841 W System.err:    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:833)
09-15 15:22:25.078  3841  3841 W System.err:    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:833)
09-15 15:22:25.078  3841  3841 W System.err:    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:833)
09-15 15:22:25.078  3841  3841 W System.err:    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:833)
09-15 15:22:25.078  3841  3841 W System.err:    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:833)
09-15 15:22:25.079  3841  3841 W System.err:    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:833)
09-15 15:22:25.079  3841  3841 W System.err:    at android.view.ViewGroup.startActionModeForChild(ViewGroup.java:833)
09-15 15:22:25.080  3841  3841 W System.err:    at android.view.View.startActionMode(View.java:5876)
09-15 15:22:25.080  3841  3841 W System.err:    at org.chromium.content.browser.ContentViewCore.showSelectActionMode$51D2ILG_(ContentViewCore.java:29100)
09-15 15:22:25.080  3841  3841 W System.err:    at org.chromium.content.browser.ContentViewCore.onSelectionEvent(ContentViewCore.java:2164)
09-15 15:22:25.080  3841  3841 W System.err:    at org.chromium.android_webview.AwContents.nativeOnDraw(Native Method)
09-15 15:22:25.080  3841  3841 W System.err:    at org.chromium.android_webview.AwContents.access$4700(AwContents.java:99)
09-15 15:22:25.080  3841  3841 W System.err:    at org.chromium.android_webview.AwContents$AwViewMethodsImpl.onDraw(AwContents.java:2992)
09-15 15:22:25.081  3841  3841 W System.err:    at com.android.webview.chromium.WebViewChromium.onDraw(WebViewChromium.java:32327)
09-15 15:22:25.081  3841  3841 W System.err:    at android.webkit.WebView.onDraw(WebView.java:2534)
09-15 15:22:25.081  3841  3841 W System.err:    at android.view.View.draw(View.java:17282)
09-15 15:22:25.081  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16264)
09-15 15:22:25.082  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.082  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.082  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.083  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.083  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.083  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.083  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.083  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.083  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.083  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.recreateChildDisplayList(ViewGroup.java:3768)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3748)
09-15 15:22:25.084  3841  3841 W System.err:    at android.view.View.updateDisplayListIfDirty(View.java:16227)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ThreadedRenderer.updateViewTreeDisplayList(ThreadedRenderer.java:648)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ThreadedRenderer.updateRootDisplayList(ThreadedRenderer.java:654)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ThreadedRenderer.draw(ThreadedRenderer.java:762)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ViewRootImpl.draw(ViewRootImpl.java:3141)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2924)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:2486)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1443)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:6918)
09-15 15:22:25.085  3841  3841 W System.err:    at android.view.Choreographer$CallbackRecord.run(Choreographer.java:878)
09-15 15:22:25.086  3841  3841 W System.err:    at android.view.Choreographer.doCallbacks(Choreographer.java:690)
09-15 15:22:25.086  3841  3841 W System.err:    at android.view.Choreographer.doFrame(Choreographer.java:625)
09-15 15:22:25.086  3841  3841 W System.err:    at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:864)
09-15 15:22:25.087  3841  3841 W System.err:    at android.os.Handler.handleCallback(Handler.java:751)
09-15 15:22:25.087  3841  3841 W System.err:    at android.os.Handler.dispatchMessage(Handler.java:95)
09-15 15:22:25.087  3841  3841 W System.err:    at android.os.Looper.loop(Looper.java:185)
09-15 15:22:25.087  3841  3841 W System.err:    at android.app.ActivityThread.main(ActivityThread.java:6493)
09-15 15:22:25.087  3841  3841 W System.err:    at java.lang.reflect.Method.invoke(Native Method)
09-15 15:22:25.087  3841  3841 W System.err:    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:916)
09-15 15:22:25.087  3841  3841 W System.err:    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:806)
09-15 15:22:25.093  3841  3841 F chromium: [FATAL:jni_android.cc(236)] Please include Java exception stack in crash report
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74

0x02. source code

这里列出来的android源码都是基于:android-7.0.0_r1
根据崩溃数据爆露的代码来看:

frameworks/base/core/java/android/view/MenuInflater.java

Context是上层传递过来的.

    private Context mContext;
    private Object mRealOwner;

    /**
     * Constructs a menu inflater.
     * 
     * @see Activity#getMenuInflater()
     */
    public MenuInflater(Context context) {
        mContext = context;
        mActionViewConstructorArguments = new Object[] {context};
        mActionProviderConstructorArguments = mActionViewConstructorArguments;
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

真正的inflate的地方:

    /**
     * Inflate a menu hierarchy from the specified XML resource. Throws
     * {@link InflateException} if there is an error.
     * 
     * @param menuRes Resource ID for an XML layout resource to load (e.g.,
     *            <code>R.menu.main_activity</code>)
     * @param menu The Menu to inflate into. The items and submenus will be
     *            added to this Menu.
     */
    public void inflate(@MenuRes int menuRes, Menu menu) {
        XmlResourceParser parser = null;
        try {
            parser = mContext.getResources().getLayout(menuRes);  //这里就是问题的根源所在,因为有插件框架,获取到的Resource对象弄错了,找不到对应的xml资源.
            AttributeSet attrs = Xml.asAttributeSet(parser);

            parseMenu(parser, attrs, menu);
        } catch (XmlPullParserException e) {
            throw new InflateException("Error inflating menu XML", e);
        } catch (IOException e) {
            throw new InflateException("Error inflating menu XML", e);
        } finally {
            if (parser != null) parser.close();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

frameworks/base/core/java/android/content/res/ResourcesImpl.java
getValue的代码实现:

    void getValue(@AnyRes int id, TypedValue outValue, boolean resolveRefs)
            throws NotFoundException {
        boolean found = mAssets.getResourceValue(id, 0, outValue, resolveRefs);
        if (found) {
            return;
        }
        throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id));
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

mAssets is AssetManager

    final AssetManager mAssets;
    private final DisplayMetrics mMetrics = new DisplayMetrics();
    private final DisplayAdjustments mDisplayAdjustments;
  • 1
  • 2
  • 3
    /**
     * Creates a new ResourcesImpl object with CompatibilityInfo.
     *
     * @param assets Previously created AssetManager.
     * @param metrics Current display metrics to consider when
     *                selecting/computing resource values.
     * @param config Desired device configuration to consider when
     *               selecting/computing resource values (optional).
     * @param displayAdjustments this resource's Display override and compatibility info.
     *                           Must not be null.
     */
    public ResourcesImpl(@NonNull AssetManager assets, @Nullable DisplayMetrics metrics,
            @Nullable Configuration config, @NonNull DisplayAdjustments displayAdjustments) {
        mAssets = assets;
        mMetrics.setToDefaults();
        mDisplayAdjustments = displayAdjustments;
        updateConfiguration(config, metrics, displayAdjustments.getCompatibilityInfo());
        mAssets.ensureStringBlocks();
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19

frameworks/base/core/java/android/content/res/Resources.java

    /**
     * Return an XmlResourceParser through which you can read a view layout
     * description for the given resource ID.  This parser has limited
     * functionality -- in particular, you can't change its input, and only
     * the high-level events are available.
     * 
     * <p>This function is really a simple wrapper for calling
     * {@link #getXml} with a layout resource.
     * 
     * @param id The desired resource identifier, as generated by the aapt
     *           tool. This integer encodes the package, type, and resource
     *           entry. The value 0 is an invalid identifier.
     *
     * @throws NotFoundException Throws NotFoundException if the given ID does not exist.
     * 
     * @return A new parser object through which you can read
     *         the XML data.
     *         
     * @see #getXml
     */
    public XmlResourceParser getLayout(@LayoutRes int id) throws NotFoundException {
        return loadXmlResourceParser(id, "layout");
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
    /**
     * Loads an XML parser for the specified file.
     *
     * @param id the resource identifier for the file
     * @param type the type of resource (used for logging)
     * @return a parser for the specified XML file
     * @throws NotFoundException if the file could not be loaded
     */
    @NonNull
    XmlResourceParser loadXmlResourceParser(@AnyRes int id, @NonNull String type)
            throws NotFoundException {
        final TypedValue value = obtainTempTypedValue();
        try {
            final ResourcesImpl impl = mResourcesImpl;
            impl.getValue(id, value, true);
            if (value.type == TypedValue.TYPE_STRING) {
                return impl.loadXmlResourceParser(value.string.toString(), id,
                        value.assetCookie, type);
            }
            throw new NotFoundException("Resource ID #0x" + Integer.toHexString(id)
                    + " type #0x" + Integer.toHexString(value.type) + " is not valid");
        } finally {
            releaseTempTypedValue(value);
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25

0x03. Context和Resource分析

  • 0x03.1. class loader:
//当前classloader
com.qihoo360.replugin.PluginDexClassLoader[DexPathList[[zip file "/data/data/com.iamcxl.xxx/Plugin.jar"],nativeLibraryDirectories=[/data/data/com.iamcxl.xxx/Plugin, /vendor/lib, /system/lib, /data/datalib]]]

//父classloader
dalvik.system.PathClassLoader[DexPathList[[directory "."],nativeLibraryDirectories=[/vendor/lib, /system/lib, /data/datalib]]]
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 0x03.2. Context and resource:

从Activity中取出当前的Application和Resource信息:

Application Context:com.iamcxl.xxx.plugin.aaa.XxxApplication@44733c40//宿主为插件创建的Application
Application BaseContext:com.qihoo360.loader2.PluginContext@44352e70 //插件宿主的Application, getBaseContext()
//在Activity中看到的当前的Resource对象:
resource:android.content.res.Resources@4438fbf8   //getResources()
BaseContext resource:android.content.res.Resources@4438fbf8 //getBaseContext().getResources()
Application Context resource:android.content.res.Resources@4438fbf8 //getApplicationContext().getResources()
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7

getApplicationContext()代码:

/**
 * Proxying implementation of Context that simply delegates all of its calls to
 * another Context.  Can be subclassed to modify behavior without changing
 * the original Context.
 */
public class ContextWrapper extends Context {
    Context mBase;
    //省略...
    @Override
    public Context getApplicationContext() {
        return mBase.getApplicationContext();
    }
    //省略...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13

getBaseContext()代码:

/**
 * Proxying implementation of Context that simply delegates all of its calls to
 * another Context.  Can be subclassed to modify behavior without changing
 * the original Context.
 */
public class ContextWrapper extends Context {
    Context mBase;
    //省略...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

getResource()代码:

public class ContextThemeWrapper extends ContextWrapper {
    private int mThemeResource;
    private Resources.Theme mTheme;
    private LayoutInflater mInflater;
    private Configuration mOverrideConfiguration;
    private Resources mResources;
    //省略...

    @Override
    public Resources getResources() {
        if (mResources != null) {
            return mResources;
        }
        if (mOverrideConfiguration == null) {
            mResources = super.getResources();
            return mResources;
        } else {
            Context resc = createConfigurationContext(mOverrideConfiguration);
            mResources = resc.getResources();
            return mResources;
        }
    }
    //省略...
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23

从动态广播中取出context和resource信息

//BroadCast's context is TinkerPatchReflectApplication.(广播参数携带的信息)
plugin context:com.tencent.bugly.beta.tinker.TinkerPatchReflectApplication@43933aa0 //context
plugin resource:com.huawei.android.content.res.ResourcesEx@43930dd0   //context.getResources()
//下面是宿主传递过来的信息
宿主 context:com.iamcxl.xxx.plugin.aaa.XxxApplication@44733c40
宿主 resource:android.content.res.Resources@4438fbf8
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6

0x04. inflate异常:

再复制一次上面的代码:

    /**
     * Inflate a menu hierarchy from the specified XML resource. Throws
     * {@link InflateException} if there is an error.
     * 
     * @param menuRes Resource ID for an XML layout resource to load (e.g.,
     *            <code>R.menu.main_activity</code>)
     * @param menu The Menu to inflate into. The items and submenus will be
     *            added to this Menu.
     */
    public void inflate(@MenuRes int menuRes, Menu menu) {
        XmlResourceParser parser = null;
        try {
            parser = mContext.getResources().getLayout(menuRes);  //这里就是问题的根源所在,因为有插件框架,获取到的Resource对象弄错了,找不到对应的xml资源.
            AttributeSet attrs = Xml.asAttributeSet(parser);

            parseMenu(parser, attrs, menu);
        } catch (XmlPullParserException e) {
            throw new InflateException("Error inflating menu XML", e);
        } catch (IOException e) {
            throw new InflateException("Error inflating menu XML", e);
        } finally {
            if (parser != null) parser.close();
        }
    }
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24

0x05. 总结

从上面的信息上来看,整个应用中出现了三个Applicaiton和两个Resource对象.
Application对象:
TinkerPatchReflectApplication //腾讯Tinker的
com.qihoo360.loader2.PluginContext //replugin插件框架的
XxxApplication //插件的

Resource对象
com.huawei.android.content.res.ResourcesEx //从Tinker的Application中取出
android.content.res.Resources //getResources()/getBaseContext().getResources()/getApplicationContext().getResources()

这个问题只出现在Android7.0上,android8.0应该也有这个问题, 至于为什么在android7.0上会出现这个问题,还需要进一步了解replugin托管了context后,对资源的处理逻辑了.

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/小小林熬夜学编程/article/detail/104287
推荐阅读
相关标签
  

闽ICP备14008679号