30

When I use notify-send to show a notification on the desktop, and then use it again to show a different notification, I have noticed that the second one only shows after the first one has disappeared.

Is there a way to get notify-send to immediately replace an existing notification with a different one?

6 Answers 6

22

You can, but you must use a patched libnotify to do so

notify-send does not have the capability to replace existing notifications before they have timed out (or disappeared). This is a known bug. However, a commenter on the bug report has posted a patch to fix it.

Installing the patched libnotify-bin from PPA

I have created a patched version of the libnotify-bin package which allows replacements in my PPA. Currently it's for Ubuntu 12.04 only, but if you need it for any other currently supported release, please post a comment and I will try my best to make it available.

To install, open a terminal and:

sudo apt-add-repository ppa:izx/askubuntu
sudo apt-get update
sudo apt-get install libnotify-bin

How to use the replacement capabilities

The patched notify-send includes two new switches, -p (or --print-id ), and -r (or --replace-id ). The --help describes them as:

  -p, --print-id                    Print the notification ID.
  -r, --replace-id=REPLACE_ID       The ID of the notification to replace.
  • With -p, each notify-send will return an ID N (number/integer).
  • Issuing another notify-send with -r N will replace the previous notification immediately.
  • For example, for bash, you can save the ID from notify-send -p ... with:

    NID=$(notify-send -p "MESSAGE-1")
    

    and then replace it with:

    notify-send -r $NID "MESSAGE-2"
    
  • You can recursively use both -p and -r in a script, as long as the -r variable is initialized to 0 at the beginning.

  • Here's a simple script that shows notifications counting from 0 to 100 at half-second intervals:

    #!/bin/bash
    NID=0
    for i in {0..100..10}    do       NID=$(notify-send -p -r $NID $i)       sleep 0.5    done
2
16

You can use the "synchronous" hint to create a "confirmation" notification that will replace previous confirmation notifications. For example:

notify-send "Message" -h string:x-canonical-private-synchronous:anything

The "x-canonical-private-synchronous" hint is specified in this document. To specify a hint, use -h type:name:value. The type here is string, name is x-canonical-private-synchronous, and it seems that the value can be whatever you want.

So if your first notification is created with that hint and the second is as well, the second will immediately replace the first. (See Animations and Durations in the documentation, in the column for "confirmation bubbles".)

4
  • string:x-canonical-private-synchronous:anything was exactly what i needed. Thanks for this answer. Also for linking to the documentation
    – avk
    Jun 30, 2017 at 8:33
  • 3
    It doesn't work with GNOME.... Jul 12, 2017 at 14:53
  • 1
    This somewhat obviously only works on ubuntu.
    – bschlueter
    Mar 18, 2019 at 1:34
  • ...and it does not work on the Ubuntu-derived Pop!_OS 22.04 May 10 at 2:29
10

X-ref:
How to force a new Notification in notify-osd to show up without waiting for the earlier one to exit?

without patches you can simply do

#!/bin/bash

for i in {0..100..10}
    do
          killall notify-osd
          notify-send "testing" $i
          sleep 1
    done

Bookmark:
How do I use 'notify-send' to immediately replace an existing notification?


Sends an error notify-osd(2592): Operation not permitted. What does that mean?

It may mean that privileges are inadequate requiring:

sudo killall notify-osd
1
  • Sends an error notify-osd(2592): Operation not permitted. What does that mean?
    – VedVals
    Nov 12, 2012 at 18:22
5

I created a simple python script that works nearly the same as notify-send but has support for --replaces-id.

notify-send.py

web: https://github.com/phuhl/notify-send.py

A python script for sending desktop notifications from the shell.

About

Libnotify is part of many scripts in the Linux world. It utilizes many of the specified features of the Desktop Notifications Specification and makes them accessible to shell-scripts. It does not however allow to replace an existing notification with the replaces-id. This is a known bug since 2008 and has a patch since 2012. The patch is still not upstream though (2018).

This python script utilizes the notify2 package and exposes the functionality to the shell.

