package org.commcare.heartbeat;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.util.Base64;
import org.commcare.CommCareApp;
import org.commcare.CommCareApplication;
import org.commcare.logging.AndroidLogger;
import org.commcare.utils.SerializationUtil;
import org.javarosa.core.model.utils.DateUtils;
import org.javarosa.core.services.Logger;
import org.javarosa.core.util.externalizable.DeserializationException;
import org.javarosa.core.util.externalizable.ExtUtil;
import org.javarosa.core.util.externalizable.ExtWrapNullable;
import org.javarosa.core.util.externalizable.Externalizable;
import org.javarosa.core.util.externalizable.PrototypeFactory;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.Date;
/**
* Created by amstone326 on 4/13/17.
*/
public class UpdateToPrompt implements Externalizable {
public static final String KEY_CCZ_UPDATE_TO_PROMPT = "ccz-update-to-prompt";
public static final String KEY_APK_UPDATE_TO_PROMPT = "apk-update-to-prompt";
private String versionString;
private int cczVersion;
private ApkVersion apkVersion;
private Date forceByDate;
protected boolean isApkUpdate;
public UpdateToPrompt(String version, String forceByDate, boolean isApkUpdate) {
if (forceByDate != null) {
this.forceByDate = DateUtils.parseDate(forceByDate);
}
this.isApkUpdate = isApkUpdate;
this.versionString = version;
buildFromVersionString();
}
public UpdateToPrompt() {
// for deserialization
}
private void buildFromVersionString() {
if (isApkUpdate) {
this.apkVersion = new ApkVersion(versionString);
} else {
this.cczVersion = Integer.parseInt(versionString);
}
}
public boolean isPastForceByDate() {
return forceByDate != null && (forceByDate.getTime() < System.currentTimeMillis());
}
public void registerWithSystem() {
CommCareApp currentApp = CommCareApplication.instance().getCurrentApp();
if (isNewerThanCurrentVersion(currentApp)) {
printDebugStatement();
writeToPrefsObject(currentApp.getAppPreferences());
} else {
// If the latest signal we're getting is that our current version is up-to-date,
// then we should wipe any update prompt for this type that was previously stored
UpdatePromptHelper.wipeStoredUpdate(this.isApkUpdate);
}
}
private void printDebugStatement() {
if (isApkUpdate) {
System.out.println(".apk version to prompt for update set to " + apkVersion);
} else {
System.out.println(".ccz version to prompt for update set to " + cczVersion);
}
if (this.forceByDate != null) {
System.out.println("force-by date is " + forceByDate);
}
}
public boolean isNewerThanCurrentVersion(CommCareApp currentApp) {
if (isApkUpdate) {
try {
Context c = CommCareApplication.instance();
PackageInfo pi = c.getPackageManager().getPackageInfo(c.getPackageName(), 0);
ApkVersion currentVersion = new ApkVersion(pi.versionName);
return currentVersion.compareTo(this.apkVersion) < 0;
} catch (PackageManager.NameNotFoundException e) {
// This shouldn't happen, but it if it does, there's no way for us to know if the
// update version is newer, so don't prompt
Logger.log(AndroidLogger.TYPE_ERROR_WORKFLOW,
"Couldn't get current .apk version to compare with in UpdateToPrompt: "
+ e.getMessage());
return false;
}
} else {
int currentVersion = currentApp.getCommCarePlatform().getCurrentProfile().getVersion();
return currentVersion < this.cczVersion;
}
}
private void writeToPrefsObject(SharedPreferences prefs) {
try {
byte[] serializedBytes = SerializationUtil.serialize(this);
String serializedString = Base64.encodeToString(serializedBytes, Base64.DEFAULT);
prefs.edit().putString(
isApkUpdate ? KEY_APK_UPDATE_TO_PROMPT : KEY_CCZ_UPDATE_TO_PROMPT,
serializedString).commit();
} catch (Exception e) {
Logger.log(AndroidLogger.TYPE_ERROR_WORKFLOW,
"Error encountered while serializing UpdateToPrompt: " + e.getMessage());
}
}
@Override
public void readExternal(DataInputStream in, PrototypeFactory pf) throws IOException, DeserializationException {
this.versionString = ExtUtil.readString(in);
this.isApkUpdate = ExtUtil.readBool(in);
this.forceByDate = (Date)ExtUtil.read(in, new ExtWrapNullable(Date.class), pf);
buildFromVersionString();
}
@Override
public void writeExternal(DataOutputStream out) throws IOException {
ExtUtil.writeString(out, versionString);
ExtUtil.writeBool(out, isApkUpdate);
ExtUtil.write(out, new ExtWrapNullable(forceByDate));
}
}