Univerzální přístup ke složce AppData v Javě
V předchozím kvízu, Kvíz - Soubory v Javě, jsme si ověřili nabyté zkušenosti z kurzu.
V tomto krátkém tutoriálu si popíšeme, jak si multiplatformně
zajistíme přístup ke složce pro ukládání dat aplikace. Ve Windows je tato
složka známá jako %appdata%
-
C:\Users\<Account>\AppData\Roaming\<AppAuthor>\<AppName>
,
v Linuxu je to /home/<account>/.local/share/<AppName>
a
v MacOS by cesta měla být přibližně
/Users/<Account>/Library/Application Support/<AppName>
.
Kvůli rozmanitosti těchto cest neexistuje v Javě nativní řešení, pomocí
kterého bychom si snadno vyžádali přístup k těmto složkám.
Závislosti
Pro snadný přístup budeme muset sáhnout po knihovně třetí strany. Určitě jich existuje více, ale já zde popíši pouze jednu, protože s ní mám zkušenosti. Jedná se o projekt appdirs na GitHubu. Ke správě závislostí budeme používat Gradle, ale pro Maven bude postup velice podobný.
Nový projekt
Projekt budu tvořit v IntelliJ Idea. Spustíme tedy IDE a klikneme na tlačítko Create New Project:

V nabídce vybereme, že chceme Java projekt spravovaný pomocí Gradlu:

Do prvního políčka vložíme název organizace či jiný identifikátor. Druhé políčko je pro název aplikace

V nastavení Gradlu zaškrtneme políčko pro AutoImport, abychom nemuseli ručně projekt synchronizovat:

Nakonec nastavíme cestu k projektu:

Vyhledání repositáře
Když jsme úspěšně založili projekt, přejdeme na stránku Maven repository, kde do vyhledávacího
políčka zadáme název knihovny: appdirs
a zvolíme vyhledat.
Zvolíme první možnost, tedy tu knihovnu, která je v balíčku
net.harawata.appdirs
a vybereme nejnovější verzi:

Na následující stránce se přepneme do záložky s Gradle a zkopírujeme si závislost, kterou přidáme do seznamu závislostí v Gradlu:

Pro ty, kteří by na stránku nechtěli chodit, přidávám závislost ke zkopírování níže:
// https://mvnrepository.com/artifact/net.harawata/appdirs compile group: 'net.harawata', name: 'appdirs', version: '1.0.3'
Sestavení
Otevřeme si soubor buid.gradle
a na konci souboru, do seznamu
závislostí, vložíme zkopírovaný řádek z webu:

Za několik málo okamžiků by se měl projekt automaticky aktualizovat a stáhnout potřebné závislosti. Celkem se stáhnou 4 knihovny:
- net.harawata:appdirs:1.0.3
- net.java.dev.jna:jna-platform:4.5.2
- net.java.dev.jna:jna:4.5.2
- org.slf4j:slf4j-api:1.7.25
První je knihovna, kterou jsme si my sami vyžádali. Tato knihovna má dvě
závislosti: jna
a slf4j
. První zmíněná knihovna
se používá k přístupu volání systémových funkcí. Druhá se používá
pro logování.
Seznámení se s knihovnou
Než se pustíme do programování, bylo by fajn se nejprve s knihovnou seznámit. Povíme si, jaké třídy/rozhraní knihovna nabízí a co vše můžeme použít.
AppDirs
Třída AppDirs
představuje hlavní komunikační rozhraní,
pomocí něhož získáváme přístup ke složkám. Třída obsahuje
následující metody pro přístup ke složkám:
getUserDataDir()
- Vrátí systémovou složku pro data aplikacegetUserConfigDir()
- Složka pro konfigurační soubory aplikacegetUserCacheDir()
- Složka pro cache aplikacegetUserLogDir()
- Složka pro logy aplikace
K vytvoření instance je zapotřebí tovární metoda
AppDirs.getInstance()
, která má v sobě zakomponovanou logiku,
podle které se rozhodne, jak instanci vytvoří. Především se podívá, na
jakém OS je program spuštěn a podle toho vybere jednu ze tří
implementaci:
WindowsAppDirs
MacOSXAppDirs
UnixAppDirs
Díky tomu, že je projekt na GitHubu, se můžeme podívat, jak tato logika pracuje:
public static AppDirs getInstance() { String os = System.getProperty("os.name").toLowerCase(); if (os.startsWith("mac os x")) { logger.debug("os.name {} is resolved to Mac OS X", os); return new MacOSXAppDirs(); } else if (os.startsWith("windows")) { logger.debug("os.name {} is resolved to Windows", os); WindowsFolderResolver folderResolver = new ShellFolderResolver(); return new WindowsAppDirs(folderResolver); } else { // Assume other *nix. logger.debug("os.name {} is resolved to *nix", os); return new UnixAppDirs(); } }
Ze systémové vlastnosti os.name
se určí, zda-li se jedná o
MacOS, Windows, nebo jakýkoliv Linux. Pravda, teď si možná říkáte, proč
využít knihovnu, když si toto všechno můžete napsat sami. Jde o to, že
zde již jsou vyřešeny problémy typu oddělovače složek a další věci.
Například abychom ve Windows získali cestu ke složce %appdata%
,
musíme využít volání nativních metod. O toto vše se knihovna postará za
nás.
Testování knihovny
Nyní si vytvoříme jednoduchou konzolovou aplikaci, kde si necháme
vytvořit instanci třídy AppDirs
, přes kterou se dostaneme k
nejrůznějším složkám aplikace.
import net.harawata.appdirs.AppDirs; import net.harawata.appdirs.AppDirsFactory; public class App { private static final String CREDENTIALS_APP_NAME = "testovaciAplikace"; private static final String CREDENTIALS_AUTHOR = "itnetwork"; private static final String CREDENTIALS_VERSION = "v1.0"; public static void main(String[] args) { final AppDirs appDirs = AppDirsFactory.getInstance(); final String userDataDir = appDirs.getUserDataDir(CREDENTIALS_APP_NAME, CREDENTIALS_VERSION, CREDENTIALS_AUTHOR); final String userConfigDir = appDirs.getUserConfigDir(CREDENTIALS_APP_NAME, CREDENTIALS_VERSION, CREDENTIALS_AUTHOR); final String userCacheDir = appDirs.getUserCacheDir(CREDENTIALS_APP_NAME, CREDENTIALS_VERSION, CREDENTIALS_AUTHOR); System.out.printf("UserDataDir: %s%n", userDataDir); System.out.printf("UserConfigDir: %s%n", userConfigDir); System.out.printf("UserCacheDir: %s%n", userCacheDir); } }
Výsledek aplikace pro Linux vypadá následovně:
Konzolová aplikace
UserDataDir: /home/petr/.local/share/testovaciAplikace/v1.0
UserConfigDir: /home/petr/.config/testovaciAplikace/v1.0
UserCacheDir: /home/petr/.cache/testovaciAplikace/v1.0
To by bylo z návodu vše. Doufám, že jsem vám ušetřil dlouhé hodiny bádání, jak získat přístup ke složce dat aplikací univerzálně na všech operačních systémech.