Archive for the 'Java' Category

Droid Memory

Mittlerweile habe ich eine funktionsfähige “App” gebastelt. Es ist ein Memory geworden, was zwar von der Spiellogik her korrekt arbeitet, aber sich noch etwas ungelenk bedienen lässt. Tja, dann fehlt auch noch ein wenig das “Drum-herum”.
Das ganze rennt bei mir bisher im Emulator mangels realem Testgerät.

Meine erste App "Droid Memory"

Droid Memory Screenshot

Kunstverwaltung – Alpha Release

Nach längerer Überlegung gebe ich nun ein erstes Alpha Release meines Programms bekannt. (Zu finden in der Code Collection.) Vom produktiven Einsatz würde ich wohl noch absehen, weil die nötige Reife bzw. Stabilität noch nicht vollständig gegeben ist. Zum Anschauen und herumspielen sollte es erst einmal reichen. Eine initiale Datenbank habe ich beigelegt, da das Programm selbst keine eigenen Datenbanken erzeugen kann. Auch ein kleiner Readme-Text liegt bei.

Ich hoffe, dass Programm gefällt, trotz mancher Macke, die vorhanden sein mag.

WIP – Kunstverwaltung

In den letzten Tagen habe ich mich wieder um mein Programm gekümmert und vor allem versucht an der Performanceschraube zu drehen. Bei regelmäßigen Profiling-Durchläufen fiel mir auf, dass beim Anzeigen von Bildern, die während der Laufzeit skaliert wurden, der Speicherverbrauch sprunghaft anstieg und sich negativ auf die Reaktionsfähigkeit der graphischen Oberfläche auszuwirken schien.

Ich bin dann zu vorskalierten Thumbnails übergegangen, damit dies nicht überhand nimmt. Über das gesamte Wochenende habe ich mich mit diesem Thema befasst, weil es mir keine Ruhe gelassen hat. Mein Vorgehen ist dieses: existiert zu einem Bild noch kein Thumbnail im entsprechenden Ordner, dann wird das Ausgangsbild skaliert und im Thumbnails-Ordner gespeichert, um dann fortlaufend die verkleinerte Variante zu benutzen. So muss nicht andauernd ein Bild für die Vorschau bzw. für die im Programm verwendete JList skaliert bzw. im Speicher vorgehalten werden.
Trotz dessen ist das Programm, wie das WIP anzeigt work in progress – also noch nicht fertig.

kunstverwaltung 1.0

Mein (noch unfertiges) Programm

 

Multipart-Krampf

Per Mail erreichte mich eine Fragestellung, wie man in Java mittels Multipart (MIME) z.B. ein Bild hochladen kann. Das eigentliche Abspeichern des übertragenen Bildes erledigt ein PHP-Skript.
Ok, muss man also das PHP-Skript von Java aus ansprechen und die Daten durchreichen, die man sonst in ein Formular eingetragen hätte, dachte ich mir.
Der Ansatz, der mir geschickt wurde, basiert auf jenem, der sich hier findet. Neben dem eigentlichen Bild sollten noch zwei andere Dinge an das PHP-Skript gesendet werden. Dazu brauchte man eine weiter Zeile a la

wr.write (something)

Dass man dann aber ein weiteres wr.flush () verwenden sollte, kam mir nicht in den Sinn. Die Aktion mündete bei mir in einer nicht endenwollenden Versuchsserie. Alle Versuche blieben erfolglos. Heute dämmerte mir, dass es wohl nicht an den übertragenen Daten liegt, sondern eher daran, wie die Übertragung abläuft.

Damit hatte der Code dann so auszusehen:

DataOutputStream raw = new DataOutputStream(socket.getOutputStream());
OutputStreamWriter wr = new OutputStreamWriter(raw);
 
// ... viel Code dazwischen ... //
 
// HTTP Header : POST Anfrage an das PHP-Skript
wr.write(header);
// Erster Teil der MIME Daten
wr.write(command);
wr.flush();
// Uebertragung des Bildes
raw.write(theData);
raw.flush();
// Ein weiterer Teil der MIME-Daten
wr.write (command2);
wr.flush();
raw.write("senden".getBytes());
raw.flush();
// Letzter Teil der MIME Uebertragung
wr.write("\r\n--myBoundary--\r\n");
wr.flush();

