为什么YouTube播放器API在Android 11上无法工作?

26

我尝试了这个YouTube视频中解释的如何在Android应用程序中播放YouTube视频的项目:

https://www.youtube.com/watch?v=Up9BjrIuoXY

我尝试使用运行Android 9和Android 10的设备播放YouTube视频,它们都能正常播放,但是在Android 11设备上,我在YouTube视频窗口内收到了以下消息:

"An error occurred while initializing the YouTube player"

这是MainActivity.java的代码:

package com.example.youtube;

import android.os.Bundle;

import com.google.android.material.floatingactionbutton.FloatingActionButton;
import com.google.android.material.snackbar.Snackbar;
import com.google.android.youtube.player.YouTubeBaseActivity;
import com.google.android.youtube.player.YouTubeInitializationResult;
import com.google.android.youtube.player.YouTubePlayer;
import com.google.android.youtube.player.YouTubePlayerView;

import androidx.appcompat.app.AppCompatActivity;
import androidx.appcompat.widget.Toolbar;

import android.view.View;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.Button;

import android.widget.Toast;

public class MainActivity extends YouTubeBaseActivity {

    Button play_btn;
    YouTubePlayerView youtubePlayerView;
    YouTubePlayer.OnInitializedListener onInitializedListener;

    private static final int RECOVERY_DIALOG_REQUEST = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        youtubePlayerView = findViewById(R.id.youtubeView);
        play_btn = findViewById(R.id.playvideo_btn);

        final android.app.Activity myActivity = this;

        onInitializedListener =new YouTubePlayer.OnInitializedListener() {
            @Override
            public void onInitializationSuccess(YouTubePlayer.Provider provider, YouTubePlayer youTubePlayer, boolean b) {
                youTubePlayer.loadVideo("Up9BjrIuoXY");
            }

            @Override
            public void onInitializationFailure(YouTubePlayer.Provider provider, YouTubeInitializationResult youTubeInitializationResult) {
                if (youTubeInitializationResult.isUserRecoverableError()) {
                    youTubeInitializationResult.getErrorDialog(myActivity, RECOVERY_DIALOG_REQUEST).show();
                } else {
                    String errorMessage = String.format(
                            getString(R.string.error_player), youTubeInitializationResult.toString());
                    Toast.makeText(myActivity, errorMessage, Toast.LENGTH_LONG).show();
                }
            }
        };

        play_btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                youtubePlayerView.initialize("AIzaSyZ2", onInitializedListener);
            }
        });

    }
}

安卓 11 设备的 YouTube 应用程序已更新。

希望有人能帮帮我。谢谢!


你有搜索过这个问题吗?- 查看这个答案或者这个答案。这是谷歌搜索结果- 如果你能获取更多错误细节,那会很有帮助。通过点击[编辑]将错误详情添加到你的问题中。 - Mauricio Arias Olave
在我发帖之前,我尝试过那些解决方案,但都没有成功。无论如何,感谢您的建议。我们已经决定使用UniWebView,因为iOS对这个库的支持几乎为零。我们的项目面向iOS和Android,而Google自古以来就没有更新他们的YouTube API。它使用UIWebView,而苹果拒绝了它们的商店。 - Misael L.
Misael L. 很高兴你找到了替代方案。请在自己的问题中添加答案,包括你提供的细节 - 由于评论是暂时的且可能会被删除,否则你的解决方案将会对其他遇到相同问题的人不可见。请参阅 Can I answer my own question?。谢谢。 - Mauricio Arias Olave
6个回答

53

在Android 11中,由于软件包可见性限制,如果您没有在清单文件中添加对Youtube服务的引用,SDK将无法找到它。

<queries>
   <intent>
     <action android:name="com.google.android.youtube.api.service.START" />
   </intent>
</queries>

