【问题标题】:Android multiple line notification like Gmail appAndroid 多行通知,如 Gmail 应用程序
【发布时间】:2013-12-23 17:12:01
【问题描述】:

我正在尝试像 Gmail 应用程序那样创建一个多行通知,如下图所示(5 个通知分组在一个通知下)

我尝试了各种示例,但似乎只能创建单个通知,例如

   public void createSingleNotification(String title, String messageText, String tickerttext) {
        int icon = R.drawable.notification_icon; // icon from resources
        CharSequence tickerText = tickerttext; // ticker-text
        long when = System.currentTimeMillis(); // notification time
        Context context = getApplicationContext(); // application Context
        CharSequence contentTitle = title; // expanded message title
        CharSequence contentText = messageText; // expanded message text
        Intent notificationIntent = new Intent(this, MainActivity.class);

        Bundle xtra = new Bundle();
        xtra.putString("title", title);
        xtra.putString("message", messageText);

        notificationIntent.putExtras(xtra);
        PendingIntent contentIntent = PendingIntent.getActivity(this, 0,
          notificationIntent, PendingIntent.FLAG_ONE_SHOT
            + PendingIntent.FLAG_UPDATE_CURRENT);
        String ns = Context.NOTIFICATION_SERVICE;

        NotificationManager mNotificationManager = (NotificationManager) getSystemService(ns);
        Notification notification = new Notification(icon, tickerText, when);
        notification.setLatestEventInfo(context, contentTitle, contentText,   contentIntent);
        notification.defaults |= Notification.DEFAULT_LIGHTS;
        notification.defaults |= Notification.DEFAULT_SOUND;
        notification.defaults |= Notification.FLAG_AUTO_CANCEL;
        notification.flags = Notification.DEFAULT_LIGHTS
          | Notification.FLAG_AUTO_CANCEL;
        final int HELLO_ID = 0;
        mNotificationManager.notify(HELLO_ID, notification);
      }

我不确定如何创建可以添加行的通知组。

【问题讨论】:

标签: android android-notifications


【解决方案1】:
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this)
    .setSmallIcon(R.drawable.notification_icon)
    .setContentTitle("Event tracker")
    .setContentText("Events received")
NotificationCompat.InboxStyle inboxStyle =
        new NotificationCompat.InboxStyle();

String[] events = {"line 1","line 2","line 3","line 4","line 5","line 6"};
// Sets a title for the Inbox in expanded layout
inboxStyle.setBigContentTitle("Event tracker details:");
...
// Moves events into the expanded layout
for (int i=0; i < events.length; i++) {
    inboxStyle.addLine(events[i]);
}
// Moves the expanded layout object into the notification object.
mBuilder.setStyle(inboxStyle);

...
// Issue the notification here.

【讨论】:

  • 那么事件从哪里来的String数组是空的?
  • 很好的例子!谢谢。
  • 很好的例子!谢谢。
【解决方案2】:

您正在寻找“大视图样式”,如下所示:

相关文档:

【讨论】:

  • 谢谢,很高兴知道它被称为大视图通知。我发现的所有教程都一次创建了一个包含多行的通知。我想要一种用单行创建通知的方法,然后在需要时添加更多行。
  • 链接到Big View
【解决方案3】:

这里我得到了解决方案:确保在通知关闭时创建 BrodCast Reciever 以清除数组堆栈

    static ArrayList<String> notifications = new ArrayList<>();

private static void sendNotification(String messageBody,Context cxt) {

    //onDismiss Intent
    Intent intent = new Intent(cxt, MyBroadcastReceiver.class);
    PendingIntent broadcastIntent = PendingIntent.getBroadcast(cxt.getApplicationContext(), 0, intent, 0);

    //OnClick Listener
    startWFApplication().addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    PendingIntent pendingIntent = PendingIntent.getActivity(cxt, 0, startWFApplication(),
            PendingIntent.FLAG_ONE_SHOT);

    Uri defaultSoundUri= RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(cxt)
            .setSmallIcon(R.drawable.fevicon)
            .setContentTitle("Title")
            .setContentText(messageBody)
            .setAutoCancel(true)
            .setSound(defaultSoundUri)
            .setContentIntent(pendingIntent);
    NotificationCompat.InboxStyle inboxStyle =
            new NotificationCompat.InboxStyle();
    // Sets a title for the Inbox in expanded layout
    inboxStyle.setBigContentTitle("Title - Notification");
    inboxStyle.setSummaryText("You have "+notifications.size()+" Notifications.");
    // Moves events into the expanded layout
    notifications.add(messageBody);
    for (int i=0; i < notifications.size(); i++) {
        inboxStyle.addLine(notifications.get(i));
    }
    // Moves the expanded layout object into the notification object.
    notificationBuilder.setStyle(inboxStyle);

    NotificationManager notificationManager =
            (NotificationManager) cxt.getSystemService(Context.NOTIFICATION_SERVICE);

    notificationManager.notify(0, notificationBuilder.build());
    notificationBuilder.setDeleteIntent(broadcastIntent);
}
public static Intent startWFApplication(){
    Intent launchIntent = new Intent();
    launchIntent.setComponent(new ComponentName("your.package", "Yyour.package.servicename"));
    return launchIntent;
}

