Customization Options for Android

This article describes the various customization options of HockeySDK for Android.

Note: CrashManager and UpdateManager are integrated separately and serve different functions. For instance, HockeyApp won't count the number of times your app has been installed if you only integrate crash reporting and not the update manager.

Basics

We assume that you have already integrated the HockeySDK as described here. Then your code should include the following two lines (or only one of them if you only want crash reporting or beta distribution):

CrashManager.register(this);
UpdateManager.register(this);

Both methods take an additional third parameter, an instance of the classes CrashManagerListener and HockeyManagerListener respectively. The methods of these classes are all optional, so you can implement only some of them. The following examples each show a single method for clarity.

Note that the examples use a non-static inner class for the listener. This class might be kept alive longer than its container (especially the CrashManagerListener is kept alive for complete lifespan of the app), which will lead to a leak of the container due to the implicit reference. You can solve this by keeping a reference from the containing class to the listener or by using a static inner class, for example:

CrashManager.register(this, APP_ID, new MyCrashManagerListener());

private static class MyCrashManagerListener extends CrashManagerListener {
    public boolean shouldAutoUploadCrashes() {
        return true;
    }
}

A longer discussion on the topic can be found here.

CrashManagerListener

Method: ignoreDefaultHandler

Return true to ignore the default exception handler, i.e. the user will not get the alert dialog with the "Force Close" button.

Example:

CrashManager.register(this, APP_ID, new CrashManagerListener() {
  public boolean ignoreDefaultHandler() {
    return true;
  }
});

Method: getContact

Return contact data or similar; note that this has privacy implications, so you might want to return nil for release builds! The string will be limited to 255 characters.

Example:

CrashManager.register(this, APP_ID, new CrashManagerListener() {
  public String getContact() {
    return "joe.user@gmail.com";
  }
});

Method: getDescription

Return additional data, i.e. parts of the system log, the last server response or similar. This string is not limited to a certain size.

Example:

CrashManager.register(this, APP_ID, new CrashManagerListener() {
  public String getDescription() {
    String description = "";

    try {
      Process process = Runtime.getRuntime().exec("logcat -d HockeyApp:D *:S");
      BufferedReader bufferedReader = 
        new BufferedReader(new InputStreamReader(process.getInputStream()));

      StringBuilder log = new StringBuilder();
      String line;
      while ((line = bufferedReader.readLine()) != null) {
        log.append(line);
        log.append(System.getProperty("line.separator"));
      }
      bufferedReader.close();

      description = log.toString();
    } 
    catch (IOException e) {
    }

    return description;
  }
});

Note: This reads the system log (similar to 'adb logcat') and filters it for lines with the tag "HockeyApp". You need to replace this string with your own tag. In addition, the permission "READ_LOGS" needs to be set in the AndroidManifest.xml. We don't recommend to do this in your live apps.

Method: getUserID

Return a user ID or similar; note that this has privacy implications, so you might want to return nil for release builds! The string will be limited to 255 characters.

Example:

CrashManager.register(this, APP_ID, new CrashManagerListener() {
  public String getUserID() {
    return Settings.Secure.getString(getContentResolver(), 
                                     Settings.Secure.ANDROID_ID);
  }
});

This returns the constant ANDROID_ID as the user ID. Note that this ID is not unique on some older devices. Details on the topic are here.

Method: shouldAutoUploadCrashes

Called when the crash manager found one or more crashes. Return true if you want to auto-send crashes (i.e. not ask the user).

Example:

CrashManager.register(this, APP_ID, new CrashManagerListener() {
  public boolean shouldAutoUploadCrashes() {
    return true;
  }
});

Method: onCrashesSent

Called when the crash manager has sent crashes to HockeyApp. Note that this method is called on a background thread.

Example:

CrashManager.register(this, APP_ID, new CrashManagerListener() {
  public void onCrashesSent() {
    runOnUIThread(new Runnable() { 
      Toast.makeText(MyActivity.this, "Crash data was sent. Thanks!", Toast.LENGTH_LONG).show();
    });
    return true;
  }
});

Method: onCrashesNotSent

Called when the crash manager failed to send crashes to HockeyApp, e.g. because the device has no network connections. Note that this method is called on a background thread.

Example:

CrashManager.register(this, APP_ID, new CrashManagerListener() {
  public void onCrashesNotSent() {
    runOnUIThread(new Runnable() { 
      Toast.makeText(MyActivity.this, "Crash data failed to sent. Please try again later.", Toast.LENGTH_LONG).show();
    });
    return true;
  }
});

UpdateManagerListener

Method: getUpdateActivityClass

Return your own subclass of UpdateActivity for customization.

Example:

  UpdateManager.register(this, APP_ID, new UpdateManagerListener() {
    public Class<? extends UpdateActivity> getUpdateActivityClass() {
      return CustomUpdateActivity.class;
    }
  });

Method: getUpdateFragmentClass

Return your own subclass of UpdateFragment for customization.

Example:

  UpdateManager.register(this, APP_ID, new UpdateManagerListener() {
    public Class<? extends UpdateFragment> getUpdateFragmentClass() {
      return CustomUpdateFragment.class;
    }
  });

Method: onUpdateAvailable

Called when the update manager found an update.

Example:

  UpdateManager.register(this, APP_ID, new UpdateManagerListener() {
    public void onUpdateAvailable() {
      // Something you want to do when an update is available, e.g.
      // enable a button to install the update. Note that the manager
       // shows an alert dialog after the method returns.
    }
  });

Method: onNoUpdateAvailable

Called when the update manager found no update.

Example:

  UpdateManager.register(this, APP_ID, new UpdateManagerListener() {
    public void onNoUpdateAvailable() {
      Toast.makeText(MainActivity.this, "No updates found.", Toast.LENGTH_SHORT).show();
    }
  });

Language Localization:

HockeySDK for Android comes with English, French, German and Spanish localizations of all user interface strings. If you want to add further localizations or override certain strings to suit your app's user interface, you can simply override them and resource merging takes care of the rest.

Our base strings resource file is located in hockeysdk/src/main/res/values/strings.xml. If your app overrides any of these strings in its strings.xml file, the overridden strings will be used in your app.

For more information about language localization for feedback please see:
iOS HockeyApp SDK info on GitHub and Android HockeyApp SDK info on GitHub