ximsfei / Android-skin-support

Android-skin-support is an easy dynamic skin framework to use for Android, Only one line of code to integrate it. Android 换肤框架, 极低的学习成本, 极好的用户体验. "一行"代码就可以实现换肤, 你值得拥有!!!
MIT License
6.41k stars 1.08k forks source link

升4.0.5后 (AndroidX) , 加载第三方内容错误 youtube #391

Open KingsleyWu opened 4 years ago

KingsleyWu commented 4 years ago

不使用Skin或使用3.1.4版本,能正常初始化view,升级到4.0.5后无法初始化 反编译过youtube也使用的是androidx,embedded_ad_overlay布局中使用的也是普通layout 添加的依赖: implementation "skin.support:skin-support:4.0.5" implementation "skin.support:skin-support-appcompat:4.0.5" implementation "skin.support:skin-support-design:4.0.5" implementation "skin.support:skin-support-constraint-layout:4.0.5" implementation "skin.support:skin-support-cardview:4.0.5"

Application中的初始化: SkinCompatManager.withoutActivity(this) .addInflater(new SkinAppCompatViewInflater()) // 基础控件换肤初始化 .addInflater(new SkinMaterialViewInflater()) // material design .addInflater(new SkinConstraintViewInflater()) // ConstraintLayout .addInflater(new SkinCardViewInflater()) // CardView .setSkinWindowBackgroundEnable(false) // 关闭windowBackground换肤 .loadSkin(); 在recyclerView item点击时初始化 YouTubePlayerSupportFragmentX 加载youtube 的YouTubePlayerView 时 出错

YouTubePlayerSupportFragmentX youTubePlayerFragment = YouTubePlayerSupportFragmentX.newInstance(); fragmentManager.getSupportFragmentManager() .beginTransaction() .replace(viewHolder.mVideoContainer.getId(), youTubePlayerFragment) .setCustomAnimations(android.R.anim.fade_in, android.R.anim.fade_out) .commit();

出错日志: 2020-08-12 17:21:55.168 19972-19972/?E/YouTubeAndroidPlayerAPI: Error creating YouTubePlayerView com.google.android.youtube.player.internal.w$a: Exception thrown by invoked constructor in com.google.android.youtube.api.jar.client.RemoteEmbeddedPlayer at com.google.android.youtube.player.internal.w.a(Unknown Source:143) at com.google.android.youtube.player.internal.w.a(Unknown Source:4) at com.google.android.youtube.player.internal.w.a(Unknown Source:36) at com.google.android.youtube.player.internal.ac.a(Unknown Source:4) at com.google.android.youtube.player.YouTubePlayerView.a(Unknown Source:8) at com.google.android.youtube.player.YouTubePlayerView$1.a(Unknown Source:12) at com.google.android.youtube.player.internal.r.g(Unknown Source:73) at com.google.android.youtube.player.internal.r$c.a(Unknown Source:66) at com.google.android.youtube.player.internal.r$b.a(Unknown Source:4) at com.google.android.youtube.player.internal.r$a.handleMessage(Unknown Source:98) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:237) at android.app.ActivityThread.main(ActivityThread.java:7948) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075) Caused by: java.lang.reflect.InvocationTargetException at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:343) at com.google.android.youtube.player.internal.w.a(Unknown Source:41) at com.google.android.youtube.player.internal.w.a(Unknown Source:4)  at com.google.android.youtube.player.internal.w.a(Unknown Source:36)  at com.google.android.youtube.player.internal.ac.a(Unknown Source:4)  at com.google.android.youtube.player.YouTubePlayerView.a(Unknown Source:8)  at com.google.android.youtube.player.YouTubePlayerView$1.a(Unknown Source:12)  at com.google.android.youtube.player.internal.r.g(Unknown Source:73)  at com.google.android.youtube.player.internal.r$c.a(Unknown Source:66)  at com.google.android.youtube.player.internal.r$b.a(Unknown Source:4)  at com.google.android.youtube.player.internal.r$a.handleMessage(Unknown Source:98)  at android.os.Handler.dispatchMessage(Handler.java:107)  at android.os.Looper.loop(Looper.java:237)  at android.app.ActivityThread.main(ActivityThread.java:7948)  at java.lang.reflect.Method.invoke(Native Method)  at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493)  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075)  Caused by: android.view.InflateException: Binary XML file line #6 in com.google.android.youtube:layout/embedded_ad_overlay: Can't convert value at index 5 to dimension: type=0x1 Caused by: java.lang.UnsupportedOperationException: Can't convert value at index 5 to dimension: type=0x1 at android.content.res.TypedArray.getDimensionPixelSize(TypedArray.java:786) at android.view.ViewGroup$MarginLayoutParams.(ViewGroup.java:9175) at android.widget.RelativeLayout$LayoutParams.(RelativeLayout.java:1296) at android.widget.RelativeLayout.generateLayoutParams(RelativeLayout.java:1110) at android.widget.RelativeLayout.generateLayoutParams(RelativeLayout.java:89) at android.view.LayoutInflater.rInflate(LayoutInflater.java:1125) at android.view.LayoutInflater.rInflateChildren(LayoutInflater.java:1084) at android.view.LayoutInflater.inflate(LayoutInflater.java:682) at android.view.LayoutInflater.inflate(LayoutInflater.java:534) at android.view.LayoutInflater.inflate(LayoutInflater.java:481) at ptw.a(Unknown Source:26) at amqr.a(PG:16) at pin.(PG:49) at com.google.android.youtube.api.jar.client.RemoteEmbeddedPlayer.(PG:5) at com.google.android.youtube.api.jar.client.RemoteEmbeddedPlayer.(PG:36) at java.lang.reflect.Constructor.newInstance0(Native Method) at java.lang.reflect.Constructor.newInstance(Constructor.java:343) at com.google.android.youtube.player.internal.w.a(Unknown Source:41) at com.google.android.youtube.player.internal.w.a(Unknown Source:4) at com.google.android.youtube.player.internal.w.a(Unknown Source:36) at com.google.android.youtube.player.internal.ac.a(Unknown Source:4) at com.google.android.youtube.player.YouTubePlayerView.a(Unknown Source:8) at com.google.android.youtube.player.YouTubePlayerView$1.a(Unknown Source:12) at com.google.android.youtube.player.internal.r.g(Unknown Source:73) at com.google.android.youtube.player.internal.r$c.a(Unknown Source:66) at com.google.android.youtube.player.internal.r$b.a(Unknown Source:4) at com.google.android.youtube.player.internal.r$a.handleMessage(Unknown Source:98) at android.os.Handler.dispatchMessage(Handler.java:107) at android.os.Looper.loop(Looper.java:237) at android.app.ActivityThread.main(ActivityThread.java:7948) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:493) 2020-08-12 17:21:55.168 19972-19972/? E/YouTubeAndroidPlayerAPI: at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1075) 2020-08-12 17:21:55.171 19972-19972/? E/VideoBinder: onInitializationFailure: INTERNAL_ERROR 2020-08-12 17:31:59.981 19972-19972/? E/ViewRootImpl@a8ce078[MainActivity]: Surface is not valid.