BroadCastReciever 看起来像这样:

public class MyBroadcastReceiver extends BroadcastReceiver {
  @Override
  public void onReceive(Context context, Intent intent) {
        Notification.notifications.clear();
     }

  }

在清单中放这个:

    <receiver
    android:name="your.package.MyBroadcastReceiver"
    android:exported="false" >
    </receiver>

【讨论】:

  • 但我认为当我从最近清除应用程序时通知列表将变为空
  • 我应用了上面的代码,当我使用 FCM concole 发送消息时,它没有显示像 gmail 应用程序这样的通知。
  • 它正在工作,谢谢 :-) 但仅在应用程序处于前台时工作,当应用程序处于后台时不工作。
  • @FirdoshAnsari 我认为您需要确保广播接收器是否正常工作。每次点击服务时尝试放置一些日志,看看你的日志是否生成。
【解决方案4】:

我知道很久以前就有人问过这个问题,可能很多像我这样的用户也在这里搜索过,但我会以这种方式给出完整的通知代码。想象一个场景,您有一个聊天应用程序,并且您希望获得按每个用户分组的通知!每个用户的通知。因此,最好的方法是通过唯一的用户 ID 进行通知,因此您必须编写一个代码来通知,因为如果您的目标是低于 API 级别 23,那么您无法猜测此时存在多少通知,这几乎很多用户看不见。那么当你想对每个收到通知的用户进行分组并保持逻辑时,你应该怎么做?我这样做的最好方法是使用带有一些轻微逻辑的共享首选项,让我使用 cmets 发布代码。

(通过这个你定位到较低的 API,所以 KitKat 也会处理这个逻辑)

模拟通知作为测试的类。

/**
 * Simple id just for test
 */
private int NOTIFICATION_ID = 1;
private static int value = 0;
Notification.InboxStyle inboxStyle = new Notification.InboxStyle();
private NotificationCompat.Builder mCopat;
private Bitmap bitmap;
private SharedPreferences sharedPreferences;
private SharedPreferences.Editor editor;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main2);
    bitmap = BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher);
    mCopat = new NotificationCompat.Builder(getApplicationContext());

    /**
     * Here we create shared preferences.Probably you will create some helper class to access shared preferences from everywhere
     */
    sharedPreferences = getSharedPreferences("shared", MODE_PRIVATE);
    editor = sharedPreferences.edit();

    /**
     * I clear this for test purpose.
     */
    editor.clear();
    editor.commit();
}


