Checking For Updates


This chapter explains the background behind update checking and introduces you to the API that allows you to integrate these checks into your application.

The updates.xml file

The updates.xml file is created in the media output directory each time you build the project. For advanced use cases, you can modify this file before uploading it to the web server. The file looks like the sample below:

<?xml version="1.0" encoding="UTF-8"?>
<updateDescriptor baseUrl="">
  <entry targetMediaFileId="8" updatableVersionMin="" updatableVersionMax="" fileName="hello_windows_4_0.exe"
         newVersion="4.0" newMediaFileId="8" fileSize="2014720" bundledJre="" myCustomAttribute="showWarning">
    <comment language="en">Hello world</comment>
    <comment language="de">Hallo Welt</comment>
    <comment language="it">Ciao mondo</comment>
  </entry>
  <entry targetMediaFileId="9" updatableVersionMin="" updatableVersionMax="" fileName="hello_linux_4_0.rpm"
         newVersion="4.0" newMediaFileId="9" fileSize="817758" bundledJre="">
    <comment />
  </entry>
  <entry targetMediaFileId="10" updatableVersionMin="" updatableVersionMax="" fileName="hello_macos_4_0.dmg"
         newVersion="4.0" newMediaFileId="10" fileSize="1359872" bundledJre="">
    <comment />
  </entry>
</updateDescriptor>

Its contents are derived from your input on the "Installer->Auto-Update Options" step where you define global options and common options that are replicated on all media file entries.

On the "Customize project defaults->Auto-update options" step of the media wizard you can override settings with specific values for the each media file.

The root of the updates.xml file is the updateDescriptor element. It has a baseUrl attribute that can be used to specify an alternate download URL for the installers and contains the value of the "Base URL for installers" setting on the "Installer->Auto-Update Options" step. By default, it is empty which means that the installers must be located in the same directory as the updates.xml file.

The updateDescriptor element contains one or more entry elements that correspond to the media files that were created by the build.

When install4j determines whether an entry in the update descriptor is a match for the current installation, it looks at three attributes of the entry element: Most importantly, the targetMediaFileId attribute has to match the media file ID of the current installation. You can show media file IDs by toggling the "Show IDs" tool bar button

Another criterion is the installed version of the application. Depending on that version, you might want to offer different updates. The updatableVersionMin and the updatableVersionMax attributes can set lower and upper limits for the installed versions that should download the associated entry in the update descriptor. By default, these attributes are empty, so no version restrictions apply. On the "Installer->Auto-Update Options" step, these versions can be set for all media files.

Attributes that describe the update installer include fileName which is necessary to construct the download URL, and fileSize which contains the size of the file in bytes. newVersion contains the available version while newMediaFileId is the media file ID of the update installer which is usually the same as targetMediaFileId. Lastly, bundledJre contains the original file name of the JRE bundle without the .tar.gz extension or the empty string if no JRE is bundled in the installer.

If you discontinue a media file, you can migrate users of that media file to a different media file with the legacy media file setting on the "Customize project defaults->Auto-update options" step of the media wizard. For each specified legacy ID, the entry for the current media file is duplicated, but with the targetMediaFileId attribute set to the legacy ID. For more complex scenarios, you can modify the updates.xml file yourself and add additional entry elements as required.

In addition to the above attributes, the nested comment elements can contain a localized description that should be displayed to the user. You can populate these elements for all media files by configuring the "Files with comments" setting in the "Installer->Auto-Update Options" step. The main use case for this feature is to display release notes in the update downloader.

Finally, you can add any number of arbitrary attributes to the entry element. This is configured with the "Additional attributes" setting in the "Installer->Auto-Update Options" step. Additional attributes are useful for custom logic to select a suitable update installer in the update downloader.

The update descriptor API and up-to-date checks

The install4j runtime API contains the com.install4j.api.update.UpdateChecker utility class that can download the updates.xml file and translate it to an instance of com.install4j.api.update.UpdateDescriptor. From there, you can get a suitable com.install4j.api.update.UpdateDescriptorEntry with a single method call:

import com.install4j.api.launcher.Variables;
import com.install4j.api.update.*;

