Universal access to the AppData folder in Java

In this short tutorial, we're going to describe a cross-platform solution to access the application data folder. On Windows, this folder is known as %appdata% - C:\Users\<Account>\AppData\Roaming\<AppAuthor>\<AppName>, on Linux it's /home/<account>/.local/share/<AppName> and in MacOS, the path should be approximately /Users/<Account>/Library/Application Support/<AppName>. Because of the diversity of these paths, there's no native solution in Java that would request access to these folders easily.

Dependencies

If we want to do things easily, we have to reach for a third-party library. Certainly there are more, but I'll describe just one I have experience with. It's the appdirs project on GitHub. To manage dependencies, we'll use Gradle, but for Maven the procedure would be very similar.

New project

I'll create the project in IntelliJ Idea. Let's start the IDE and click on the Create New Project button:

In the menu, we'll choose we want a Java project managed by Gradle:

In the first field, we'll enter the name of the organization or other identifier. The second field is for the application name:

In the Gradle settings, we'll check the AutoImport checkbox to avoid synchronizing the project manually:

Finally, we'll set the path to the project:

Finding the repository

Once we have successfully set up the project, we'll go to the Maven repository page, enter the name of the library: appdirs in the search box and choose Search. We'll choose the first option, the library in the net.harawata.appdirs package, and select the latest version:

On the next page, we'll switch to the Gradle tab and copy the dependency that we'll add to the dependencies list in Gradle:

For those who don't want to go to the website, I attach the dependency below, you can just copy it:

// https://mvnrepository.com/artifact/net.harawata/appdirs
compile group: 'net.harawata', name: 'appdirs', version: '1.0.3'

Building

Open the buid.gradle file and paste the copied line from the website to the dependency list at the end of the file:

In a few moments, the project should update automatically and download the necessary dependencies. A total of 4 libraries will be downloaded:

  • net.harawata:ap­pdirs: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

The first is the library we requested. This library has two dependencies: jna and slf4j. The first one is used to access system function calls. The second one is used for logging.

Exploring the library

Before we start programming, it'd be nice to get to know the library first. We'll see what classes/interfaces the library offers and what we can do with them.

AppDirs

The AppDirs class is the main communication interface we use to access the folders. The class contains the following methods for accessing the folders:

  • getUserDataDir() - Returns the system folder for the application data
  • getUserConfigDir() - The folder for application configuration files
  • getUserCacheDir() - The application cache folder
  • getUserLogDir() - The application log folder

To create an instance, we need the AppDirs.getInstance() factory method, which has its own logic to decide how to create the instance. First of all, it looks which OS the program is running on and selects one of these three implementations accordingly:

  • WindowsAppDirs
  • MacOSXAppDirs
  • UnixAppDirs

Since it's a GitHub project, we can see how this logic works:

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();
  }
}

Based on the os.name system property the code determines whether it's MacOS, Windows, or any Linux. True, now you may be wondering why to use the library when you can write all this yourself. The point is there are directory separator issues and other things already resolved by the library. For example, to get the path to the %appdata% folder on Windows, we must use native method calls. The library will take care of all this for us.

Testing the library

Now let's create a simple console application where we'll create an AppDirs class instance to get to the various application folders.

import net.harawata.appdirs.AppDirs;
import net.harawata.appdirs.AppDirsFactory;

public class App {

    private static final String CREDENTIALS_APP_NAME = "testApplication";
    private static final String CREDENTIALS_AUTHOR = "ict.social";
    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);
    }
}

The result of the application on Linux looks like this:

Console application
UserDataDir: /home/peter/.local/share/testApplication/v1.0
UserConfigDir: /home/peter/.config/testApplication/v1.0
UserCacheDir: /home/peter/.cache/testApplication/v1.0

That would be all. I hope I saved you long hours of researching how to access the application data folder universally on all operating systems.


 

 

Activities (2)

 

 

Comments

To maintain the quality of discussion, we only allow registered members to comment. Sign in. If you're new, Sign up, it's free.

No one has commented yet - be the first!