public void hey(View view) {

    /**
     * Add notification,let`s say add 4 notifications with same id which will be grouped as single and after it add the rest which will be grouped as new notification.
     */
    int clickedTime = value++;
    if (clickedTime == 4) {
        NOTIFICATION_ID++;
    }


    /**
     * Here is the important part!We must check whether notification id inserted inside the shared preferences or no.If inserted IT MEANS THAT WE HAVE an notification
     * to where we should add this one (add the new one to the existing group in clear way)
     */
    if (sharedPreferences.getString(String.valueOf(NOTIFICATION_ID), null) != null) {
        Log.d("fsafsafasfa", "hey: " + "not null adding current");

        /**
         * TAKE A NOTICE YOU MUST NOT CREATE A NEW INSTANCE OF INBOXSTYLE, OTHERWISE, IT WON`T WORK. JUST ADD VALUES TO EXISTING ONE
         */

        NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification.Builder builder = new Notification.Builder(this);
        builder.setContentTitle("Lanes");
        builder.setContentText("Notification from Lanes " + value);
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setLargeIcon(bitmap);
        builder.setAutoCancel(true);

        /**
         * By this line you actually add an value to the group,if the notification is collapsed the 'Notification from Lanes' text will be displayed and nothing more
         * otherwise if it is expanded the actual values (let`s say we have 5 items added to notification group) will be displayed.
         */
        inboxStyle.setBigContentTitle("Enter Content Text");
        inboxStyle.addLine("hi events " + value);


        /**
         * This is important too.Send current notification id to the MyBroadcastReceiver which will delete the id from sharedPrefs as soon as the notification is dismissed
         * BY USER ACTION! not manually from code.
         */
        Intent intent = new Intent(this, MyBroadcastReceiver.class);
        intent.putExtra("id", NOTIFICATION_ID);


        PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);

        /**
         * Simply set delete intent.
         */
        builder.setDeleteIntent(pendingIntent);
        builder.setStyle(inboxStyle);
        nManager.notify("App Name", NOTIFICATION_ID, builder.build());

        /**
         * Add id to shared prefs as KEY so we can delete it later
         */
        editor.putString(String.valueOf(NOTIFICATION_ID), "notification");
        editor.commit();
    } else {

        /***
         * Here is same logic EXCEPT that you do create an INBOXSTYLE instance so the values are added to actually separate notification which will just be created now!
         * The rest logic is as same as above!
         */

        /**
         * Ok it gone to else,meaning we do no have any active notifications to add to,so just simply create new separate notification 
         * TAKE A NOTICE to be able to insert new values without old ones you must call new instance of InboxStyle so the old one will not take the place in new separate
         * notification.
         */
        Log.d("fsafsafasfa", "hey: " + " null adding new");
        inboxStyle = new Notification.InboxStyle();
        NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
        Notification.Builder builder = new Notification.Builder(this);
        builder.setContentTitle("Lanes");
        builder.setContentText("Notification from Lanes " + value);
        builder.setSmallIcon(R.mipmap.ic_launcher);
        builder.setLargeIcon(bitmap);
        builder.setAutoCancel(true);
        inboxStyle.setBigContentTitle("Enter Content Text");
        inboxStyle.addLine("hi events " + value);

        Intent intent = new Intent(this, MyBroadcastReceiver.class);
        intent.putExtra("id", NOTIFICATION_ID);
        PendingIntent pendingIntent = PendingIntent.getBroadcast(this.getApplicationContext(), 0, intent, PendingIntent.FLAG_ONE_SHOT);
        builder.setDeleteIntent(pendingIntent);

        builder.setStyle(inboxStyle);
        nManager.notify("App Name", NOTIFICATION_ID, builder.build());
        editor.putString(String.valueOf(NOTIFICATION_ID), "notification");
        editor.commit();

    }

}
}

删除意图的广播接收器。不要忘记在清单中添加接收器!

public class MyBroadcastReceiver extends BroadcastReceiver {

/**
 * Receive swipe/dismiss or delete action from user.This will not be triggered if you manually cancel the notification.
 * @param context
 * @param intent
 */
@Override
public void onReceive(Context context, Intent intent) {

    /**
     * As soon as received,remove it from shared preferences,meaning the notification no longer available on the tray for user so you do not need to worry.
     */
    SharedPreferences sharedPreferences = context.getSharedPreferences("shared", context.MODE_PRIVATE);
    SharedPreferences.Editor editor = sharedPreferences.edit();
    editor.remove(String.valueOf(intent.getExtras().getInt("id")));
    editor.commit();
}
}

【讨论】:

    【解决方案5】:

    目前没有“通知组”之类的东西,而是带有多行文本的单个通知(正如已经指出的那样,这是通过 bigContentView 完成的,您想使用 Builder创建)。要更新通知以添加更多数据,只需在 BigTextStyle 中使用更大的字符串或在 InboxStyle 中使用更多行再次发布(使用相同的 ID 和标签)。

    【讨论】:

    • 谢谢我使用 BigTextStyle 创建了一个 BigView 通知。我正在研究一种更新通知中显示的消息的方法。我知道我可以使用相同的 ID 更新通知。但是有没有办法获取通知中当前显示的消息并将其保存为字符串,然后我可以在更新通知之前根据需要进行编辑。
    • 不,您必须自己跟踪该数据。发布通知对象后,您将无法真正取回其内容。
    • 谢谢,我存储数据,然后在需要时使用更新的数据创建通知。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-12-10
    • 2021-09-26
    • 1970-01-01
    • 2021-09-14
    • 1970-01-01
    相关资源
    最近更新 更多