【问题标题】:Youtube player support fragment no longer working on Android studio 3.2 (androidx)Youtube 播放器支持片段不再适用于 Android Studio 3.2 (androidx)
【发布时间】:2019-03-05 17:31:48
【问题描述】:

我刚刚将我的 Android Studio 更新到 3.2 版并按照说明使用 androidx。

我一直在 Fragment 活动中使用 Youtube 片段,一切正常,但更新后,这 3 行简单的行现在给我错误“无法解析方法 'add(...)'”:

YouTubePlayerSupportFragment youTubePlayerFragment = YouTubePlayerSupportFragment.newInstance();
FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
transaction.add(R.id.youtube_fragment, youTubePlayerFragment).commit();

...当我尝试使用“替换”而不是“添加”时,它说:“错误的第二个参数类型。找到:'com.google.android.youtube.player.YouTubePlayerSupportFragment',需要:'androidx。片段.app.Fragment'"

...这让我觉得问题与新的 AndroidX 功能有关。

问题是add方法要第二个参数类型:

androidx.fragment.app.Fragment

...但是 YouTubePlayerSupportFragment 返回一个:

android.support.v4.app.Fragment

有谁知道如何解决这个问题? 有没有办法将“android.support.v4.app.Fragment”转换成“androidx.fragment.app.Fragment”?

