Dependencies in App Bundle (Java)

G

gbpa005

Neues Mitglied
Thread Starter
Dabei seit
27.09.2011
Beiträge
12
Reaktionspunkte
1
Hi,
aufgrund der deutlich anziehenden Nachfrage für Macs möchte ich meine in Java geschriebene Software auch speziell angepasst herausbringen und habe vorgestern den schicken, neuen MacBook Pro ausgepackt. Ich habe mich grundlegend mit dem System vertraut gemacht und Java und XCode installiert, wobei ich derzeit weiter Eclipse auch auf dem Mac verwende. Die Anpassung des Programms ist relativ unkompliziert (Menüs etc.). Das meiste lief "Out-of-the-Box".

Kopfzerbrechen bereitet mir das Deployment. Ich konnte mit dem Jar Builder zwar bereits ein funktionierendes App Bundle generieren, aber was mache ich mit den Dependencies? Das konkrete Programm umfasst etwa 90 MB mit ca. 800 Dateien (das meiste Media), die vom Programm als relative Pfade eingelesen werden. Die Ordnerstruktur:

-meinProgramm.jar
|
- jars - bibliothek1.jar
| - bibliothek1.jar
| - ....
|
- media - .....
- .....
...

Es sind neben dem runnable jar 4 Ordner mit jar-, xml-Dateien, mp3- und png-Dateien, auf die ich File-Zugriff benötige. Müssen diese Sachen alle in den Ressources-Ordner und wie greife ich auf diese zu? Im Developer-Guide ist für Bilder das Beispiel java.awt.Toolkit.getDefaultToolkit().getImage("NSImage://your-image-name") angegeben, aber dazu müsste ich in der Applikation alle Pfade umbiegen und was ist mit den Sound- und XML-Dateien?
Meine Fragen:
1. Wie gehe ich am Besten wor?
2. Wenn ich alles im App-Bundle habe, brauche ich dann noch das Packaging, oder ist das nicht nötig?
3. Zur Installation wird das App-Bundle lediglich in den Programme-Ordner im Finder gezogen, oder?
4. Wie kann ich einzelne Dateien im Bundle updaten (evtl. nachgeschobene Fehlerbehebungen etc.).

Herzlichen Dank und viele Grüße,
gbpa005
 
Rückfrage: Wird eine Applikation in diese Dateien schreiben? Oder geht es um reinen Lesezugriff?
 
Es geht um reinen Lesezugriff. Die Nutzerdaten werden in einem Verzeichnis unter user.home abgelegt (ist das die richtige Systemvariable?). Programmeinstellungen speichere ich mit Preferences (keine Ahnung wo das beim Mac landet; bei Windows ist es die Registry). In das App Bundle wird nicht geschrieben.
 
Das AppBundle ist ja lediglich eine Ordnerstruktur, die du mit einem ant target erstellen kannst. Google mal danach, es gibt da m.E. fertige Beispiele.
Wenn die Anwendung sehr umfangreich ist kann es sich lohnen, mit dem Package Maker (https://developer.apple.com/library...MakerUserGuide/Introduction/Introduction.html) einen Mac-spezifischen Installer / Updater zu bauen. Der kann dann z.. alle R/O Ressourcen in das AppBundle setzen und nach /Applications installieren und die R/W Ressourcen in das passende Verzeichnis im Benutzerprofil und fragt bei Bedarf von alleine nach dem Admin-Passwort.
Du könntest auch izypack nehmen, das wäre ein plattformübergreifender Installer, ich weiss aber nicht, ob der die Probleme mit den unterschiedlichen Berechtigungen auf das /Application Verzeichnis so schön löst wie der Package Maker. Aber auch bei den neuen Windows-Versionen musst du ja unterscheiden zwischen Daten in "Program Files" und den "Bewegungsdaten" im ProgramData-Verzeichnis oder im User-Profil...

Edit: ich war zu langsam...
 
Zuletzt bearbeitet:
Vielen Dank für die Hinweise. Die Nutzer- und die Programmdaten habe ich bereits sauber getrennt. Was mir noch große Schwierigkeiten bereitet ist der Zugriff auf Dateien im App-Bundle. Es ist ja letztlich eine Ordnerstruktur, oder? Ist es möglich, die Dateien über einen relativen Pfad einzulesen?
 
Zu den Preferences: http://stackoverflow.com/questions/675864/where-are-java-preferences-stored-on-mac-os-x
Zu den Daten im Bundle: mit relativem Pfad wirst du nur zugreifen können, wenn du im JarBundler das Ausführungsverzeichnis nicht auf das Userverzeichnis umbiegst (was glaube ich Standard ist - sitze gerade nicht vor einem Mac). Du könntest auch mit absolutem Pfad zugreifen, versuche mal:
Code:
new File(DEINEKLASSE.class.getProtectionDomain().getCodeSource().getLocation().toURI().getPath());
Einfacher ist es vermutlich, wenn du die benötigten Dateien nicht im Bundle speicherst sondern "sytemweit" in /Library/DeineApp (auf Windowas: "ProgramData") ablegst. Dann kann der User die App hinlegen wo er will und du weisst immer, wo die Daten sind. Allerdings benötigst du dann auch einen Installer und kanst das Bundle nicht mehr einfach so verteilen...
 
.. dann müsstest du ja mit
Code:
String current = new java.io.File( "." ).getCanonicalPath();
im Bundle landen....

Um deine Frage zu beantworten: eigentlich ja, testen kann ich erst heute abend ;-)
 
