Media Player controls in Notification

前端 未结 5 648
没有蜡笔的小新
没有蜡笔的小新 2021-02-01 19:14

I have written complete Music Player to stream music from the web, but I don\'t know how to put media player controls in Notification and when the screen is Lock.

I am f

相关标签:
5条回答
  • 2021-02-01 19:45

    You need to set a custom intent action, not the AudioPlayerBroadcastReceiver component class.

    Create a Intent with custom action name like this

    Intent switchIntent = new Intent("com.example.app.ACTION_PLAY");
    

    Then, register the PendingIntent Broadcast receiver

    PendingIntent pendingSwitchIntent = PendingIntent.getBroadcast(this, 100, switchIntent, 0);
    

    Then, set a onClick for the play control, do similar custom action for other controls if required.

    notificationView.setOnClickPendingIntent(R.id.btn_play_pause_in_notification, pendingSwitchIntent);
    

    Next, register the custom action in AudioPlayerBroadcastReceiver like this

    <receiver android:name="com.example.app.AudioPlayerBroadcastReceiver" >
        <intent-filter>
            <action android:name="com.example.app.ACTION_PLAY" />
        </intent-filter>
    </receiver>
    

    Finally, when play is clicked on Notification RemoteViews layout, you will receive the play action by the BroadcastReceiver

    public class AudioPlayerBroadcastReceiver extends BroadcastReceiver{
        @Override
        public void onReceive(Context context, Intent intent) {
    
            String action = intent.getAction();
    
            if(action.equalsIgnoreCase("com.example.app.ACTION_PLAY")) {
                // do your stuff to play action;
            }
        }
    }
    

    EDIT: how to set the intent filter for Broadcast receiver registered in code

    You can also set the Custom Action through Intent filter from code for the registered Broadcast receiver like this

        // instance of custom broadcast receiver
    CustomReceiver broadcastReceiver = new CustomReceiver();
    
    IntentFilter intentFilter = new IntentFilter();
    intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
    // set the custom action
    intentFilter.addAction("com.example.app.ACTION_PLAY");
    // register the receiver
    registerReceiver(broadcastReceiver, intentFilter); 
    

    check this link for more info

    https://www.binpress.com/tutorial/using-android-media-style-notifications-with-media-session-controls/165

    0 讨论(0)
  • 2021-02-01 19:45

    To achieve this you need media session and notification builber as the following :

    private void createMediaSession(){
    
        mediaSessionCompat = new MediaSessionCompat(this, "media session");
    
        stateBuilder = new PlaybackStateCompat.Builder()
                .setActions(
                        PlaybackStateCompat.ACTION_PLAY |
                                PlaybackStateCompat.ACTION_PAUSE |
                                PlaybackStateCompat.ACTION_PLAY_PAUSE |
                                PlaybackStateCompat.ACTION_SKIP_TO_NEXT |
                                PlaybackStateCompat.ACTION_SKIP_TO_PREVIOUS
                );
        mediaSessionCompat.setMediaButtonReceiver(null);
        mediaSessionCompat.setPlaybackState(stateBuilder.build());
        mediaSessionCompat.setCallback(new MediaSessionCompat.Callback() {
            @Override
            public void onPlay() {
                super.onPlay();
    
                //write code to control your music
            }
    
            @Override
            public void onPause() {
                super.onPause();
    
                //write code to control your music
            }
    
            @Override
            public void onSkipToNext() {
                super.onSkipToNext();
    
                //write code to control your music
            }
    
            @Override
            public void onSkipToPrevious() {
                super.onSkipToPrevious();
    
                //write code to control your music
            }
        });
    
        mediaSessionCompat.setActive(true);
    }
    
    private void showNotification(){
    
        notificationBuilder = new NotificationCompat.Builder(this, CHANNEL_ID);
        
        NotificationCompat.Action playPauseAction = new NotificationCompat.Action(
                icon, string,
                MediaButtonReceiver.buildMediaButtonPendingIntent(this,
                        PlaybackStateCompat.ACTION_PLAY_PAUSE)
        );
    
    
        PendingIntent contentPendingIntent = PendingIntent.getActivity(this,
                0, new Intent(this, MainActivity.class),0
        );
    
        notificationBuilder.setContentTitle("Song Title")
                .setSmallIcon(R.mipmap.ic_launcher_round)
                .setContentIntent(contentPendingIntent)
                .setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
                .addAction(playPauseAction)
                .setPriority(NotificationCompat.PRIORITY_MAX)
                .setStyle(new androidx.media.app.NotificationCompat.MediaStyle()
                        .setMediaSession(mediaSessionCompat.getSessionToken())
                        .setShowActionsInCompactView(0));
    
        notificationManager =
                (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        notificationManager.notify(0, notificationBuilder.build());
    
    }
    

    finally you need to create a broadcast receiver as the following

    public static class MyReceiver extends BroadcastReceiver {
    
        @Override
        public void onReceive(Context context, Intent intent) {
            MediaButtonReceiver.handleIntent(mediaSessionCompat, intent);
        }
    }
    

    and you should add the following dependency in the gradle

    implementation 'androidx.media:media:1.1.0'
    

    now you're ready to call the showNotification() method wherever you want to show your notification. If you still having problems you can take a look at this tutorial for your reference

    0 讨论(0)
  • 2021-02-01 19:48

    All of you PendingIntents have same requestCode. That is the primary reason why other notification actions are not working.

    Change request codes.

    PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);

    PendingIntent ppreviousIntent = PendingIntent.getService(this, 1, previousIntent, 0);
    
    PendingIntent pplayIntent = PendingIntent.getService(this, 2, playIntent, 0); 
    
    PendingIntent pnextIntent = PendingIntent.getService(this, 3, nextIntent, 0); 
    
    PendingIntent pcloseIntent = PendingIntent.getService(this, 4, closeIntent, 0);
    
    0 讨论(0)
  • 2021-02-01 19:53

    Did you find a solution? I can explain to you with another code. It's a little bit similar, but I have modified it because I am playing a Streaming Audio. Let me know if you need some help.

    I just want to share with you my showNotification() method

    private void showNotification() {
    
        if (intent.getAction().equals(Constants.ACTION.STARTFOREGROUND_ACTION)) {
    
            //Start IntentNotification
            Log.i(LOG_TAG, "Received Start Foreground Intent ");
            Intent notificationIntent = new Intent(ForegroundService.this, MainActivity.class);
            notificationIntent.setAction(Constants.ACTION.MAIN_ACTION);
    
            //With this settings you can open the same Activity without recreate.
            //But you have to put in your AndroidManifest.xml the next line: to your Activity
            //activity android:name=".MainActivity" android:launchMode="singleInstance"
    
            notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
    
            PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
                    notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
    
            //Intent for Play
            Intent playIntent = new Intent(this, ForegroundService.class);
            playIntent.setAction(Constants.ACTION.PLAY_ACTION);
            PendingIntent pplayIntent = PendingIntent.getService(this, 0, playIntent, 0);
    
            //Intent for Pause
            Intent pausaIntent = new Intent(this, ForegroundService.class);
            pausaIntent.setAction(Constants.ACTION.PAUSE_ACTION);
            PendingIntent pauseIntent = PendingIntent.getService(this, 0, pausaIntent, 0);
    
            //Intent for Close
            stopIntent = new Intent(this, ForegroundService.class);
            stopIntent.setAction(Constants.ACTION.CLOSE_ACTION);
            PendingIntent closeIntent = PendingIntent.getService(this, 0, stopIntent, 0);
    
            //Icon for your notification
            Bitmap icon = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
    
            notifManager =
                    (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
    
    
            PendingIntent pi = PendingIntent.getActivity(getApplicationContext(), 0,
                    new Intent(getApplicationContext(), MainActivity.class),
                    PendingIntent.FLAG_UPDATE_CURRENT);
    
            // Build the notification object.
            mNotificationBuilder = new Notification.Builder(this)
                    .setContentTitle("Thinking out Loud")
                    .setContentText("Ed Sheeran")
                    .setSmallIcon(R.mipmap.ic_launcher)
                    .setLargeIcon(Bitmap.createScaledBitmap(icon, 128, 128, false))
                    .setContentIntent(pendingIntent)
                    .setOngoing(true)
                    .addAction(R.drawable.ic_play_service, "PLAY", pplayIntent) //you can set a specific icon
                    .addAction(R.drawable.ic_pause_service, "PAUSE", pauseIntent) //you can set a specific icon
                    .addAction(R.drawable.ic_close_service, "CLOSE", closeIntent);//you can set a specific icon
    
            startForeground(Constants.NOTIFICATION_ID.FOREGROUND_SERVICE, mNotificationBuilder.build());
    
        } else if (intent.getAction().equals(Constants.ACTION.PLAY_ACTION)) {
            Log.i(LOG_TAG, "Clicked Play");
    
            //Click Play notification
        } else if (intent.getAction().equals(Constants.ACTION.PAUSE_ACTION)) {
            Log.i(LOG_TAG, "Clicked PAUSE");
    
            //This is for Pause
        } else if (intent.getAction().equals(Constants.ACTION.CLOSE_ACTION)) {
            Log.i(LOG_TAG, "Clicked Close");
    
            //This is for close the NotificationService
            stopForeground(true);
    
        } else if (intent.getAction().equals(Constants.ACTION.STOPFOREGROUND_ACTION)) {
            Log.i(LOG_TAG, "Received Stop Foreground Intent");
            stopForeground(true);
    
            //Stop Notification Service
            stopSelf();
        }
    }
    

    My Constants.class

    public class Constants {
        public interface ACTION {
            public static String MAIN_ACTION = "action.main";
            public static String PREV_ACTION = "action.prev";
            public static String PLAY_ACTION = "action.play";
            public static String PAUSE_ACTION = "action.pause";
            public static String NEXT_ACTION = "action.next";
            public static String CLOSE_ACTION = "action.close";
            public static String STARTFOREGROUND_ACTION = "action.startforeground";
            public static String STOPFOREGROUND_ACTION = "action.stopforeground";
        }
    
        public interface NOTIFICATION_ID {
            public static int FOREGROUND_SERVICE = 101;
        }
    }
    
    0 讨论(0)
  • 2021-02-01 19:57

    try something like this (i used integers for actions):

    intent.putExtra("action", ACTION_EXIT);
    pendingIntent = PendingIntent.getService(this, intent.getIntExtra("action", 0), intent, PendingIntent.FLAG_UPDATE_CURRENT);
    

    in public static PendingIntent getService (Context context, int requestCode, Intent intent, int flags) the requestCode must be unique.

    0 讨论(0)
提交回复
热议问题