Java 9 – eine Einführung: So funktioniert der Taskbar-Support

© Shutterstock.com / Profit_Image
Das kürzlich erschienene Java 9 besteht aus mehr als nur Modulen und dem Projekt Jigsaw. Über 90 sogenannte JEPs (JDK Enhancement Proposals) sind Teil von Version 9 des Java Development Kits. Im siebten Teil seiner Serie zu Java 9 stellt Michael Inden, Oracle-zertifizierter Java-Entwickler, den Taskbar-Support vor, der nicht Teil eines JEPs ist.
Die vorliegende Artikelserie zu Java 9 setzt sich aus Texten von Michael Indens Buch „Java 9 – Die Neuerungen“ zusammen, das beim dpunkt.verlag erschienen ist.
PS: Verpassen Sie nicht unsere Infografik zu Project Jigsaw!
Nachdem wir im ersten Teil dieser Blog-Serie diverse kleinere Änderungen in der Syntax der Sprache Java kennengelernt haben, schauten wir uns im zweiten Teil einige relevante Erweiterungen im JDK an, konkreter: im Process-API und den Collection-Factory-Methoden. Im dritten Teil ging es anschließend um die Ergänzungen im Stream-API, im vierten Teil besprachen wir die Erweiterungen in Optional<T>
. Im fünften Teil der Artikelserie standen die Erweiterungen der Java-Klasse LocalDate
im Fokus, in Teil sechs war die Verarbeitung von Stackframes und der Klasse StackWalker
Thema. Im siebten Teil seiner Reihe stellt Michael Inden den Taskbar-Support von Java 9 vor.
Java 9: Die Taskbar richtig nutzen
Sofern das Betriebssystem es unterstützt, ist seit JDK 9 eine Interaktion mit der Taskbar oder dem Dock möglich. Dazu wurde die Klasse java.awt.Taskbar
eingeführt, die diverse Möglichkeiten bietet, mit der Taskbar bzw. dem Dock zu interagieren.
isTaskbarSupported()
– Diese statische Methode prüft, ob die Taskbar grundsätzlich unterstützt wird.getTaskbar()
– Liefert eine Instanz einerTaskbar
.setIconImage(java.awt.Image)
– Stellt ein eigenes Icon bereit.setIconBadge(String)
– Erlaubt es, einen kleinen Hinweistext zu setzen. Für einen Mail-Client kann das etwa eine Zahl für die Anzahl neuer Nachrichten sein.requestUserAttention()
– Durch Aufruf dieser Methode kann man die Aufmerksamkeit des Benutzers auf das Programm lenken. Bei Mac OS hüpft das Programm-Icon dann im Dock, je nach Wert des zweiten Parameterscritical
auch unentwegt weiter, bis das Programm den Fokus erhält.setProgressValue()
– Steuert eine kleine Progressbar an, die in das Icon eingeblendet wird.isSupported(Feature)
– Prüft, ob das angegebene Feature unterstützt wird. Die Menge aller Features erhält man durch Aufruf vonFeature.values()
. Dabei ist Feature eineenum
-Aufzählung innerhalb der KlasseTaskbar
.
Wir wollen ein wenig mit den obigen Methoden experimentieren und erstellen ein Beispiel. Zunächst prüfen wir durch Aufruf von isTaskbarSupported()
, ob die Taskbar-Funktionalität prinzipiell unterstützt wird. Ist dies nicht der Fall, so geben wir eine Fehlermeldung aus. Ansonsten ermitteln wir eine Instanz per getTaskbar()
und starten ein paar Verarbeitungsschritte. Zunächst nutzen wir die eigene Methode showProvidedFeatures(Taskbar)
und listen alle von der Taskbar unterstützten Features auf. Zum Abschluss kommt der spannendste Teil: Zunächst modifizieren wir das Icon. Danach setzen wir verschiedene Hinweistexte und fordern zwischendurch die Aufmerksamkeit des Nutzers ein. Diesen Ablauf implementieren wir in der Methode performSomeTaskbarChanges(Taskbar)
.
Im Listing findet man diverse Aufrufe von Thread.sleep()
, die dazu dienen, die Abläufe durch die entsprechenden Pausen besser beobachtbar zu gestalten. Allerdings erfordert das auch das Behandeln oder Weiterreichen von InterruptedExceptions
. Diese können im Beispiel nicht auftreten, weil kein anderer Thread unseren Applikations-Thread per interrupt()
aufrufen kann. Deshalb behandeln wir die Exception nicht, sondern reichen sie bis zur main()
-Methode weiter. Um das Beispiel einfach zu halten, verzichte ich auch auf eine ausgeklügeltere Fehlerbehandlung für eine IOException
, die theoretisch ausgelöst werden könnte, wenn das für die nachfolgende Applikation genutzte Bild nicht gefunden würde.
public static void main(final String[] args) throws Exception { if (Taskbar.isTaskbarSupported()) { final Taskbar taskbar = Taskbar.getTaskbar(); showProvidedFeatures(taskbar); performSomeTaskbarChanges(taskbar); } else { System.out.println("Taskbar is not supported on your platform." + " Unlucky you :("); } } private static void showProvidedFeatures(final Taskbar taskbar) { System.out.println("Taskbar is supported and provides the " + "following features:"); final Consumer<Feature> checkFeatureSupport = feature -> System.out.printf("Feature %s " + "is supported: %s%n",feature, taskbar.isSupported(feature)); Arrays.stream(Feature.values()).forEach(checkFeatureSupport); } private static void performSomeTaskbarChanges(final Taskbar taskbar) throws IOException, InterruptedException { setImage(taskbar); setBadge(taskbar, "1"); requestUserAttention(taskbar, false); // springt einmal setBadge(taskbar, "2"); setBadge(taskbar, "progress"); requestUserAttention(taskbar, true); // springt fortwährend performProgressInteraction(taskbar); } private static void setImage(final Taskbar taskbar) throws IOException, InterruptedException { if (taskbar.isSupported(Feature.ICON_IMAGE)) { final InputStream imageInputStream = TaskbarExample.class.getResourceAsStream("prog.png"); final Image image = ImageIO.read(imageInputStream); taskbar.setIconImage(image); Thread.sleep(2500); } } private static void setBadge(final Taskbar taskbar, final String text) throws InterruptedException { if (taskbar.isSupported(Feature.ICON_BADGE_TEXT)) { taskbar.setIconBadge(text); Thread.sleep(1000); } } private static void requestUserAttention(Taskbar taskbar, boolean critical) throws InterruptedException { if (taskbar.isSupported(Feature.USER_ATTENTION)) { taskbar.requestUserAttention(true, critical); Thread.sleep(2500); } } private static void performProgressInteraction(final Taskbar taskbar) throws InterruptedException { if (taskbar.isSupported(Feature.PROGRESS_VALUE)) { for (int i = 0; i < 100; i++) { taskbar.setProgressValue(i); Thread.sleep(100); } } }
Der durch das obige Programm implementierte Ablauf ist exemplarisch für Mac OS in der folgenden Abbildung dargestellt. Dort sieht man jeweils den Stand nach den einzelnen Aufrufen in performTaskbarChanges(Taskbar)
.
Fazit
Die Klasse Taskbar
erlaubt eine bessere Integration von Java-Applikationen in den Desktop und ermöglicht eine Vielzahl dafür wesentlicher Aktionen, wie das Bereitstellen eines eigenen Icons, das Setzen von Hinweistexten sowie die Darstellung eines Fortschrittsbalkens. Leider sind die beschriebenen Änderungen derzeit nur in Mac OS vollständig verfügbar. Unter Windows und Linux werden sie nur in einem weniger ausgeprägten Funktionsumfang angeboten.

Neben Änderungen an der Sprache bilden auch die Erweiterungen in diversen APIs einen Schwerpunkt. Fehlen darf hier natürlich auch nicht ein Kapitel über die fundamentalste Änderung in Java 9: Project Jigsaw. Auch fortgeschrittenere Themen wie Services und die Migration bestehender Applikationen werden besprochen. Da Java 9 auch einige Auswirkungen auf Build Tools und IDEs mit sich bringt, gibt ein Kapitel einen Überblick über den derzeitigen Stand zum Tooling rund um die neue Java-Version.
„Taskbar-Support vor, der nicht Teil eines JEPs ist.“
das ist ja so nicht korrekt, in http://openjdk.java.net/jeps/272 heisst es u.a.:
Task bar/dock interactions
Request user attention: Allow an application to request the attention of the user, using platform capabilities such as blinking the application icon in the taskbar or bouncing the icon in the dock.