Vielleicht werde ich mir das mal bei Gelegenheit in einer Klasse kapseln, falls ich das irgendwann selbst brauchen sollte.

Screenshot: Kunstverwaltung

Nach einer etwas längeren „Sendepause“ von mir, melde ich mich nun zurück. In der Zeit, wo es auf dem Blog etwas ruhiger geworden ist, war ich natürlich nicht untätig. Ich habe mich mal wieder an die Arbeiten zu meiner Datenbank-Anwendung in Java gemacht. Schließlich will ich das Programm auch zur Fertigstellung bringen.
Mittlerweile finde ich, dass ich schon einen Screenshot vorzeigen kann, auch wenn ich noch weit von dem Punkt entfernt bin, an dem ich es veröffentliche. (Ich halte mich da an das Motto: „Das Programm ist fertig, wenn es fertig ist“)

Kunstverwaltung 1.0 Screenshot

Kunstverwaltung 1.0 Screenshot


Geplant war – zu mindest nach meiner Ansicht, da ich angesprochen wurde – das Programm produktiv als Bilderverwaltung für die angefertigten Bilder von Kunsttherapieteilnehmern zu verwenden. Inzwischen kann ich wohl diesen „Traum“ oder wie man immer es nennen möge, begraben, weil man derweil zu etwas anderem gegriffen hat.
Tja, das hätte mich schon gefreut, wenn ich direkt meine eigene Software hätte an den Mann bringen können. :-(
Bisher hört das Programm auf den Namen „Kunstverwaltung 1.0“, kann zu den in der Datenbank hinterlegten Bildern die Informationen wie Künstler, Maltechnik, etc. anzeigen.

JList mit Bildern

Wer die JList [1] aus dem Swing-Paket [2] von Java kennt, dem wird mitunter aufgefallen sein, dass diese im ersten Moment nur einfachen Text als Listeneintrag zur Verfügung stellt.
Nun, für ein Programm, an dem ich zur Zeit schreibe, wollte ich allerdings sowas wie eine Vorschau haben, die zugleich die Bilder auflistet.
Mittlerweile habe ich mir was zurecht gebastelt, wovon ich denke, dass es der eine oder andere gebrauchen könnte.
Damit die JList Bilder darstellen kann, war es nötig einen eigenen ListCellRenderer [3] sowie ListModel [4] zu erstellen. Erstgenanntes wird gebraucht, um die Bilder in der Liste anzuzeigen, während anderes die Bilddaten für die Liste verwaltet.

JList mit Bildern

JList mit Bildern

Der Quellcode samt einer kleinen Beispielanwendung findet sich wie immer in der Code Collection und ist wie immer Open Source.

[1] JavaDoc JList
[2] Wikipedia Swing
[3] JavaDoc ListCellRenderer
[4] JavaDoc ListModel

Good to Know Java – HashMap’s get

Am letzten Januar-Wochenende lief bei mir Mail aus dem Forum ein. Im Forum selbst musste ich mir den gelieferten Beitrag näher betrachten, da die Angelegenheit doch etwas tricky war.
Hier mal der Code aus dem Beitrag:

import java.util.*;
 
class dummy { void dummy() {} }
 
public class AnnoyingJava {
	public static void main(String args[]) {
		Map map = new HashMap();
		short i=0;
		map.put(i,new dummy());
 
		dummy first = map.get(0);
		dummy second = map.get( (short) 0 );
 
		System.out.println("first==null? " + (first==null) );
		System.out.println("second==null? " + (second==null) );
	}
}

Eines vorweg: das Ganze ist gültiger Code, der sich ohne Probleme kompilieren und ausführen lässt. Doch, so einfach ist es nicht.

System.out.println("first==null? " + (first==null) );

wird am Ende ausgeben, das first null sei. Die zweite Ausgabe wird „second==null? false“ liefern.

Wenn 0 nicht gleich 0 ist

„Wie kann das sein?“, fragt man sich an dieser Stelle. Ok, wir haben in unsere Map [1,2] eine neue Instanz eines dummy-Objektes mit dem Schlüssel 0 abgelegt. Die Map nimmt für die Keys Werte vom Typ Short entgegen und erlaubt für die Values Objekte vom Typ dummy. (Also das, was in den spitzen Klammern angegeben ist.) Man hätte auch was anderes nehmen können, dafür gibt es seit Java 5 das Sprachmittel der Generics [3], die es erlauben Maps (und andere Collections [4]) für unterschiedliche Objekt-Typen zu verwenden.
Um dem Beitragsteller zu helfen, war ein Griff zur Dokumentation der get-Methode [5] sowie der put-Methode [6] notwendig, da mir das Verhalten von get() etwas sonderbar vorkam, da ein expliziter Cast [7] nach short notwendig wurde.
Ich stellte fest, dass get() Parameter vom Typ Object annimmt. Tja, das bedeutet im Grunde, dass man da alles reinwerfen kann, angefangen vom Short bishin zum Knäckebrot. (Ok, das Knäckebrot ist ein kleiner Scherz von mir.) Weil Object die Mutter aller Klassen in Java ist, kann jeder „Nachfahre“ davon an die Stelle gesetzt werden, wo Object beispielsweise als Funktionsparameter auftritt. Mir dämmerte das die 0 wohl nicht der short-0 entspricht und die get-Methode bei der Suche in der Map deswegen scheitert.

Im Nachgang zu dieser Geschichte, bin ich zu dem Schluss gekommen, dass man hier statt Object als Parameter für get() besser den generischen Typ K genommen hätte. Eine konsequente Verwendung der Generics bringt hier eindeutig mehr Sicherheit, denn der Java-Compiler hätte an dieser Stelle eine Fehlermeldung ausgeworfen, wenn get nur mit einer 0 gefüttert worden wäre.

Update:

Jetzt habe ich doch noch ein paar Quellen zu diesem Thema gelesen und habe nun endlich ein vernünftiges Argument dadurch erhalten, weshalb man sich entschlossen hatte, die get-Methode mit Object auszustatten. Im Grunde möchte man nur den Inhalt – sei er nun Short, String oder sonstwas – vergleichen, jedoch nicht, ob es sich auch um den gleichen Objekttyp oder abgeleiteten Objekttyp handelt. Da erschien es wohl sinnig, zu Object als Parameter für get zu wählen.

Allerdings wird man dennoch nicht umhin kommen, wenn man über einen Schlüssel an die HashMap geht, entweder einen Cast vorzunehmen bzw. eine Variable vom passenden Typ in get() zu werfen, damit es einen Wert aus der HashMap liefert.

[1] Doku. Interface Map
[2] Doku. Klasse HashMap
[3] Generics
[4] Collections
[5] Doku. HashMap get
[6] Doku. HashMap put
[7] Die Typanpassung – Java ist auch eine Insel

Playing with Java’s Native Interface 2

After feeding google with the right search words I was able to resolve the ugly runtime error, that was described in my blog entry “Playing with Java’s Native Interface”. A FAQ on the MinGW project site gave me a final hint to build a working DLL for Java.
Now, I should write down this essential detail for future purpose.

gcc -D_JNI_IMPLEMENTATION_ -Wl,--kill-at -I/path/to/Java/jdk_x/include -I/path/to/Java/jdk_x/include/win32 -shared -o HelloWorld.dll HelloWorld.c

Running MinGW again with fresh commandline instructions makes my Java program happy. So, I’m ready to enter the world of JNI.

Playing with Java’s Native Interface

Last night, I found a small tutorial about the Java Native Interface (JNI), which allows you to load and execute code written in other languages like C within your Java application. I started reading at chapter 2 Getting Started to follow up the steps of an „hello world“ – example. Writing the Java and C source was very easy, but I experienced few problems when I compiled the C code and tried to start the Java program.

For a better understanding, I post my code beneath.

Here, the Java code:

1
2
3
4
5
6
7
8
9
10
11
12
public class HelloWorld {
    static {
        // Load the HelloWorld.dll
        System.loadLibrary("HelloWorld");
    }
    // Forward declaration of the print() routine, which resides on HelloWorld.dll
    public native void print();
    public static void main(String[] args) {
        // Trying to call print() from HelloWorld.dll
        new HelloWorld().print();
    }
}

I invoked the Java compiler with java HelloWorld.java. Then I need to generate a header file for include it in my C source file. The following command will do this.

javah -jni HelloWorld

javah generates a header like this one here.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#include <jni.h>
/* Header for class HelloWorld */
 
#ifndef _Included_HelloWorld
#define _Included_HelloWorld
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     HelloWorld
 * Method:    print
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_HelloWorld_print
  (JNIEnv *, jobject);
 
#ifdef __cplusplus
}
#endif
#endif