Differences between notify-send.py and notify-send

  • In notify-send.py -h shows help instead of being the parameter for hints. For hints use --hint.
  • In notify-send.py -r ID and notify-send.py --replaces-id ID exists. In order to replace a notification call notify-send.py with the ID that was returned by the notification to be replaced.
  • notify-send.py returns the ID of the newly created notification.
  • notify-send.py --replaces-process NAME exists. Every notification that gets created with the same NAME will replace every notification before it with the same NAME. If called with this parameter notify-send.py might block, best to be called with a trailing &.

Installation

Requires python3.

git clone https://github.com/phuhl/notify-send.py
cd notify-send.py
sudo pip install notify2
sudo python setup.py install

Usage

$ notify-send.py -h
usage: notify-send.py [-h] [-u LEVEL] [-t TIME] [-a APP_NAME]
                  [-i ICON[,ICON...]] [-c TYPE[,TYPE...]]
                  [--hint TYPE:NAME:VALUE] [-r ID]
                  [--replaces-process NAME]
                  SUMMERY [BODY]

positional arguments:
      SUMMERY
      BODY

optional arguments:
      -h, --help        show this help message and exit
      -u LEVEL, --urgency LEVEL
                        Specifies the urgency level (low, normal, critical).
      -t TIME, --expire-time TIME
                        Specifies the timeout in milliseconds at which to
                        expire the notification.
      -a APP_NAME, --app-name APP_NAME
                        Specifies the app name for the icon
      -i ICON[,ICON...], --icon ICON[,ICON...]
                        Specifies an icon filename or stock icon to display.
      -c TYPE[,TYPE...], --category TYPE[,TYPE...]
                        Specifies the notification category.
      --hint TYPE:NAME:VALUE
                        Specifies basic extra data to pass. Valid typesare
                        int, double, string and byte.
      -r ID, --replaces-id ID
                        Specifies the id of the notification that should be
                        replaced.
     --replaces-process NAME
                        Specifies the name of a process that should take care
                        of replacing notifications for this process.

notify-send[.py] as root user

In order to display notifications, even if libnotify or

notify-send.py

is used from the root user these two scripts are helpful.

#!/bin/bash
username=<your username here>
if [ "$(id -u)" != "1000" ] ; then
    sudo -u $username DISPLAY=:0 DBUS_SESSION_BUS_ADDRESS=unix:path=/run/user/1000/bus notify-send.sh "$@"
else
    notify-send.sh "$@"
fi

With notify-send.sh like this:

#!/bin/bash
notify-send.py "$@" &

See also

Also take a look at my notification-daemon inspired by Dunst, but with several improvements, including the possibility of a transparent background and a notification center that stores notifications.

1
  • This solution worked for me on ubuntu 18.10. None of the other solutions seemed to work as well.
    – Dreamcat4
    Dec 26, 2018 at 18:43
0

This is a working example of Mark L's Answer:

tvpowered volume.gif

With this method a confirmation bubble is sent overlapping the top panel bar. Traditionally a notification bubble which appears lower below the top panel bar.

A notification bubble usually lasts a few seconds but in above gif the confirmation bubble is immediately replaced by the next one. The method is to call the notify-send command in a loop:

# Make volume bar using progress bar methods
VolumeBar $CurrVolume
# Ask Ubuntu: https://askubuntu.com/a/871207/307523
notify-send --urgency=critical "tvpowered" \
    -h string:x-canonical-private-synchronous:volume \
    --icon=/usr/share/icons/gnome/48x48/devices/audio-speakers.png \
    "Volume: $CurrVolume $Bar"

In above code snippet the function VolumeBar sets the variable $Bar with a progress bar based on the value passed in $CurrVolume.

0

Using gdbus call (working on Debian 10)

#!/bin/bash

last_id='0'

for i in {0..10}; do

    volume=$(( i * 10 ))

    r=$(gdbus call \
        --session \
        --dest org.freedesktop.Notifications \
        --object-path /org/freedesktop/Notifications \
        --method org.freedesktop.Notifications.Notify \
        'Xfce volume control' \
        "$last_id" \
        'audio-volume-medium-symbolic' \
        "Volume $volume%" \
        '' \
        '[]' \
        "{'x-canonical-private-synchronous': <''>, 'transient': <true>, 'value': <$volume>}" \
        2000)

    last_id="${r:8:-2}"

    sleep 0.5

done

With the help of dbus-monitor, this blog post and this question

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.