赞
踩
首先从崩溃日志的信息上就能看出来不是应用层的资源问题。
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
这里列出来的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;
}
真正的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();
}
}
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));
}
mAssets is AssetManager
final AssetManager mAssets;
private final DisplayMetrics mMetrics = new DisplayMetrics();
private final DisplayAdjustments mDisplayAdjustments;
/**
* 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();
}
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");
}
/**
* 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);
}
}
//当前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]]]
从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()
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();
}
//省略...
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;
//省略...
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;
}
}
//省略...
从动态广播中取出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
再复制一次上面的代码:
/**
* 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();
}
}
从上面的信息上来看,整个应用中出现了三个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后,对资源的处理逻辑了.
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。