How to add button to notifications in android?

AndroidButtonWidgetNotifications

Android Problem Overview


My app plays music and when users open notifications screen by swiping from the top of the screen ( or generally from the bottom right of the screen on tablets ), I want to present them a button to stop the currently playing music and start it again if they want.

I am not planning to put a widget on the user's home screen, but just into notifications. How can I do this?

Android Solutions


Solution 1 - Android

You can create an intent for the action (in this case stop playing) and then add it as an action button to your notification.

Intent snoozeIntent = new Intent(this, MyBroadcastReceiver.class);
snoozeIntent.setAction(ACTION_SNOOZE);
snoozeIntent.putExtra(EXTRA_NOTIFICATION_ID, 0);
PendingIntent snoozePendingIntent =
        PendingIntent.getBroadcast(this, 0, snoozeIntent, 0);

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this, CHANNEL_ID)
        .setSmallIcon(R.drawable.notification_icon)
        .setContentTitle("My notification")
        .setContentText("Hello World!")
        .setPriority(NotificationCompat.PRIORITY_DEFAULT)
        .setContentIntent(pendingIntent)
        .addAction(R.drawable.ic_snooze, getString(R.string.snooze),
                snoozePendingIntent);

Please refer to the Android documentation.

Solution 2 - Android

I will try to provide a solution that I have used and most of the music player also use the same technique to show player controls in notification bar.

I am running a service which is used to manage Media Player and all its controls. Activity User control interacts with Service by sending Intents to the service for example

 Intent i = new Intent(MainActivity.this, MyRadioService.class);
        i.setAction(Constants.Player.ACTION_PAUSE);

        startService(i);

TO receive intents and perform action in Service class I am using following code in onStartCommand method of Service

 @Override
public int onStartCommand(Intent intent, int flags, int startId) {

    
    if (intent.getAction().equals(Constants.Player.ACTION_PAUSE)) {
        if(mediaPlayer.isPlaying()) {
            pauseAudio();
        }
    }
  

Now to exact answer to your question to show notification with playing controls. You can call following methods to show notification with controls.

   //    showNotification
private void startAppInForeground() {
//  Start Service in Foreground

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

// Define play control intent 
   Intent playIntent = new Intent(this, MyRadioService.class);
    playIntent.setAction(Constants.Player.ACTION_PLAY);

// Use the above play intent to set into PendingIntent
    PendingIntent pplayIntent = PendingIntent.getService(this, 0,
            playIntent, 0);

// binding play button from layout to pending play intent defined above 
views.setOnClickPendingIntent(R.id.status_bar_play, pplayIntent);
views.setImageViewResource(R.id.status_bar_play,
            R.drawable.status_bg);

Notification status = null;
 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN) {
        status = new Notification.Builder(this).build();
    }

  status.flags = Notification.FLAG_ONGOING_EVENT;
    status.icon = R.mipmap.ic_launcher;
    status.contentIntent = pendingIntent;
    startForeground(Constants.FOREGROUND_SERVICE, status);

} Hope this really helps you. And you will be able to achieve what you want. Have a Happy Coding :)

Solution 3 - Android

    // It shows buttons on lock screen (notification).

Notification notification = new Notification.Builder(context)
    .setVisibility(Notification.VISIBILITY_PUBLIC)
    .setSmallIcon(R.drawable.NotIcon)
    .addAction(R.drawable.ic_prev, "button1",ButtonOneScreen) 
    .addAction(R.drawable.ic_pause, "button2", ButtonTwoScreen)  
   .....
    .setStyle(new Notification.MediaStyle()
    .setShowActionsInCompactView(1)
    .setMediaSession(mMediaSession.getSessionToken())
    .setContentTitle("your choice")
    .setContentText("Again your choice")
    .setLargeIcon(buttonIcon)
    .build();


Please refer this for more details Click here

Solution 4 - Android

tested, working code with android Pie. These all go inside the same service class.

Show a notification:

public void setNotification() {

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
	{
	NotificationChannel channel = new NotificationChannel("a", "status", NotificationManager.IMPORTANCE_DEFAULT);
	channel.setDescription("notifications");
	notificationManager = getSystemService(NotificationManager.class);
	notificationManager.createNotificationChannel(channel);

	}
else
	notificationManager =  (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);


Receiver.service = this;
Notification.MediaStyle style = new Notification.MediaStyle();

notification = new Notification.Builder(this)
		.setSmallIcon(R.mipmap.ic_launcher)
		.setContentTitle("Notification")
		.addAction(R.drawable.close_icon,  "quit_action", makePendingIntent("quit_action"))
		.setStyle(style);

style.setShowActionsInCompactView(0);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O)
	{
	notification.setChannelId("a");
	}

// notificationManager.notify(123 , notification.build()); // pre-oreo
startForeground(126, notification.getNotification());
}