KingsleyWu commented 4 years ago

最终定位到: SkinAppCompatViewInflater 的 wrapContext方法中 final boolean inheritContext = isPre21 && shouldInheritContext(context, (ViewParent) parent); 与AppCompatDelegateImpl 源码中不一致 inheritContext = (attrs instanceof XmlPullParser) // If we have a XmlPullParser, we can detect where we are in the layout ? ((XmlPullParser) attrs).getDepth() > 1 // Otherwise we have to use the old heuristic : shouldInheritContext((ViewParent) parent); 替换一致后问题解决

KingsleyWu commented 4 years ago

@ximsfei

KingsleyWu commented 4 years ago

另外SkinCompatDelegate 中的createView 方法 中的 wrapper.wrapContext(mContext, parent, attrs); 替换为 传进来的context wrapper.wrapContext(context, parent, attrs); public View createView(View parent, final String name, @NonNull Context context, @NonNull AttributeSet attrs) { if (mSkinCompatViewInflater == null) { mSkinCompatViewInflater = new SkinCompatViewInflater(); }

    List<SkinWrapper> wrapperList = SkinCompatManager.getInstance().getWrappers();
    for (SkinWrapper wrapper : wrapperList) {
        Context wrappedContext = wrapper.wrapContext(context, parent, attrs);
        if (wrappedContext != null) {
            context = wrappedContext;
        }
    }
    return mSkinCompatViewInflater.createView(parent, name, context, attrs);
}
KingsleyWu commented 4 years ago

主要出现 这种问题是因为 youtube 使用的context 是从youtube的应用中传过来的,在换肤的框架中把这个context替换成了本app的context导致获取资源获取不到

SjAndy88 commented 4 years ago

补充个

另外SkinCompatDelegate 中的createView 方法 中的 wrapper.wrapContext(mContext, parent, attrs); 替换为 传进来的context wrapper.wrapContext(context, parent, attrs); public View createView(View parent, final String name, @nonnull Context context, @nonnull AttributeSet attrs) { if (mSkinCompatViewInflater == null) { mSkinCompatViewInflater = new SkinCompatViewInflater(); }

    List<SkinWrapper> wrapperList = SkinCompatManager.getInstance().getWrappers();
    for (SkinWrapper wrapper : wrapperList) {
        Context wrappedContext = wrapper.wrapContext(context, parent, attrs);
        if (wrappedContext != null) {
            context = wrappedContext;
        }
    }
    return mSkinCompatViewInflater.createView(parent, name, context, attrs);
}

华为机器的长按弹出actionMode,会出现显示异常,原因是华为定制了actionMode样式,原因也是他说的一样,在换肤的框架中把这个context替换成了本app的context导致获取资源获取不到。 把mContext改成context就解决了。 这个问题跟了我3天时间,中间放弃了,后面通过替换方式才跟踪到问题点,上来一搜才发现有这个。 问题不好定位,一度崩溃。