我可以在使用 Exoplayer 开发的播客应用程序中使用媒体样式通知吗

Can I use Media Style notification with a podcast app I am developing using Exoplayer

所以我正在浏览媒体样式通知示例https://www.binpress.com/tutorial/using-android-media-style-notifications-with-media-session-controls/165,所有这些都涉及到使用 Media Player,我的问题是我可以将它与 Exoplayer 一起使用吗?

我想对我的 Exoplayer 应用程序做同样的事情。有什么想法吗?

这是我现在正在做的事情

    public class ExoPlayerService extends Service {

    private static final String TAG = ExoPlayerService.class.getSimpleName();
    private final IBinder mIBinder = new LocalBinder();

    private Handler mHandler = new Handler();
    private SimpleExoPlayer exoPlayer = null;
    //MyPlayerListener playerListener;
    PlayerListener playerListener;
    private boolean isPlayerInstantiated = false;

    public ExoPlayerService() {
        super();
    }

    public void setListener(PlayerListener listener) {
        this.playerListener = listener;
        if(!isPlayerInstantiated){
            isPlayerInstantiated = true;
            listener.onPlayerInstatiated(exoPlayer);
        }
    }


    public interface PlayerListener{
        void releasePlayer(SimpleExoPlayer exoPlayer);
        void onPlayerInstatiated(SimpleExoPlayer exoPlayer);
    }

    public class LocalBinder extends Binder {
        public ExoPlayerService getInstance() {
            // Return this instance of LocalService so clients can call public methods
            return ExoPlayerService.this;
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
            createNotification();
            Toast.makeText(this, "Service Started", Toast.LENGTH_SHORT).show();
        } else if (intent.getAction().equals(Constants.ACTION.PREV_ACTION)) {
            Toast.makeText(this, "Clicked Previous", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "Clicked Previous");
        } else if (intent.getAction().equals(Constants.ACTION.PLAY_ACTION)) {
            Toast.makeText(this, "Clicked Play", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "Clicked Play");
        } else if (intent.getAction().equals(Constants.ACTION.NEXT_ACTION)) {
            Toast.makeText(this, "Clicked Next", Toast.LENGTH_SHORT).show();
            Log.i(TAG, "Clicked Next");
        } else if (intent.getAction().equals(
                Constants.ACTION.STOPFOREGROUND_ACTION)) {
            Log.i(TAG, "Received Stop Foreground Intent");
            Toast.makeText(this, "Service Stoped", Toast.LENGTH_SHORT).show();
            stopForeground(true);
            stopSelf();
        }
        return START_STICKY;
    }


    @Override
    public void onCreate() {
        Log.d(TAG, "Service on create calledddd");
        super.onCreate();
        BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter();
        TrackSelection.Factory videoTrackSelectionFactory =
                new AdaptiveVideoTrackSelection.Factory(bandwidthMeter);
        TrackSelector trackSelector =
                new DefaultTrackSelector(mHandler, videoTrackSelectionFactory);

        // 2. Create a default LoadControl
        LoadControl loadControl = new DefaultLoadControl();

        // 3. Create the exoPlayer
        exoPlayer = ExoPlayerFactory.newSimpleInstance(getApplicationContext(), trackSelector, loadControl);
        Log.d(TAG, "EXO PLAYER CREATED IN SERVICE ");
        if(playerListener != null){
            isPlayerInstantiated = true;
            playerListener.onPlayerInstatiated(exoPlayer);
        }else{
            isPlayerInstantiated = false;
        }
    }


    public void setHandler(Handler handler)
    {
        mHandler = handler;
    }


    private NotificationCompat.Builder createNotification() {

        // Using RemoteViews to bind custom layouts into Notification
        RemoteViews views = new RemoteViews(getPackageName(), R.layout.status_bar);
        RemoteViews bigViews = new RemoteViews(getPackageName(), R.layout.status_bar_expanded);

        // showing default album image
        views.setViewVisibility(R.id.status_bar_icon, View.VISIBLE);
        views.setViewVisibility(R.id.status_bar_album_art, View.GONE);
        bigViews.setImageViewBitmap(R.id.status_bar_album_art, Constants.getDefaultAlbumArt(this));
        views.setImageViewResource(R.id.status_bar_play, R.drawable.apollo_holo_dark_pause);
        bigViews.setImageViewResource(R.id.status_bar_play, R.drawable.apollo_holo_dark_pause);

        Intent previousIntent = new Intent(this, ExoPlayerService.class);
        previousIntent.setAction(Constants.ACTION.PREV_ACTION);
        PendingIntent ppreviousIntent = PendingIntent.getService(this, 0,
                previousIntent, 0);

        Intent playIntent = new Intent(this, ExoPlayerService.class);
        playIntent.setAction(Constants.ACTION.PLAY_ACTION);
        PendingIntent pplayIntent = PendingIntent.getService(this, 0,
                playIntent, 0);

        Intent nextIntent = new Intent(this, ExoPlayerService.class);
        nextIntent.setAction(Constants.ACTION.NEXT_ACTION);
        PendingIntent pnextIntent = PendingIntent.getService(this, 0,
                nextIntent, 0);

        Intent closeIntent = new Intent(this, ExoPlayerService.class);
        closeIntent.setAction(Constants.ACTION.STOPFOREGROUND_ACTION);
        PendingIntent pcloseIntent = PendingIntent.getService(this, 0,
                closeIntent, 0);


        views.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
        bigViews.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);

        views.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);
        bigViews.setOnClickPendingIntent(R.id.status_bar_next, pnextIntent);

        views.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);
        bigViews.setOnClickPendingIntent(R.id.status_bar_prev, ppreviousIntent);

        views.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);
        bigViews.setOnClickPendingIntent(R.id.status_bar_collapse, pcloseIntent);

        views.setImageViewResource(R.id.status_bar_play, R.drawable.apollo_holo_dark_pause);
        bigViews.setImageViewResource(R.id.status_bar_play, R.drawable.apollo_holo_dark_pause);

        views.setTextViewText(R.id.status_bar_track_name, "Song Title");
        bigViews.setTextViewText(R.id.status_bar_track_name, "Song Title");
        views.setTextColor(R.id.status_bar_track_name, getResources().getColor(R.color.black));
        bigViews.setTextColor(R.id.status_bar_track_name, getResources().getColor(R.color.black));

        views.setTextViewText(R.id.status_bar_artist_name, "Artist Name");
        bigViews.setTextViewText(R.id.status_bar_artist_name, "Artist Name");
        views.setTextColor(R.id.status_bar_artist_name, getResources().getColor(R.color.black));
        bigViews.setTextColor(R.id.status_bar_artist_name, getResources().getColor(R.color.black));

        bigViews.setTextViewText(R.id.status_bar_album_name, "Album Name");
        bigViews.setTextColor(R.id.status_bar_album_name, getResources().getColor(R.color.black));

        Intent intent = new Intent(this, AudioActivity.class);
        //     intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP);

        // The stack builder object will contain an artificial back stack for the
            // started Activity.
        // This ensures that navigating backward from the Activity leads out of
        // your application to the Home screen.
        TaskStackBuilder stackBuilder = TaskStackBuilder.create(this);
        // Adds the back stack for the Intent (but not the Intent itself)
        stackBuilder.addParentStack(AudioActivity.class);
        // Adds the Intent that starts the Activity to the top of the stack
        stackBuilder.addNextIntent(intent);

        PendingIntent resultPendingIntent =
                stackBuilder.getPendingIntent(
                        0,
                        PendingIntent.FLAG_UPDATE_CURRENT
                );

        NotificationCompat.Builder status =
                new NotificationCompat.Builder(getApplicationContext());
        status.setContent(views);
        status.setContentIntent(resultPendingIntent);
        status.setCustomBigContentView(bigViews);
        status.setSmallIcon(R.drawable.ic_launcher);
        //  status.flags |= Notification.FLAG_NO_CLEAR;
        /*status.contentView = views;
        status.bigContentView = bigViews;
        status.flags = Notification.FLAG_ONGOING_EVENT;
        status.icon = R.drawable.ic_launcher;
        status.contentIntent = pendIntent;

        status.flags |= Notification.FLAG_NO_CLEAR;*/
        startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE, status.build());
        return status;
    }

    @Override
    public void onDestroy()
    {
        Log.d(TAG, "Service on destroy called !!!!!!!!!!!!");
        /*Set this to false as the player unbinds from the service on being destroyed
        this allows for a new instance of the player to be instantiated again */

        isPlayerInstantiated = false;

        if(mHandler != null)
        {
            mHandler = null;
        }

        if(playerListener != null)
            playerListener.releasePlayer(exoPlayer);
        exoPlayer = null;
    }

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

    @Override
    public boolean onUnbind(Intent intent) {

        /* Set isPlayerInstantiated = false, as this service does not get destroyed on unbinding, we want all the clients
         * binding to it to go ahead and use already create exoplayer instance */
        isPlayerInstantiated = false;
        return super.onUnbind(intent);
    }
}

之所以要用MediaStyle的方式,是因为我想自定义背景颜色,感觉它的实现风格也简单多了。

是的,您可以在 ExoPlayer 中使用 MediaStyle 通知。事实上,您需要实施一些 Best practices in media playback 包括:

  • 音频焦点
  • BECOMING_NOISY广播
  • 媒体会议
  • 一个 MediaStyle 通知
  • 服务生命周期,包括作为前台服务
  • 让您的 UI 保持同步

ExoPlayer 不会为您处理任何这些事情。

您可以将 PlayerNotificationManager 与 Exoplayer 一起使用。事实上,您可以 build feature-rich media apps with ExoPlayer 包括:

  • 通知中的播放控件和信息
  • 让你的服务前台
  • 连接媒体会话
  • 投射到其他设备
  • 缓存在线媒体以供离线播放

ExoPlayer 会为您处理所有这些事情。