8

归档臭虫Android版YouTube播放器API库工程师:看到Android的YouTube上的API标签Android版YouTube播放器API将引发新的YouTube版本

在过去一周的过程中一半,我已经注意到这个奇怪的BadParcelableException在我们的应用程序中稳步增加,并已将它钉在YouTube上的新版本的Android上。如果您的应用程序正在播放YouTube视频,把你的应用的背景下,力停止YouTube应用,并重新恢复你的应用程序将发生

这个崩溃。在Youtube版本12.19.56上重现崩溃。还在较旧的YouTube版本12.05.21上进行了测试,崩溃不在那里。

堆栈跟踪:

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 

一些更多的信息:

@Override 
public void onCreate(Bundle savedInstanceState) { 
    ... 
    super.onCreate(savedInstanceState); // Crashing here MainActivity.java:190 
    ... 
} 
+1

基于堆栈跟踪,它好像FragmentManager试图获取初始化过程中它的一些从捆绑的内部状态,包试图unparcel本身,但失败了。因为捆绑内容以一种微妙的方式打破。你可以在Activity'onSaveInstanceState'的调用结束时发布Activity state Bundle的内容吗?覆盖该方法,在返回之前设置断点,然后从调试器(包括所有嵌套对象及其内容)复制* entire * Bundle内容并将其粘贴到某处供我们查看(Github Gist等)。特别注意SparseArrays。 – user1643723

+0

请注意,将Bundle中的错误放在一边,您自己的代码在这里可能会有点内疚。确保你没有以某种方式破坏Parcel数据,因为在你自己的一个Parcelables中犯了错误。 – user1643723

+0

@ user1643723我试过了,但是如何从调试器中复制某些内容以列出文本格式的所有内容? – mco

回答

4

视图状态保存和恢复的问题。 Youtube应用程序有一个错误和存储视图状态,其中包含来自youtube apk的类asc的实例。所以我们的应用程序无法恢复它,因为对这个类一无所知。我的解决办法是防止节省YoutubePlayerView视图状态YouTubePlayerSupportFragment明年代码:

@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); 
     } 
    } 
} 

此代码应添加到您的YouTubePlayerSupportFragment子类。 此解决方案不会从捆绑软件中删除youtube播放器状态。所以youtube播放器将会成功恢复。

+0

在这里尝试了很多不同的解决方案之后,这就是它的工作原理。谢谢! – dtrejogo

+0

谢谢!唯一的工作解决方案 – user1354784

+0

@xkor:getView()是做什么的? – Saggy

0

显然,这是YouTube应用的一个bug。 我建议你使用这个hack来擦除从youtube客户端传递来的bundle以避免这个分析错误。

@Override 
public void onCreate(Bundle b) { 
    if (b != null) { 
    final ClassLoader contextCl = getClassLoader(); 
    b.setClassLoader(contextCl); 
    } 
    super.onCreate(b); 
} 

该错误可能是由于YouTube库中的代码存储定制Parcelable状态包(YouTube库中的类里面可能是由ProGuard混淆,因此奇怪的名字:

@Override 
public void onCreate(Bundle b) { 
    if (b != null) { 
     b.remove("android:fragments"); 
    } 
    super.onCreate(b); 
} 
+0

我不确定,如果可以的话。堆栈跟踪导致'BaseBundle#unparcel',这并不意味着,在解析FragmentManager状态之前触发该错误*你的建议是否会在调用'remove'的过程中导致它早些发生? – user1643723

+0

当我查看BaseBundle源代码时,我的意思是相同的,但事实上,它的作用就像一个魅力,没有崩溃和日志中的任何堆栈跟踪。 PS之前放弃捆绑我得到了100%的概率发生此错误。 PSS你的类加载器设置的建议也很有趣。我会尝试检查它是如何工作的。 (尽管如此,我不需要这个包在我的执行) – Fitz

+0

你确定吗?通过省略此捆绑包,您将失去所有片段,视图和YouTube播放器库中包含的任何状态的保存状态。 – user1643723

0
按照您的onCreate代码

使用像“asc”)。

如果上述建议不起作用,沿@菲茨的建议的线条遵循和下降的状态包。不要试图在onCreate中搞砸(这不会起作用),而是最好重写onSaveInstanceState以返回Bundle.EMPTY,如果您的应用程序在进行播放时暂停。


注意,有问题的错误是在多个方面相当棘手。如果你(或YouTube应用程序)将嵌套Bundles存储在彼此之内,那么也需要设置适当的ClassLoader ...有人应该告诉Google获得一些常识,并在Bundle中使用Thread#getContextClassLoader来彻底解决这个问题。

+0

我在我的MainActivity上试过这个,没有运气,仍然发生同样的崩溃。我有MainActivity,那么带有ViewPager的片段和ViewPager的其中一个项目就是包含YouTubePlayerSupportFragment的片段 – dtrejogo

0

我发现我工作的解决方案。在我的onCreate方法中,我收到了由于YouTube播放器中的ClassNotFoundException而引发的RuntimeException。视频失去其状态。按下游戏会导致重新开始。否则照常营业。

-1

我刚刚结束了使用为我工作一个try catch块。

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); 
} 
相关问题