Helper function:

public PendingIntent makePendingIntent(String name)
	{
	Intent intent = new Intent(this, FloatingViewService.Receiver.class);
	intent.setAction(name);
	PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0, intent, 0);
	return pendingIntent;
	}

To handle the actions:

static public class Receiver extends BroadcastReceiver {
static FloatingViewService service;

@Override
public void onReceive(Context context, Intent intent)
	{

	String whichAction = intent.getAction();

	switch (whichAction)
		{
	
		case "quit_action":
			service.stopForeground(true);
			service.stopSelf();
			return;

		}

	}
}

You'll need to update your manifest too:

<receiver android:name=".FloatingViewService$Receiver">
        <intent-filter>
            <action android:name="quit_action" />
        </intent-filter>
    </receiver>

Solution 5 - Android

I think that beside Ankit Gupta answer, you can use MediaSession (API > 21) to add native mediaController view :

notificationBuilder
        .setStyle(new Notification.MediaStyle()
            .setShowActionsInCompactView(new int[]{playPauseButtonPosition})  // show only play/pause in compact view
            .setMediaSession(mSessionToken))
        .setColor(mNotificationColor)
        .setSmallIcon(R.drawable.ic_notification)
        .setVisibility(Notification.VISIBILITY_PUBLIC)
        .setUsesChronometer(true)
        .setContentIntent(createContentIntent(description)) // Create an intent that would open the UI when user clicks the notification
        .setContentTitle(description.getTitle())
        .setContentText(description.getSubtitle())
        .setLargeIcon(art);

Source: tutorial

you can alse create custom view and display it in the notificcation area , first answer here is great.

Solution 6 - Android

you can add button as below and can perform action on that button also i have done for me as below please check.

NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
                NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this)
                        .setSmallIcon(R.drawable.ic_logo)
                        .setAutoCancel(true)
                        .setContentTitle(name)
                        .setContentText(body)
                        .setGroupSummary(true)
                        .addAction(android.R.drawable.ic_menu_directions, "Mark as read", morePendingIntent);

//morePendingIntent(do your stuff)

  PendingIntent morePendingIntent = PendingIntent.getBroadcast(
                        this,
                        REQUEST_CODE_MORE,
                        new Intent(this, NotificationReceiver.class)
                                .putExtra(KEY_INTENT_MORE, REQUEST_CODE_MORE)
                                .putExtra("bundle", object.toString()),
                        PendingIntent.FLAG_UPDATE_CURRENT
                );

Solution 7 - Android

I don't know if this is the right way or not, but it works.

  1. Create a BroadCastReceiver class to receive the data when button is pressed.
public class MyBroadCastReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context context, Intent intent) {
        
        String log = "URI: " + intent.toUri(Intent.URI_INTENT_SCHEME);
        Log.d("my", "LOG:::::::" + log);
    }
}
  1. Now in any activity where you want to create the notification -
 Intent intent = new Intent();
        intent.setAction("unique_id");
        intent.putExtra("key", "any data you want to send when button is pressed");
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, REQUEST_CODE, intent, 0);
  1. Now use this pending intent when you are creating the notification and lastly you need to register this broadcast in order to receive it in MyBroadCastReceiver class.
BroadcastReceiver br = new MyBroadCastReceiver();
        IntentFilter filter = new IntentFilter("unique_id");
        registerReceiver(br, filter);

Now if you want to do certain things when the button is pressed, you can do so in the onReceive() method in MyBroadCastReceiver class.

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionfrankishView Question on Stackoverflow
Solution 1 - AndroidRuben MiquelinoView Answer on Stackoverflow
Solution 2 - AndroidAnkit GuptaView Answer on Stackoverflow
Solution 3 - AndroidChandsi GuptaView Answer on Stackoverflow
Solution 4 - AndroidAl RoView Answer on Stackoverflow
Solution 5 - AndroidtabebqenaView Answer on Stackoverflow
Solution 6 - AndroidYuvrajsinhJadejaView Answer on Stackoverflow
Solution 7 - AndroidSudhanshu DubeyView Answer on Stackoverflow