【问题讨论】:

    标签: youtube androidx


    【解决方案1】:

    建议的解决方案不起作用,直到我尝试了来自 Bek:Pierfrancesco Soffritti's android-youtube-player 的评论,该评论得到维护并且可以顺利运行。

    【讨论】:

      【解决方案2】:

      非常感谢@Hosszuful 和@Mehdi。我听从了你的建议,效果很好。

      在我提出这个问题几周后,我将我的应用“翻译”为 Kotlin,因此,我也尝试翻译您的答案。

      这就是我最终的结果,它对我有用。

      package com.google.android.youtube.player //<--- IMPORTANT!!!!
      
      import android.os.Bundle
      import android.view.LayoutInflater
      import android.view.ViewGroup
      import androidx.fragment.app.Fragment
      import com.google.android.youtube.player.internal.ab
      import java.util.*
      
      class YouTubePlayerSupportFragmentX : Fragment(), YouTubePlayer.Provider {
          private val a = ViewBundle()
          private var b: Bundle? = null
          private var c: YouTubePlayerView? = null
          private var d: String? = null
          private var e: YouTubePlayer.OnInitializedListener? = null
          override fun initialize(var1: String, var2: YouTubePlayer.OnInitializedListener) {
              d = ab.a(var1, "Developer key cannot be null or empty")
              e = var2
              a()
          }
      
          private fun a() {
              if (c != null && e != null) {
                  c?.a(this.activity, this, d, e, b)
                  b = null
                  e = null
              }
          }
      
          override fun onCreate(var1: Bundle?) {
              super.onCreate(var1)
              b = var1?.getBundle("YouTubePlayerSupportFragment.KEY_PLAYER_VIEW_STATE")
          }
      
          override fun onCreateView(var1: LayoutInflater, var2: ViewGroup?, var3: Bundle?): android.view.View? {
              c = YouTubePlayerView(Objects.requireNonNull(this.activity), null, 0, a)
              a()
              return c
          }
      
          override fun onStart() {
              super.onStart()
              c?.a()
          }
      
          override fun onResume() {
              super.onResume()
              c?.b()
          }
      
          override fun onPause() {
              c?.c()
              super.onPause()
          }
      
          override fun onSaveInstanceState(var1: Bundle) {
              super.onSaveInstanceState(var1)
              (if (c != null) c?.e() else b)?.let { var2 ->
                  var1.putBundle("YouTubePlayerSupportFragment.KEY_PLAYER_VIEW_STATE", var2)
              }
          }
      
          override fun onStop() {
              c?.d()
              super.onStop()
          }
      
          override fun onDestroyView() {
              this.activity?.let { c?.c(it.isFinishing)  }
              c = null
              super.onDestroyView()
          }
      
          override fun onDestroy() {
              if (c != null) {
                  val var1 = this.activity
                  c?.b(var1 == null || var1.isFinishing)
              }
              super.onDestroy()
          }
      
          private inner class ViewBundle : YouTubePlayerView.b {
              override fun a(var1: YouTubePlayerView, var2: String, var3: YouTubePlayer.OnInitializedListener) {
                  e?.let { initialize(var2, it) }
              }
      
              override fun a(var1: YouTubePlayerView) {}
          }
      
          companion object {
              fun newInstance(): YouTubePlayerSupportFragmentX {
                  return YouTubePlayerSupportFragmentX()
              }
          }
      }
      

      可能有更好的方法来写下来,如果在这方面提供任何帮助,我们将不胜感激,但是,如果其他人正在寻找此问题解决方案的 Kotlin 版本,则应该使用此代码。

      PS:我会将@Mehdi 的答案保留为已接受的答案,因为他还与@Hosszuful 分享学分,而且我的答案只是他们建议的 Kotlin 版本。

      【讨论】:

        【解决方案3】:

        我通过以下代码块让它工作。

        Object obj = 
        getSupportFragmentManager().findFragmentById(R.id.youtube_player_fragment);
            if (obj instanceof YouTubePlayerSupportFragment)
                youTubePlayerFragment = (YouTubePlayerSupportFragment) obj;
        

        在调试过程中,我发现片段管理器将成为 YouTubePlayerSupportFragment 的唯一实例。但是当我写时编译器无法转换它

        (YouTubePlayerSupportFragment) 
        getSupportFragmentManager().findFragmentById(R.id.youtube_player_fragment);
        

        上面的代码块(instanceof)运行良好。

        【讨论】:

          【解决方案4】:

          替换.add

          transaction.add(R.id.youtube_fragment, youTubePlayerFragment).commit();
          

          用这个.replace

          transaction.replace(R.id.youtube_fragment, youTubePlayerFragment).commit();
          

          并将this类复制到您的项目文件夹(可能需要创建以下文件夹)

          java -> com -> google -> android -> youtube -> player -> (这里是名称) YouTubePlayerSupportFragmentX.java

          然后在代码中替换

          YouTubePlayerSupportFragmentYouTubePlayerSupportFragmentX

          【讨论】:

          • 不工作,说它仍然需要 androidx 片段。
          • 为 YoutubeLib 创建一个类并将其放在您的项目中检查更新的答案。
          • 那你的答案和上面的答案有什么不同呢?这些也很有效。
          【解决方案5】:

          我已经按照@Hosszful 的回答解决了这个问题, 我只是使用这个文件,https://gist.github.com/medyo/f226b967213c3b8ec6f6bebb5338a492

          【讨论】:

          • 这个答案和 Hosszuful 的答案不同吗?
          • 理论上是一样的 技术上,这样执行更好,只要导入文件就可以了
          【解决方案6】:

          只需将原始java文件(com.google.android.youtube.player.YouTubePlayerFragment)复制到您的项目到相同的包但不同的类名等com.google.android.youtube.player.YouTubePlayerFragmentX,并将扩展类从android.app.Fragment更新为androidx.fragment.app.Fragment

          实现是一样的:

          YouTubePlayerFragmentX youTubePlayerFragment = YouTubePlayerFragmentX.newInstance();
          FragmentTransaction transaction = getChildFragmentManager().beginTransaction();
          transaction.add(R.id.youtube_fragment, youTubePlayerFragment).commit();
          

          经过测试......它正在工作。

          【讨论】:

          • 你是从哪里找到源代码来做这个的?
          • 在 Android Studio 中只需输入类名 YouTubePlayerFragment,然后在 mac 上按 COMMAND+B,或选择 Navigate / Declaration 菜单。
          • 它充满了错误,需要访问不公开的类
          • 你的课程包是什么?它必须是 com.google.android.youtube.player 包。
          【解决方案7】:

          只需使用transaction.replace。忽略错误,它会工作。 Google 尚未将 youtube api 库重构为 androidx

          【讨论】:

          • 知道他们何时会更新库吗?
          • 最后一个 api 版本是 2015 年 10 月 14 日版本1.2.2。我认为他们不会在不久的将来更新它。
          • 官方youtube api 有问题。您可以使用自定义 youtube github.com/PierfrancescoSoffritti/android-youtube-player
          • 应用不编译时如何忽略错误。
          • 您确定这不会在将来造成任何问题吗?