Skip to content

Instantly share code, notes, and snippets.

@sauravrao637
Last active April 9, 2022 20:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sauravrao637/eb21c9cdb5b81c7e640406c6fb2ed107 to your computer and use it in GitHub Desktop.
Save sauravrao637/eb21c9cdb5b81c7e640406c6fb2ed107 to your computer and use it in GitHub Desktop.
Playing around with version codes in android app

I suggest to not only store a boolean flag, but the complete version code. This way you can also query at the beginning if it is the first start in a new version. You can use this information to display a "Whats new" dialog, for example.

The following code should work from any android class that "is a context" (activities, services, ...). If you prefer to have it in a separate (POJO) class, you could consider using a "static context", as described here for example.

/**
 * Distinguishes different kinds of app starts: <li>
 * <ul>
 * First start ever ({@link #FIRST_TIME})
 * </ul>
 * <ul>
 * First start in this version ({@link #FIRST_TIME_VERSION})
 * </ul>
 * <ul>
 * Normal app start ({@link #NORMAL})
 * </ul>
 * 
 * @author schnatterer
 * 
 */
public enum AppStart {
	FIRST_TIME, FIRST_TIME_VERSION, NORMAL;
}

/**
 * The app version code (not the version name!) that was used on the last
 * start of the app.
 */
private static final String LAST_APP_VERSION = "last_app_version";

/**
 * Finds out started for the first time (ever or in the current version).<br/>
 * <br/>
 * Note: This method is <b>not idempotent</b> only the first call will
 * determine the proper result. Any subsequent calls will only return
 * {@link AppStart#NORMAL} until the app is started again. So you might want
 * to consider caching the result!
 * 
 * @return the type of app start
 */
public AppStart checkAppStart() {
	PackageInfo pInfo;
	SharedPreferences sharedPreferences = PreferenceManager
			.getDefaultSharedPreferences(this);
	AppStart appStart = AppStart.NORMAL;
	try {
		pInfo = getPackageManager().getPackageInfo(getPackageName(), 0);
		int lastVersionCode = sharedPreferences
				.getInt(LAST_APP_VERSION, -1);
		int currentVersionCode = pInfo.versionCode;
		appStart = checkAppStart(currentVersionCode, lastVersionCode);
		// Update version in preferences
		sharedPreferences.edit()
				.putInt(LAST_APP_VERSION, currentVersionCode).commit();
	} catch (NameNotFoundException e) {
		Log.w(Constants.LOG,
				"Unable to determine current app version from pacakge manager. Defenisvely assuming normal app start.");
	}
	return appStart;
}

public AppStart checkAppStart(int currentVersionCode, int lastVersionCode) {
	if (lastVersionCode == -1) {
		return AppStart.FIRST_TIME;
	} else if (lastVersionCode < currentVersionCode) {
		return AppStart.FIRST_TIME_VERSION;
	} else if (lastVersionCode > currentVersionCode) {
		Log.w(Constants.LOG, "Current version code (" + currentVersionCode
				+ ") is less then the one recognized on last startup ("
				+ lastVersionCode
				+ "). Defenisvely assuming normal app start.");
		return AppStart.NORMAL;
	} else {
		return AppStart.NORMAL;
	}
}

It could be used from an activity like this:

public class MainActivity extends Activity {		
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		
		switch (checkAppStart()) {
		case NORMAL:
			// We don't want to get on the user's nerves
			break;
		case FIRST_TIME_VERSION:
			// TODO show what's new
			break;
		case FIRST_TIME:
			// TODO show a tutorial
			break;
		default:
			break;
		}

		// ...
	}
	// ...
}

The basic logic can be verified using this JUnit test:

public void testCheckAppStart() {
	// First start
	int oldVersion = -1;
	int newVersion = 1;
	assertEquals("Unexpected result", AppStart.FIRST_TIME,
			service.checkAppStart(newVersion, oldVersion));

	// First start this version
	oldVersion = 1;
	newVersion = 2;
	assertEquals("Unexpected result", AppStart.FIRST_TIME_VERSION,
			service.checkAppStart(newVersion, oldVersion));

	// Normal start
	oldVersion = 2;
	newVersion = 2;
	assertEquals("Unexpected result", AppStart.NORMAL,
			service.checkAppStart(newVersion, oldVersion));
}

With a bit more effort you could probably test the android related stuff (PackageManager and SharedPreferences) as well. Anyone interested in writing the test? :)

Note that the above code will only work properly if you don't mess around with your android:versionCode in AndroidManifest.xml!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment