如何在 android 中添加按钮到通知中?

我的应用程序播放音乐,当用户从屏幕顶部(或平板电脑屏幕右下角)滑动屏幕打开通知时,我想给他们一个按钮,让他们停止当前正在播放的音乐,如果他们愿意,可以重新开始。

我并不打算在用户的主屏幕上放置一个小工具,而只是把它放到通知中。我怎么能这么做?

103920 次浏览

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.

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 :)

    // 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

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.

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>

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
);

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.