Last but not least, the source for HelloWorld.dll

1
2
3
4
5
6
7
8
9
#include <jni.h>
#include <stdio.h>
#include "HelloWorld.h"
 
JNIEXPORT void JNICALL Java_HelloWorld_print(JNIEnv *env, jobject obj)
{
	printf("Hello World from C inside Java :-) \n");
	return;
}

Creating the library with MinGW was quit tricky, because I hadn’t any idea of the correct parameters for MinGW. After reading few sites, which deal with such subjects, I used the following comandline instruction to invoke MinGW.

gcc -IC:/path/to/java/jdk_x/include -IC:/path/to/java/jdk_x/include/win32 -A -k -shared -o HelloWorld.dll HelloWorld.c

Yeah, this creates a HelloWorld.dll, but there is one drawback. If I compile the source with this options, I will get a warning:

..\MinGW\..\..\lib\gcc\mingw32\3.4.5\..\..\..\..\mingw32\bin\ld.exe: warning: cannot find entry symbol _DllMainCRTStartup@12; defaulting to xxxxxxxx

It’s possible to run the Java application with this specific library, but a runtime exception will be raised when the application is running. Here’s an example of what I mean:

%> java HelloWorld
Hello World from C inside Java :-)
Exception in thread "main" java.lang.UnsatisfiedLinkError: HelloWorld.print()V
at HelloWorld.print(Native Method)
at HelloWorld.main(HelloWorld.java:22)
Hello World from C inside Java :-)
Hello World from C inside Java :-)
Hello World from C inside Java :-)
Hello World from C inside Java :-)
Hello World from C inside Java :-)

