android - 如何在Android的音频流播放器中添加通知 Controller ?

标签 android audio push-notification exoplayer

我正在制作一个android应用。此应用程序的功能之一是从Firebase读取音乐文件并播放音乐。现在,我正在尝试使用exoplayer来做到这一点。到目前为止,我已经能够创建一个可以播放给定链接中的音乐的简单播放器。具有播放,暂停和查找功能。现在,我希望在通知栏上具有所有此功能,以便可以从那里进行控制。如何实现这一目标。这是我的代码的示例示例:

public class MainActivity extends AppCompatActivity {

    private SimpleExoPlayer exoPlayer;

    private ExoPlayer.EventListener eventListener = new ExoPlayer.EventListener() {
        @Override
        public void onTimelineChanged(Timeline timeline, Object manifest) {
            Log.i(TAG,"onTimelineChanged");
        }

        @Override
        public void onTracksChanged(TrackGroupArray trackGroups, TrackSelectionArray trackSelections) {
            Log.i(TAG,"onTracksChanged");
        }

        @Override
        public void onLoadingChanged(boolean isLoading) {
            Log.i(TAG,"onLoadingChanged");
        }

        @Override
        public void onPlayerStateChanged(boolean playWhenReady, int playbackState) {
            Log.i(TAG,"onPlayerStateChanged: playWhenReady = "+String.valueOf(playWhenReady)
                    +" playbackState = "+playbackState);
            switch (playbackState){
                case ExoPlayer.STATE_ENDED:
                    Log.i(TAG,"Playback ended!");
                    //Stop playback and return to start position
                    setPlayPause(false);
                    exoPlayer.seekTo(0);
                    break;
                case ExoPlayer.STATE_READY:
                    Log.i(TAG,"ExoPlayer ready! pos: "+exoPlayer.getCurrentPosition()
                            +" max: "+stringForTime((int)exoPlayer.getDuration()));
                    setProgress();
                    break;
                case ExoPlayer.STATE_BUFFERING:
                    Log.i(TAG,"Playback buffering!");
                    break;
                case ExoPlayer.STATE_IDLE:
                    Log.i(TAG,"ExoPlayer idle!");
                    break;
            }
        }

        @Override
        public void onPlayerError(ExoPlaybackException error) {
            Log.i(TAG,"onPlaybackError: "+error.getMessage());
        }

        @Override
        public void onPositionDiscontinuity() {
            Log.i(TAG,"onPositionDiscontinuity");
        }
    };

    private SeekBar seekPlayerProgress;
    private Handler handler;
    private ImageButton btnPlay;
    private TextView txtCurrentTime, txtEndTime;
    private boolean isPlaying = false;

    private static final String TAG = "MainActivity";

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

        prepareExoPlayerFromURL(Uri.parse("https://firebasestorage.googleapis.com/v0/b/musyc-f264f.appspot.com/o/Karone-Okarone-Minar-Rahman-Official-Music-Video-Eagle-Music.mp3?alt=media&token=a40ed28a-2970-4160-ac1d-33881e34253a"));
    }


    private void prepareExoPlayerFromURL(Uri uri){

        TrackSelector trackSelector = new DefaultTrackSelector();

        LoadControl loadControl = new DefaultLoadControl();

        exoPlayer = ExoPlayerFactory.newSimpleInstance(this, trackSelector, loadControl);

        DefaultDataSourceFactory dataSourceFactory = new DefaultDataSourceFactory(this, Util.getUserAgent(this, "exoplayer2example"), null);
        ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory();
        MediaSource audioSource = new ExtractorMediaSource(uri, dataSourceFactory, extractorsFactory, null, null);
        exoPlayer.addListener(eventListener);

        exoPlayer.prepare(audioSource);
        initMediaControls();
    }



    private void initMediaControls() {
        initPlayButton();
        initSeekBar();
        initTxtTime();
    }

    private void initPlayButton() {
        btnPlay = (ImageButton) findViewById(R.id.btnPlay);
        btnPlay.requestFocus();
        btnPlay.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                setPlayPause(!isPlaying);
            }
        });
    }

    /**
     * Starts or stops playback. Also takes care of the Play/Pause button toggling
     * @param play True if playback should be started
     */
    private void setPlayPause(boolean play){
        isPlaying = play;
        exoPlayer.setPlayWhenReady(play);
        if(!isPlaying){
            btnPlay.setImageResource(android.R.drawable.ic_media_play);
        }else{
            setProgress();
            btnPlay.setImageResource(android.R.drawable.ic_media_pause);
        }
    }

    private void initTxtTime() {
        txtCurrentTime = (TextView) findViewById(R.id.time_current);
        txtEndTime = (TextView) findViewById(R.id.player_end_time);
    }

    private String stringForTime(int timeMs) {
        StringBuilder mFormatBuilder;
        Formatter mFormatter;
        mFormatBuilder = new StringBuilder();
        mFormatter = new Formatter(mFormatBuilder, Locale.getDefault());
        int totalSeconds =  timeMs / 1000;

        int seconds = totalSeconds % 60;
        int minutes = (totalSeconds / 60) % 60;
        int hours   = totalSeconds / 3600;

        mFormatBuilder.setLength(0);
        if (hours > 0) {
            return mFormatter.format("%d:%02d:%02d", hours, minutes, seconds).toString();
        } else {
            return mFormatter.format("%02d:%02d", minutes, seconds).toString();
        }
    }

    private void setProgress() {
        seekPlayerProgress.setProgress(0);
        seekPlayerProgress.setMax((int) exoPlayer.getDuration()/1000);
        txtCurrentTime.setText(stringForTime((int)exoPlayer.getCurrentPosition()));
        txtEndTime.setText(stringForTime((int)exoPlayer.getDuration()));

        if(handler == null)handler = new Handler();
        //Make sure you update Seekbar on UI thread
        handler.post(new Runnable() {
            @Override
            public void run() {
                if (exoPlayer != null && isPlaying) {
                    seekPlayerProgress.setMax((int) exoPlayer.getDuration()/1000);
                    int mCurrentPosition = (int) exoPlayer.getCurrentPosition() / 1000;
                    seekPlayerProgress.setProgress(mCurrentPosition);
                    txtCurrentTime.setText(stringForTime((int)exoPlayer.getCurrentPosition()));
                    txtEndTime.setText(stringForTime((int)exoPlayer.getDuration()));

                    handler.postDelayed(this, 1000);
                }
            }
        });
    }

    private void initSeekBar() {
        seekPlayerProgress = (SeekBar) findViewById(R.id.mediacontroller_progress);
        seekPlayerProgress.requestFocus();

        seekPlayerProgress.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (!fromUser) {
                    // We're not interested in programmatically generated changes to
                    // the progress bar's position.
                    return;
                }

                exoPlayer.seekTo(progress*1000);
            }

            @Override
            public void onStartTrackingTouch(SeekBar seekBar) {

            }

            @Override
            public void onStopTrackingTouch(SeekBar seekBar) {

            }
        });

        seekPlayerProgress.setMax(0);
        seekPlayerProgress.setMax((int) exoPlayer.getDuration()/1000);

    }


}