String updateUrl = Variables.getCompilerVariable("sys.updatesUrl");
UpdateDescriptor updateDescriptor = UpdateChecker.getUpdateDescriptor(updateUrl, ApplicationDisplayMode.GUI);
if (updateDescriptor.getPossibleUpdateEntry() != null) {
    // TODO an update is available, execute update downloader
}

See the Javadoc for more detailed information.

In this way, you can display your own notification that announces the new version and lets the user decide whether to download it or not. This API is primarily intended for use in your application. The "hello" sample project shows how to use it in a complex example, see the source file hello/gui/HelloGui.java in your install4j installation and look for the checkForUpdateWithApi method.

In a custom installer application, you would rather use a "Check for update" action that performs the same actions as UpdateChecker and saves the downloaded UpdateDescriptor to an installer variable. All update downloader templates included with install4j execute the "Check for update" action at some point. Its URL is set to ${installer:updatesUrl?:${compiler:sys.updatesUrl}} by default. If you start the update downloader with the argument -VupdatesUrl=<URL>, it will define the installer variable "updatesUrl" and that value will be used as the URL. Otherwise it falls back to the compiler variable "sys.updatesUrl" that contains the URL for updates.xml that you have entered on the "Installer->Auto-Update Options" step.

Instances of UpdateDescriptorEntry expose all attributes of the corresponding entry element in the updates.xml file. They also provide access to any additional attributes that were added to the entry element so you can implement custom logic to find a suitable update. The most important method of the UpdateDescriptorEntry class is the getUrl()method that constructs the full URL from which the update installer can be downloaded. If no baseUrlhas been specified on the updateDescriptor root element, the URL starts with the parent directory from which the updates.xml file has been downloaded.

Update schedule registry

A common requirement is to check for an update on a regular schedule. install4j comes with a standard implementation of an update schedule registry that frees you of the task to implement one yourself. This update schedule registry is fully integrated with the launcher integration that starts update downloaders when launchers are executed, but it is also available in the API.

The com.install4j.api.update.UpdateScheduleRegistry class is intended to be used in your application. You configure a particular UpdateSchedule by calling

import com.install4j.api.update.*;

UpdateScheduleRegistry.setUpdateSchedule(UpdateSchedule.DAILY);

and call

boolean shouldCheckForUpdate = UpdateScheduleRegistry.checkAndReset();

each time your application is started. If you get a positive response, you can start a suitable update downloader with the ApplicationLauncher class as explained below.

To facilitate the configuration of the update schedule in your installer, install4j offers a special "Update schedule selector" form component whose initial value is set to the current setting (if any) and automatically updates the setting for the installed application when the user clicks "Next".

Starting update downloaders from your own code

If you have a GUI application, you could provide integration with the update downloader by offering a "Check for update" menu item or similar that invokes the update downloader. One problem in this scenario is that if the updater downloads and executes the update installer, your application will still be running and the user will receive a corresponding warning message in the installer. The solution to this problem is to use the com.install4j.api.launcher.ApplicationLauncher class to launch the update downloader. With this utility class, you can launch the update installer by passing its ID as an argument. IDs of installer applications can be shown by toggling the "Show IDs" tool bar button.

If you launch an installer application such as an update downloader that way, the "Shut down calling launcher" action will be able to close your application. To react to the shutdown and perform cleanup operations, you can pass a callback to the ApplicationLauncher.launchApplication(...) call. After you are notified via the callback, your application will be terminated with a call to System.exit(). For example, for an update downloader with ID 123:

import java.io.IOException;
import com.install4j.api.launcher.ApplicationLauncher;

try {
ApplicationLauncher.launchApplication("123", null, false, new ApplicationLauncher.Callback() {
public void exited(int exitValue) {
//TODO update check complete, no update available
}

public void prepareShutdown() {
//TODO update installer will be executed, perform cleanup before process is terminated
}
}
);
} catch (IOException e) {
e.printStackTrace();
//TODO handle invocation failure
}

To easily get such a code snippet for invoking the update downloader, select the update downloader application and click on the Start Integration Wizard button on the right.