Blog (1)
Komentarze (3)
Recenzje (0)
@RadzikowskiPrzygotowanie programu Java dla Windows

Przygotowanie programu Java dla Windows

15.12.2013 07:02, aktualizacja: 15.12.2013 23:39

W najprostszym przypadku aby uruchomić aplikację Java na systemie Windows wystarczy dwukrotnie kliknąć plik .jar, najczęściej wygenerowany podczas budowy naszego projektu w IDE (np. Eclipse, Netbeans, Intellij). Jednak gdy przygotowujemy aplikację dla osoby trzeciej, np. naszego klienta, może pojawić się kilka komplikacji / braków oczekiwanych udogodnień (zakładamy tutaj osobę o niewielkiej wiedzy informatycznej, nie administrstora-specjalistę):

  • Klient nie posiada zainstalowanego środowiska uruchomieniowego Javy (JRE) służącego do uruchamiania aplikacji .jar.
  • Klient posiada przestarzałą wersję JRE, niekompatybilną z naszym programem.
  • Program powinien mieć instalator, który umieści aplikację "gdzieś na komputerze", a Klientowi utworzy ikony do kliknięcia na pulpicie oraz w Menu Start.

W pierwszych dwóch przypadkach nasz program po prostu nie zadziała, przy braku instalatora nie będzie odbierany jako "profesjonalny".

Aby rozwiązać te 3 problemy użyjemy:

Tutorial wykorzystuje najnowsze wersje pakietów na chwilę obecną, w tym Javę 1.7, lecz opisane kroki (po zmienieniu numerów wersji w pliku pom.xml) powinny zadziałać też dla wersji 1.6 oraz prawdopodobnie najbliższych kolejnych wydań Javy.

Cała procedura została przeprowadzona na systemie Windows, ale kroki 1. i 2. z powodzeniem można wykonać na dowolnym systemie.

Krok 1. Przygotowanie przykładowej aplikacji

W swoim ulubionym IDE stwórz nowy projekt korzystajacy z Maven-a, utwórz w nim 2 klasy - App oraz MyFrame.

package pl.com.radzikowski.developingforwindows;

import java.awt.EventQueue;

public class App {

    public static void main(String[] args) {
        EventQueue.invokeLater(new Runnable() {
            @Override
            public void run() {
                new MyFrame();
            }
        });

    }
}

package pl.com.radzikowski.developingforwindows;

import java.awt.Font;
import java.awt.Label;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;
import javax.swing.JFrame;

public class MyFrame extends JFrame {
    
    MyFrame() {
        Font font = new Font("Verdana", Font.PLAIN, 18);
        Label label = new Label("Hello (cruel) Windows World!");
        label.setFont(font);
        add(label);

        addWindowListener(new WindowAdapter() {
            @Override
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }
        });
        
        pack();
        setVisible(true);
    }
    
}

Uaktualnij plik konfiguracyjny Mavena, podając informacje odnośnie projektu oraz używanej wersji Javy. Na tym etapie plik pom.xml powinien wyglądać jak poniżej.

<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
         xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
    <modelVersion>4.0.0</modelVersion>
    <groupId>pl.com.radzikowski.developingforwindows</groupId>
    <artifactId>JavaDevelopedForWindows</artifactId>
    <packaging>jar</packaging>
    <version>1.0</version>
    <name>JavaDevelopedForWindows</name>
    <url>http://radzikowski.com.pl</url>
	
    <properties>
        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
    </properties>
	
    <build>
        <plugins>
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.5.1</version>
                <configuration>
                    <source>1.7</source>
                    <target>1.7</target>
                </configuration>
            </plugin>
		</plugins>
	</build>
</project>

Krok 2. Stworzenie pliku .exe

Kolejnym etapem jest stworzenie pliku .exe uruchamiającego nasz program. Aby uniezależnić się od tego, czy nasz klient posiada zainstalowane środowisko JRE, dołączymy jego najnowszą wersję do naszego projektu. Przy uruchomieniu pliku .exe kolejne próby uruchomienia naszego programu będą wyglądały następująco:

  • Sprawdź, czy na komputerze zainstalowane jest JRE w wersji minimum 1.7. Jeżeli tak, użyj go do uruchomienia pliku .jar.
  • Sprawdź, czy w katalogu programu znajduje się folder z JRE w wersji minimum 1.7. Jeżeli tak, użyj go do uruchomienia pliku .jar.
  • Wyświetl komunikat o braku JRE, otwóz stronę pobierania środowiska w przeglądarce.

Za wszystko to odpowiadać będzie wtyczka launch4j.

Etap 2.1. Pobierz najnowszą wersję JRE