最佳答案

static RemoteViews notificationView;
static Notification notification;
static NotificationManager notificationManager;

private void startNotification() {

    String ns = Context.NOTIFICATION_SERVICE;
    notificationManager = (NotificationManager) getSystemService(ns);
    notification = new Notification(R.mipmap.ic_launcher, null, System.currentTimeMillis());
    notificationView = new RemoteViews(getPackageName(), R.layout.mynotification);

    if (isPlaying) {
        notificationView.setInt(R.id.closeOnFlash, "setBackgroundResource", R.drawable.pausecontrol);
        notificationView.setViewVisibility(R.id.delete, View.GONE);
    } else {
        notificationView.setViewVisibility(R.id.delete, View.VISIBLE);
        notificationView.setInt(R.id.closeOnFlash, "setBackgroundResource", R.drawable.playcontrol);
    }

    notificationView.setTextViewText(R.id.appName, "Testing......");

    //the intent that is started when the notification is clicked (works)
    Intent notificationIntent = new Intent(this, MainActivity.class);
    PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this, 0,
            notificationIntent, 0);

    editor = preferences.edit();
    editor.putString("play", "notify");
    editor.apply();

    notification.contentView = notificationView;
    notification.contentIntent = pendingNotificationIntent;
    notification.flags |= Notification.FLAG_NO_CLEAR;

    //this is the intent that is supposed to be called when the
    //button is clicked
    Intent intentPlay = new Intent(this, switchButtonListener.class);

    notificationView.setOnClickPendingIntent(R.id.closeOnFlash, getPendingSelfIntent(this, "play", intentPlay));
    notificationView.setOnClickPendingIntent(R.id.delete, getPendingSelfIntent(this, "delete", intentPlay));

    notificationManager.notify(1, notification);
}

public static class switchButtonListener extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        if (intent.getAction().equals("play")) {
            if (exoPlayer.getPlayWhenReady()) {
                exoPlayer.setPlayWhenReady(false);
                btnPlay.setImageResource(android.R.drawable.ic_media_play);
                notificationView.setViewVisibility(R.id.delete, View.VISIBLE);
                notificationView.setInt(R.id.closeOnFlash, "setBackgroundResource", R.drawable.playcontrol);
                notificationManager.notify(1, notification);


            } else {
                exoPlayer.setPlayWhenReady(true);
                btnPlay.setImageResource(android.R.drawable.ic_media_pause);
                notificationView.setViewVisibility(R.id.delete, View.GONE);
                notificationView.setInt(R.id.closeOnFlash, "setBackgroundResource", R.drawable.pausecontrol);
                notificationManager.notify(1, notification);
            }
        } else {
            Log.e("yes..", "worlinggggggggg");
            notificationManager.cancelAll();
        }

    }
}

protected PendingIntent getPendingSelfIntent(Context context, String action, Intent intent) {
    intent.setAction(action);
    return PendingIntent.getBroadcast(context, 0, intent, 0);
}`enter code here`

它为我工作

关于android - 如何在Android的音频流播放器中添加通知 Controller ?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46563716/

相关文章:

java - 过度使用 Application 类来存储持久数据

java - 报警管理器 Android SDK

c# - Xamarin.Android 中不推荐使用某些 NotificationBuilder 方法,我应该使用哪些方法?

ios - Firebase 静默通知不会启动已关闭的 iOS 应用

java - CAPTURE_AUDIO_OUTPUT 在运行时未请求许可

java - 使用 SpringBoot 和 React Native 的提醒推送通知

java - 在 Java 类 Android 应用程序之间传递字符串数组

Android 模拟器在 MBP M1 Pro 上停止响应

python - 如何在 Ubuntu 11.04 上使用 ffmpeg 将文本文件转换为音频 (mp3)?

audio - canvas - 动画和播放声音的可点击、可触摸的矩形