1
非常感谢。其他人的参考资料:https://developer.android.com/about/versions/11/privacy/package-visibility - Zahra Jamshidi
更新此查询不起作用。YouTubeInitializationResult.SERVICE_INVALID @ivagarz - Jay Patel
2
哇,谢谢!你在哪里找到这个神秘的“com.google.android.youtube.api.service.START”?这个有文档记录吗? - James Allen
嗨@ivagarz,这个在哪里有文档记录? - Jorgesys

29

更新Ivagarz的回答查询标签不能在应用程序标签下工作,因此您必须将其添加到manifest标签之外,像这样

更新至Ivagarz的回答,queries标签无法在应用程序标签下工作。所以您需要将其添加到manifest标签之外,像这样:

<manifest
//permissions here
    <application
            android:allowBackup="true"
            android:icon="@mipmap/ic_launcher"
            android:label="@string/app_name"
            android:supportsRtl="true"
            android:theme="@style/AppTheme">
        </application>
        <queries>
        <intent>
         <action android:name="com.google.android.youtube.api.service.START"/>
        </intent>
        </queries>
    </manifest>

如果你遇到了"unexpected element <queries> found in <manifest>"错误,请参考以下链接:https://dev59.com/AFIG5IYBdhLWcg3wyEhG - surhidamatya

11
这是因为从Android 11(API 30+)开始,Android默认隐藏所有不属于核心系统应用/服务的其他应用和服务,您必须在Manifest.xml中明确声明需要访问特定应用程序。根据文档,这些是您无需声明需要访问的唯一应用程序:
- 您自己的应用程序。 - 某些实现核心Android功能的系统包,例如媒体提供程序。了解有关如何确定在运行您的应用程序的设备上自动显示哪些包的更多信息。 - 安装了您的应用程序的应用程序。 - 使用startActivityForResult()方法启动活动并在您的应用程序中启动活动的任何应用程序。 - 启动或绑定到您的应用程序中的服务的任何应用程序。 - 访问您的应用程序中的内容提供程序的任何应用程序。 - 具有内容提供程序的任何应用程序,其中已授予您的应用程序URI权限以访问该内容提供程序。 - 接收来自您的应用程序的输入的任何应用程序。仅当您的应用程序作为输入法编辑器提供输入时才适用此情况。
您可以通过以下3种方式声明需要访问:
...将元素添加到应用程序的清单文件中。在元素内,指定其他应用程序按包名, 按意图签名按提供程序权限
在YouTube的情况下,似乎声明按包名最有意义,如下所示(请注意-包名不是com.youtube!):
<queries>
   <package android:name="com.google.android.youtube" />
</queries>

看起来即使你只是打开一个YouTube网页链接也需要这个,我认为这是因为如果你已经安装了YouTube应用程序,它会将任何尝试打开像https://youtu.be/blah这样的东西都注册为请求YouTube应用程序,而不是Web浏览器。


6

虽然专门请求YouTube应用程序可以使用,但我认为这有点太具体了,因为如果用户安装了其他播放器(不确定是否有),则该解决方案将会失效。 我认为正确的解释是,Youtube应用程序不仅过滤https协议,还会过滤主机“youtube.com”(这很合理)。因此,通过同时指定主机,我使得Youtube应用程序在没有特定声明的情况下对我的应用程序可用:

<queries>    
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data  android:scheme="https" android:host="youtube.com" />
    </intent>
</queries>

顺便说一句,当我测试时,"youtube.com"和"youtu.be"在两种链接中都能正常使用。但为了保险起见,我在我的应用程序中都使用了这两个链接。


0

好的,最终我们决定使用UniWebView Unity包和YouTube JavaScript API。我们的项目面向iOS和Android。


0

我还不确定哪个是正确的操作,但两个选项在我使用的两个不同应用程序中都有效:

<queries>    
    <intent>
        <action android:name="android.intent.action.VIEW" />
        <data  android:scheme="https" android:host="youtube.com" />
    </intent>
</queries>

这个:

<queries>
   <intent>
     <action android:name="com.google.android.youtube.api.service.START" />
   </intent>
</queries>

我不知道哪一个是“更好的”,或者“正确”的使用方法。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接