Zuletzt bearbeitet:
Herzlichen Dank für Deine Hilfe! Ich werde einmal mit einem kleinen Demo ein paar Versuche machen und melde mich, wenn es geklappt hat.
 
http://fjep.sourceforge.net/
damit kannst du deine Dependencies in deine Haupt jar mit rein Packen. Legst du am besten in einen Lib Ordner neben src in Eclipse.

Brauchst du zb das Home dann nimmst du:
http://docs.oracle.com/javase/1.4.2/docs/api/java/lang/System.html#getProperties()
da kannst du dir Plattformunabhängig home username usw liefern lassen.

Speichern von Preferences sollte man mit:
http://docs.oracle.com/javase/1.4.2/docs/guide/lang/preferences.html
machen.

Das schöne an java, hat man sauber gearbeitet läuft es überall. Hat man es nicht wird man bestraft.
 
Ok, ich hab's raus. Bei Java-Anwendungen müssen die Ressourcen, die sonst im Arbeitsverzeichnis liegen im App-Bundel abgelegt werden, und zwar im folgenden Verzeichnis: MeinProgramm.app -> Contents -> Resources -> Java. Man kann hier beliebige Ordner an- und Dateien ablegen und direkt mit relativen Pfaden darauf zurückgreifen. Um abhängige Bibliotheken mit einzubinden muss man ein bisschen mehr tricksen, ist aber generell auch kein Problem. Hier die Anleitung, für den Fall, dass jemand das gleiche Problem haben:
1. Mit dem JarBundler ein .app-Bundel erzeugen. Wichtig: Auf dem Properties-Panel die Checkbox "Set Working Directory inside Application Bundle" aktivieren. Die abhängigen Bibliotheken lässt man erst einmal raus.
2. Jar mit der Main-Klasse auf dem Kartei-Reiter "Build Information" auswählen und Main-Klasse angeben. Sonstige Einstellungen (z. B. hübsches Icon) auswählen.
3. App-Bundle erzeugen.

Ab jetzt geht es manuell weiter:
4. Im Finder App-Bundel öffnen und in das Verzeichnis MeinProgramm.app -> Contents -> Resources -> Java die restlichen Jar-Dateien und sonstige Ressourcen kopieren.
5. Per Hand die Datei MeinProgramm.app -> Contents -> Info.plist editieren. Direkt konnte ich nicht darauf zurück greifen und musste sie erst per Zwischenablage rauskopieren und außerhalb des App-Bundles editieren. Unterhalb des Eintrags <key>ClassPath</key> neben dem Eintrag <string>$JAVAROOT/meineJarDatei.jar</string> auch Einträge der anderen abhängigen Jars eintragen. Info.plist anschließend wieder in das App-Bundle zurück kopieren.
6. App-Bundle per Doppelklick starten. Wenn die Konfiguration stimmt, dann sollte es problemlos starten.

Auf diese Weise werden die Jar-Dateien auch nicht zu groß, sodass evtl. Updates nicht zu umfangreich werden. Man muss einfach die entsprechenden Jars im App-Bundle ersetzen.

Danke für Eure Hilfe und viele Grüße,
gbpa005
 
  • Gefällt mir
Reaktionen: ruerueka
Mach Dich mal mit der Manifest-Datei und Classpath-Angaben darin vertraut...
 
Problem ist schon gelöst. Mit manifest etc. kenne ich mich sehr gut aus. Ich entwickle seit langem Jahren Java-Anwendungen. Es ging nur um die Spezifika des Deployment auf Mac und dabei spezifisch um die App-Bundles.

Vielen Dank und viele Grüße,
gbpa005
 
Noch eine Rückfrage: Wie verteilst du updates? Du solltest den Aktualisierungsprozess unbedingt auf deinem Mac mit einem User testen, der keine Admin-Rechte hat.
 
Hi,
ehrlich gesagt weiß ich noch nicht, wie ich das mit den Updates handhaben soll. Auf Windows habe ich entsprechende Lösungen parat (kleiner Installer, der mit NSIS erstellt wurde und Admin-Rechte anfordert). Derzeit wüsste ich für Mac nur folgendes: Die User müssen das App-Bundle per Hand öffnen und die veränderten Dateien hinein kopieren. Das wäre allerdings nicht sonderlich nutzerfreundlich.
Im Netz gibt es verblüffend wenige Informationen dazu, wie man in ein App-Bundle schreiben kann. Wie könnte man dabei vorgehen?

Viele Grüße,
gbpa005
 
Zurück
Oben Unten