Detect if new install or updated version (Android app)

The only solution I can see that doesn't involve an entity outside of the device would be to get the PackageInfo for your app and check the values of

  • versionCode
  • firstInstallTime
  • lastUpdateTime

On first install, firstInstallTime and lastUpdateTime will have the same value (at least on my device they were the same); after an update, the values will be different because lastUpdateTime will change. Additionally, you know approximately what date and time you create the version that introduces this new behavior, and you also know which version code it will have.

I would extend Application and implement this checking in onCreate(), and store the result in SharedPreferences:

public class MyApplication extends Application {

    // take the date and convert it to a timestamp. this is just an example.
    private static final long MIN_FIRST_INSTALL_TIME = 1413267061000L;
    // shared preferences key
    private static final String PREF_SHARE_REQUIRED = "pref_share_required";

    @Override
    public void onCreate() {
        super.onCreate();
        checkAndSaveInstallInfo();
    }

    private void checkAndSaveInstallInfo() {
        SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this);
        if (prefs.contains(PREF_SHARE_REQUIRED)) {
            // already have this info, so do nothing
            return;
        }

        PackageInfo info = null;
        try {
            info = getPackageManager().getPackageInfo(getPackageName(), 0);
        } catch (NameNotFoundException e) {
            // bad times
            Log.e("MyApplication", "couldn't get package info!");
        }

        if (packageInfo == null) {
            // can't do anything
            return;
        }

        boolean shareRequired = true;
        if (MIN_FIRST_INSTALL_TIME > info.firstInstallTime
                && info.firstInstallTime != info.lastUpdateTime) {
            /*
             * install occurred before a version with this behavior was released
             * and there was an update, so assume it's a legacy user
             */
            shareRequired = false;
        }
        prefs.edit().putBoolean(PREF_SHARE_REQUIRED, shareRequired).apply();
    }
}

This is not foolproof, there are ways to circumvent this if the user really wants to, but I think this is about as good as it gets. If you want to track these things better and avoid tampering by the user, you should start storing user information on a server (assuming you have any sort of backend).


public static boolean isFirstInstall(Context context) {
    try {
        long firstInstallTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).firstInstallTime;
        long lastUpdateTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).lastUpdateTime;
        return firstInstallTime == lastUpdateTime;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return true;
    }
}



public static boolean isInstallFromUpdate(Context context) {
    try {
        long firstInstallTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).firstInstallTime;
        long lastUpdateTime = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).lastUpdateTime;
        return firstInstallTime != lastUpdateTime;
    } catch (PackageManager.NameNotFoundException e) {
        e.printStackTrace();
        return false;
    }
}

Tags:

Android