Ze strony http://www.oracle.com/technetwork/java/javase/downloads/jre7-downloads... pobierz paczkę dla Windows x86, w momencie tworzenia tego tutoriala najnowszą wersją jest jre‑7u45-windows-i586.tar.gz.

Z paczki wypakuj (przy użyciu np. programu 7‑Zip) katalog jre1.7.0_45, przenieś go do głównego katalogu projektu. Folder po wypakowaniu powinien ważyć 110 MB.

Etap 2.2. Dodaj wtyczki przygotowujące plik .exe

W pliku pom.xml dodaj kolejne 3 wtyczki w drzewie project -> build -> plugins.

<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-resources-plugin</artifactId>
	<version>2.6</version>
	<executions>
		<execution>
			<id>copy-resources</id>
			<phase>package</phase>
			<goals>
				<goal>copy-resources</goal>
			</goals>
			<configuration>
				<outputDirectory>${project.build.directory}/jre</outputDirectory>
				<resources>          
					<resource>
						<directory>jre1.7.0_45</directory>
					</resource>
				</resources>              
			</configuration>            
		</execution>
	</executions>
</plugin>
			
<plugin>
	<groupId>org.apache.maven.plugins</groupId>
	<artifactId>maven-shade-plugin</artifactId>
	<version>2.2</version>
	<executions>
		<execution>
			<phase>package</phase>
			<goals>
				<goal>shade</goal>
			</goals>
		</execution>
	</executions>
	<configuration>
		<shadedArtifactAttached>true</shadedArtifactAttached>
		<shadedClassifierName>shaded</shadedClassifierName>
		<transformers>
			<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
				<mainClass>pl.com.radzikowski.developingforwindows.App</mainClass>
			</transformer>
		</transformers>
	</configuration>
</plugin>

<plugin>
	<groupId>com.akathist.maven.plugins.launch4j</groupId>
	<artifactId>launch4j-maven-plugin</artifactId>
	<version>1.5.1</version>
	<executions>
		<execution>
			<id>l4j-clui</id>
			<phase>package</phase>
			<goals>
				<goal>launch4j</goal>
			</goals>
			<configuration>
				<headerType>gui</headerType>
				<jar>${project.build.directory}/${project.artifactId}-${project.version}-shaded.jar</jar>
				<outfile>${project.build.directory}/JavaDevelopedForWindows.exe</outfile>
				<downloadUrl>http://java.com/download</downloadUrl>
				<classPath>
					<mainClass>pl.com.radzikowski.developingforwindows.App</mainClass>
					<preCp>anything</preCp>
				</classPath>
				<jre>
					<path>jre</path>
					<minVersion>1.7.0</minVersion>
					<jdkPreference>preferJre</jdkPreference>
				</jre>
				<versionInfo>
					<fileVersion>1.0.0.0</fileVersion>
					<txtFileVersion>${project.version}</txtFileVersion>
					<fileDescription>${project.name}</fileDescription>
					<copyright>2013 Maciej Radzikowski radzikowski.com.pl</copyright>
					<productVersion>1.0.0.0</productVersion>
					<txtProductVersion>1.0.0.0</txtProductVersion>
					<productName>${project.name}</productName>
					<companyName>Maciej Radzikowski</companyName>
					<internalName>JavaDevelopedForWindows</internalName>
					<originalFilename>JavaDevelopedForWindows.exe</originalFilename>
				</versionInfo>
			</configuration>
		</execution>
	</executions>
</plugin>

Zadania poszczególnych wtyczek:

  • maven-resources-plugin - kopiuje katalog jre1.7.0_45 do target/jre.
  • maven-shade-plugin - przygotowuje wersję pliku .jar z dołączonymi zależnościami (dependencies - akurat nie ma ich w naszym bardzo prostym, przykładowym projekcie) możliwą do uruchomienia przez podwójne kliknięcie lub konsolowym poleceniem dzięki dołączeniu informacji o nazwie klasy głównej.
  • launch4j-maven-plugin - przygotowuje właściwy plik .exe uruchamiający plik .jar w środowisku określonym wg punktów z kroku 2.

Etap 2.3. Sprawdzenie działania programu

Będąc w katalogu projektu otwórz katalog target. Powinny się tam znajdować między innymi:

  • Katalog jre
  • Plik JavaDevelopedForWindows-1.0-shaded.jar
  • Plik JavaDevelopedForWindows.exe

Spróbuj uruchomić oba ostatnie pliki. W obu przypadkach powinno pojawić się okienko:

Hello World Window
Hello World Window