That’s a nasty thing. Currently, I’m looking for a solution.

JTrackbacker 1.0 Beta fertig

Heute ist es soweit: ich gebe die Betaversion meines Trackbackprogramms “JTrackbacker 1.0″ frei. Die Software ist wie immer Open Source und umsonst. :mrgreen:

Zur besseren Ansicht ein Screenshot (zum Vergrößern, bitte draufklicken):

JTrackbacker Screenshot

JTrackbacker Screenshot

JTrackbacker kann eine Liste von, ich nenne sie mal, permanenten Pings verwalten. Unter permanenten Pings verstehe ich URLs von Seiten, die bei jedem selbst verfassten Beitrag benachrichtigt werden sollen, z.B. Technorati oder ein anderes Blogverzeichnis. Sollen zusätzlich zu dieser Liste andere Blogs oder Webseiten benarchitigt werden, so kann man im Feld Trackbackadresse eine oder mehrere Trackback-URLs (bitte mit ; trennen) angeben.

In dieser Version von JTrackbacker muss man allerdings den Titel und die URL des eigenen Beitrag im Feld Beitragstitel bzw. Beitragsadresse eingeben, da ich noch keine passende Lösung gefunden habe, wie das Programm das selbständig erledigen könnte. Zudem sollte dieses Feature auch mit anderen Blogsystemen als nur WordPress funktionieren. Im Textfeld Zusammenfassung des Beitrag genügt es, wenn man ein paar Zeilen hineinkopiert oder mein schreibt eine Zusammenfassung mit seinen eigenen Worten.

Die Dialoge zu Ping Liste und Einstellungen erreicht man einfach über das Menü Programm.

Installieren lässt sich das Programm recht leicht: einfach die JAR-Datei jtrackbacker-1.0-beta.jar entpacken. Der Windowsbenutzer legt sich auf Wunsch eine Verknüpfung zur JTrackbacker.jar auf seinem Desktop an. Ein Linuxer kann sich je nach Desktopumgebung einen Starter anlegen oder schreibt sich ein kleines Shellscript (z.B. JTrackbacker wurde unter dem bin-Verzeichnis im eigenen Home-Verzeichnis entpackt):

#!/bin/bash
cd $HOME/bin/JTrackbacker/
exec java -jar JTrackbacker.jar