Exoplayer音频在后台服务中无法播放

4

所以我开发了一个安卓应用程序,使用exoplayer库来流式传输音乐url。然而,在创建后台服务以在后台启用音乐流时,它不起作用,但是当我尝试将同一代码用于前台(MainActivity)时,它能工作。

安卓清单

    <?xml version="1.0" encoding="utf-8"?>
    <manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    package="com.sparrowpaul.musicservice">

    <uses-permission android:name="android.permission.INTERNET"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:roundIcon="@mipmap/ic_launcher_round"
        android:supportsRtl="true"
        android:theme="@style/AppTheme"
        tools:ignore="GoogleAppIndexingWarning">
        <activity android:name=".MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <service android:name=".BackgroundService"/>

    </application>

</manifest>

MainActivity.Java

    package com.sparrowpaul.musicservice;

    import androidx.appcompat.app.AppCompatActivity;

    import android.content.Intent;
    import android.os.Bundle;

public class MainActivity extends AppCompatActivity {



    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Intent intent = new Intent(MainActivity.this, BackgroundService.class);
        startService(intent);



    }


}

BackgroundService.java

public class BackgroundService extends Service implements ExoPlayer.EventListener {

    private Handler mainHandler;
    private RenderersFactory renderersFactory;
    private BandwidthMeter bandwidthMeter;
    private LoadControl loadControl;
    private DataSource.Factory dataSourceFactory;
    private ExtractorsFactory extractorsFactory;
    private MediaSource mediaSource;
    private TrackSelection.Factory trackSelectionFactory;
    private SimpleExoPlayer player;
    private final String streamUrl = "http://bbcwssc.ic.llnwd.net/stream/bbcwssc_mp1_ws-einws";
    private TrackSelector trackSelector;

    @Override
    public void onCreate() {
        super.onCreate();
        startPlayer();
    }

    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        startPlayer();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
    }

    public void startPlayer(){

        renderersFactory = new DefaultRenderersFactory(getApplicationContext());
        bandwidthMeter = new DefaultBandwidthMeter();
        trackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter);
        trackSelector = new DefaultTrackSelector(trackSelectionFactory);
        loadControl = new DefaultLoadControl();

        player = ExoPlayerFactory.newSimpleInstance(this, renderersFactory, trackSelector, loadControl);

        player.addListener(this);

        dataSourceFactory = new DefaultDataSourceFactory(getApplicationContext(), "ExoplayerDemo");
        extractorsFactory = new DefaultExtractorsFactory();
        mainHandler = new Handler();
        mediaSource = new ExtractorMediaSource(Uri.parse(streamUrl),
                dataSourceFactory,
                extractorsFactory,
                mainHandler,
                null);

        player.prepare(mediaSource);
    }

}
1个回答

9
你需要将服务作为前台服务启动,并为其提供通知。ExoPlayer的UI模块配备了一个PlayerNotificationManager,可帮助您进行通知
大致上,你需要在活动中将服务作为前台服务启动。然后,一旦你的服务创建了通知,你需要调用startForeground(notificationId, notification)。如果你不将其作为前台服务启动,系统将在短时间内停止你的服务。请参见这里:https://developer.android.com/guide/components/services#Foreground 下面的示例可以让你了解如何使用ExoPlayer的通知管理器。
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
  if (player == null) {
    startPlayer();
    playerNotificationManager = new PlayerNotificationManager(
        this, CHANNEL_ID, NOTIFICATION_ID,
        createMediaDescriptionAdapter(),
        new PlayerNotificationManager.NotificationListener() {
          @Override
          public void onNotificationPosted(int notificationId, Notification notification, boolean ongoing) {
            startForeground(notificationId, notification);
          }
          @Override
          public void onNotificationCancelled(int notificationId, boolean dismissedByUser) {
            if (dismissedByUser) {
              // Do what the app wants to do when dismissed by the user,
              // like calling stopForeground(true); or stopSelf();
            }
          }
    });
    playerNotificationManager.setPlayer(player);
  }
  return START_STICKY;
}

会尝试并告诉您反馈。谢谢。 - sparrow paul
嘿@marcbaechinger,我想知道在没有艺术品的情况下流式传输音频时如何隐藏播放器视图...我想隐藏黑屏或使其包裹控件。 - Pemba Tamang
@marcbaechinger 谢谢,它起作用了。我还使用了这个视频中的步骤(使用ExoPlayer构建功能丰富的媒体应用程序(Google I/O '18)https://www.youtube.com/watch?v=svdq1BWl4r8&t=1160s来完成它 - sparrow paul

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