Uruchomienie pliku JavaDevelopedForWindows.exe powinno się udać także po:

  • Usunięciu katalogu jre z katalogu target
  • LUB odinstalowaniu środowisk JRE i JDK.

Natomiast po wykonaniu obu powyższych operacji próba uruchomienia programu powinna zakończyć się ukazaniem komunikatu oraz otwarciem strony http://java.com/download.

Krok 3. Stworzenie instalatora

Ostatnim etapem jest stworzenie instalatora. Użyjemy do tego programu Inno Setup. Alternatywą jest ISTool, który jest graficznym interfejsem dla Inno Setup, pomocnym przy tworzeniu bardziej wyszukanego instalatora.

Uruchom program Inno Setup, wybierz opcję "Create a new script file using the Script Wizard". Zatwierdź, kliknij "Next" w pierwszym kroku wizarda. Następnie podaj podstawowe dane programu, np.:

Application Information
Application Information

W kolejnym kroku wszystkie opcje pozostaw domyślne.

Application Folder
Application Folder

W następnym kroku należy podać pliki, które mają zostać zapakowane do instalatora, a następnie przy instalacji umieszczone w docelowym katalogu. Naszym głównym plikiem wykonywalnym będzie target/JavaDevelopedForWindows.exe z naszego projektu. Musimy także dołączyć katalog target/jre (z podkatalogami) oraz oczywiście plik JavaDevelopedForWindows-1.0-shaded.jar.

Application Files
Application Files

Opcje umieszczenia ikon programu możesz dobrać według własnego uznania i potrzeb.

Application Icons
Application Icons

Zgodnie z informacją w README JRE 7 przy jego redystrybucji musimy upewnić się, że użytkownik zaakceptuje jego licencję. Są na to dwa sposoby - albo dołączamy oryginalną treść licencji i wymagamy jej akceptacji w instalatorze, albo przygotowujemy własną licencję do produktu zawierającą odnośnik do licencji JRE w paragrafie o oprogramowaniu osób trzecich. Choć pewnie zazwyczaj będziemy używać tej drugiej opcji, tu na potrzeby naszego małego przykładu po prostu dołączymy licencję Oracle. Jak widzimy w pliku jre1.7.0_45/LICENSE, znajdziemy ją pod adresem http://java.com/license. Skopiuj ją do pliku .txt, a następnie dodaj w kolejnym oknie kreatora.

Application Documentation
Application Documentation

W kolejnym kroku warto wybrać język polski plus ew. inne jako języki instalatora. Dalej w opcjach instalatora możemy wybrać pulpit lub nasz projekt jako folder stworzenia pliku instalatora, oraz dostosować nazwę pliku. Jeżeli wizard zapyta nas o użycie dyrektyw #define, opcję tą można zostawić zaznaczoną dla zwiększenia czytelności późniejszego skryptu instalatora. Ostatnie co nam pozostało to zakończyć kreatora, zapisać skrypt konfiguracji i go skompilować.

Krok 4. Sprawdzenie działania instalatora

Ostatnim co nam zostało to uruchomić plik Java Developed For Windows Setup.exe i klikając Dalej zainstalować program, po czym go uruchomić - klikając ikonę na pulpicie lub w Menu Start.

Uwagi końcowe

Tutorial ten powstał po spędzeniu kilku dni na przemyśleniach i poszukiwaniach, w jaki sposób najlepiej przygotować program napisany w Javie dla klienta, który chce zainstalować go na Windowsie, a następnie zbieraniu wszystkich elementów w jeden projekt.

Można tu dywagować nad tym, czy tworzenie .exe nie przeczy idei wieloplatformowości Javy. Moim zdaniem - nie. Gdybym miał program okienkowy, który chciałbym upublicznić także dla mniej zaawansowanych użytkowników, umieściłbym go do pobrania w 2 wersjach - .jar i .exe taki jak powyższy. Użytkownicy Windowsa z zasady nie chcą się bawić w instalowanie dodatkowego oprogramowania, chcą mieć jak najprostszy sposób zainstalowania i używania programu. A w rzeczywistości program nadal uruchamia się w środowisku Javy. W ten sposób wszyscy zyskują naprawdę niewielkim nakładem pracy programisty.

Końcowy plik instalatora Java Developed For Windows Setup.exe dzięki spakowaniu naszego katalogu jre (który sam ważył 110 MB) ma 24.3 MB. Jest to lepszy wynik niż w przypadku uprzedniego skompresowania katalogu jre do .zip i dopiero wtedy dodaniu do instalatora, przynajmniej w moim przypadku. Wynik 24.3 MB uważam za bardzo dobry, ale można próbować dodatkowo go zmniejszyć:

Wybrane dla Ciebie
Komentarze (16)