问题
Filing bug to YouTube Android Player API Library engineers: see android-youtube-api tag
Over the course of the past week and a half, I've noticed this weird BadParcelableException steadily increasing in our app and have nailed it down to YouTube's new release on android.
This crash will occur if your app is playing a youtube video, bringing your app to background, force stopping the Youtube app, and resuming your app again. Crash reproducible on Youtube version 12.19.56. Also tested on an older YouTube version 12.05.21 and the crash was not there.
Stack trace:
main Exception: Unable to start activity ComponentInfo{com.myapp.MainActivity}:
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: asc
Stack: java.lang.RuntimeException: Unable to start activity ComponentInfo{com.myapp.MainActivity}:
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: asc
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2666)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2727)
at android.app.ActivityThread.-wrap12(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1478)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:154)
at android.app.ActivityThread.main(ActivityThread.java:6121)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:889)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:779) Caused by:
android.os.BadParcelableException: ClassNotFoundException when unmarshalling: asc
at android.os.Parcel.readParcelableCreator(Parcel.java:2536)
at android.os.Parcel.readParcelable(Parcel.java:2462)
at android.os.Parcel.readValue(Parcel.java:2365)
at android.os.Parcel.readSparseArrayInternal(Parcel.java:2813)
at android.os.Parcel.readSparseArray(Parcel.java:2068)
at android.os.Parcel.readValue(Parcel.java:2422)
at android.os.Parcel.readArrayMapInternal(Parcel.java:2732)
at android.os.BaseBundle.unparcel(BaseBundle.java:269)
at android.os.Bundle.getSparseParcelableArray(Bundle.java:934)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1208)
at android.support.v4.app.FragmentManagerImpl.moveFragmentToExpectedState(FragmentManager.java:1528)
at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1595)
at android.support.v4.app.FragmentManagerImpl.dispatchCreate(FragmentManager.java:2893)
at android.support.v4.app.FragmentController.dispatchCreate(FragmentController.java:190)
at android.support.v4.app.FragmentActivity.onCreate(FragmentActivity.java:353)
at android.support.v7.app.AppCompatActivity.onCreate(AppCompatActivity.java:85)
at com.myapp.BaseActivity.onCreate(BaseActivity.java:36)
at com.myapp.MainActivity.onCreate(MainActivity.java:190)
at android.app.Activity.performCreate(Activity.java:6682)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1118)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2619) ... 9 more
Caused by: java.lang.ClassNotFoundException: Didn't find class "asc" on path: DexPathList[[zip file "/data/app/com.myapp-naA-_cCrz-w81rqx98ipcQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.myapp-naA-_cCrz-w81rqx98ipcQ==/lib/arm64, /system/lib64, /vendor/lib64]]
at dalvik.system.BaseDexClassLoader.findClass(BaseDexClassLoader.java:93)
at java.lang.ClassLoader.loadClass(ClassLoader.java:379)
at java.lang.ClassLoader.loadClass(ClassLoader.java:312)
... 32 more
Some more info:
@Override
public void onCreate(Bundle savedInstanceState) {
...
super.onCreate(savedInstanceState); // Crashing here MainActivity.java:190
...
}
回答1:
The problem in view state saving and restoring. Youtube app have a bug and store view state which contains instance of class asc
from youtube apk. So our app can not restore it because known nothing about this class. My solution is preventing view state saving for YoutubePlayerView
in YouTubePlayerSupportFragment
by next code:
@Override
public void onSaveInstanceState(Bundle bundle) {
super.onSaveInstanceState(bundle);
// disable view state saving to prevent saving states from youtube apk which cannot be restored.
View view = getView();
if (view instanceof ViewGroup) {
ViewGroup viewGroup = ((ViewGroup) view);
for (int i = 0; i < viewGroup.getChildCount(); i++) {
viewGroup.getChildAt(i).setSaveFromParentEnabled(false);
}
}
}
This code should be added to your subclass of YouTubePlayerSupportFragment
.
This solution does not remove youtube player state from bundle. So youtube player will be restored successfully.
回答2:
Obviously it's a bug of YouTube app. I'd recommend you to use this hack to erase bundle passed from youtube client to escape this parsing error.
@Override
public void onCreate(Bundle b) {
if (b != null) {
b.remove("android:fragments");
}
super.onCreate(b);
}
回答3:
Use following code in your onCreate:
@Override
public void onCreate(Bundle b) {
if (b != null) {
final ClassLoader contextCl = getClassLoader();
b.setClassLoader(contextCl);
}
super.onCreate(b);
}
The bug is probably due to YouTube library code storing custom Parcelable inside the state Bundle (YouTube library classes are probably obfuscated by Proguard, hence weird names like "asc").
If the suggestion above does not work, follow along the lines of @Fitz's suggestion and drop the state Bundle. Don't try to mess with it in onCreate (that won't work), instead it is best to override onSaveInstanceState to return Bundle.EMPTY if your app is suspended when you have a playback in progress.
Note, that the bug in question is pretty tricky in multiple ways. If you (or YouTube app) store nested Bundles inside each other, those also need to have proper ClassLoader set… Someone should tell Google to get some common sense and just use Thread#getContextClassLoader inside Bundle to fix that problem once and for all.
回答4:
I found a solution that works for me. In my onCreate
method I catch the RuntimeException
that gets thrown due to the ClassNotFoundException
in the youtube player. The video loses its state. Pressing play causes it to start over. Otherwise business as usual.
回答5:
I just ended up using a try catch block that worked for me.
try {
super.onCreate(savedInstanceState);
} catch (BadParcelableException e) {
// Maybe put an analytic here to see if it is still being thrown.
// So when youtube fixes the issue in the future we can remove this
// ugly try catch.
Log.e(TAG, e.toString);
}
来源:https://stackoverflow.com/questions/44379747/youtube-android-player-api-throws-badparcelableexception-classnotfoundexception