package com.github.javiersantos.appupdater; import android.app.Activity; import android.content.Context; import android.content.DialogInterface; import android.support.annotation.DrawableRes; import android.support.annotation.NonNull; import android.support.annotation.StringRes; import android.support.design.widget.Snackbar; import android.support.v7.app.AlertDialog; import android.text.TextUtils; import android.util.Log; import com.github.javiersantos.appupdater.enums.AppUpdaterError; import com.github.javiersantos.appupdater.enums.Display; import com.github.javiersantos.appupdater.enums.Duration; import com.github.javiersantos.appupdater.enums.UpdateFrom; import com.github.javiersantos.appupdater.objects.GitHub; import com.github.javiersantos.appupdater.objects.Update; public class AppUpdater implements IAppUpdater { private Context context; private LibraryPreferences libraryPreferences; private Display display; private UpdateFrom updateFrom; private Duration duration; private GitHub gitHub; private String xmlOrJsonUrl; private Integer showEvery; private Boolean showAppUpdated; private String titleUpdate, descriptionUpdate, btnDismiss, btnUpdate, btnDisable; // Update available private String titleNoUpdate, descriptionNoUpdate; // Update not available private int iconResId; private UtilsAsync.LatestAppVersion latestAppVersion; private DialogInterface.OnClickListener btnUpdateClickListener, btnDismissClickListener, btnDisableClickListener; private AlertDialog alertDialog; private Snackbar snackbar; public AppUpdater(Context context) { this.context = context; this.libraryPreferences = new LibraryPreferences(context); this.display = Display.DIALOG; this.updateFrom = UpdateFrom.GOOGLE_PLAY; this.duration = Duration.NORMAL; this.showEvery = 1; this.showAppUpdated = false; this.iconResId = R.drawable.ic_stat_name; // Dialog this.titleUpdate = context.getResources().getString(R.string.appupdater_update_available); this.titleNoUpdate = context.getResources().getString(R.string.appupdater_update_not_available); this.btnUpdate = context.getResources().getString(R.string.appupdater_btn_update); this.btnDismiss = context.getResources().getString(R.string.appupdater_btn_dismiss); this.btnDisable = context.getResources().getString(R.string.appupdater_btn_disable); } @Override public AppUpdater setDisplay(Display display) { this.display = display; return this; } @Override public AppUpdater setUpdateFrom(UpdateFrom updateFrom) { this.updateFrom = updateFrom; return this; } @Override public AppUpdater setDuration(Duration duration) { this.duration = duration; return this; } @Override public AppUpdater setGitHubUserAndRepo(@NonNull String user, @NonNull String repo) { this.gitHub = new GitHub(user, repo); return this; } @Override public AppUpdater setUpdateXML(@NonNull String xmlUrl) { this.xmlOrJsonUrl = xmlUrl; return this; } @Override public AppUpdater setUpdateJSON(@NonNull String jsonUrl) { this.xmlOrJsonUrl = jsonUrl; return this; } @Override public AppUpdater showEvery(Integer times) { this.showEvery = times; return this; } @Override public AppUpdater showAppUpdated(Boolean res) { this.showAppUpdated = res; return this; } @Override @Deprecated public AppUpdater setDialogTitleWhenUpdateAvailable(@NonNull String title) { setTitleOnUpdateAvailable(title); return this; } @Override @Deprecated public AppUpdater setDialogTitleWhenUpdateAvailable(@StringRes int textResource) { setTitleOnUpdateAvailable(textResource); return this; } @Override public AppUpdater setTitleOnUpdateAvailable(@NonNull String title) { this.titleUpdate = title; return this; } @Override public AppUpdater setTitleOnUpdateAvailable(@StringRes int textResource) { this.titleUpdate = context.getString(textResource); return this; } @Override @Deprecated public AppUpdater setDialogDescriptionWhenUpdateAvailable(@NonNull String description) { setContentOnUpdateAvailable(description); return this; } @Override @Deprecated public AppUpdater setDialogDescriptionWhenUpdateAvailable(@StringRes int textResource) { setContentOnUpdateAvailable(textResource); return this; } @Override public AppUpdater setContentOnUpdateAvailable(@NonNull String description) { this.descriptionUpdate = description; return this; } @Override public AppUpdater setContentOnUpdateAvailable(@StringRes int textResource) { this.descriptionUpdate = context.getString(textResource); return this; } @Override @Deprecated public AppUpdater setDialogTitleWhenUpdateNotAvailable(@NonNull String title) { setTitleOnUpdateNotAvailable(title); return this; } @Override @Deprecated public AppUpdater setDialogTitleWhenUpdateNotAvailable(@StringRes int textResource) { setTitleOnUpdateNotAvailable(textResource); return this; } @Override public AppUpdater setTitleOnUpdateNotAvailable(@NonNull String title) { this.titleNoUpdate = title; return this; } @Override public AppUpdater setTitleOnUpdateNotAvailable(@StringRes int textResource) { this.titleNoUpdate = context.getString(textResource); return this; } @Override @Deprecated public AppUpdater setDialogDescriptionWhenUpdateNotAvailable(@NonNull String description) { setContentOnUpdateNotAvailable(description); return this; } @Override @Deprecated public AppUpdater setDialogDescriptionWhenUpdateNotAvailable(@StringRes int textResource) { setContentOnUpdateNotAvailable(textResource); return this; } @Override public AppUpdater setContentOnUpdateNotAvailable(@NonNull String description) { this.descriptionNoUpdate = description; return this; } @Override public AppUpdater setContentOnUpdateNotAvailable(@StringRes int textResource) { this.descriptionNoUpdate = context.getString(textResource); return this; } @Override @Deprecated public AppUpdater setDialogButtonUpdate(@NonNull String text) { setButtonUpdate(text); return this; } @Override @Deprecated public AppUpdater setDialogButtonUpdate(@StringRes int textResource) { setButtonUpdate(textResource); return this; } @Override public AppUpdater setButtonUpdate(@NonNull String text) { this.btnUpdate = text; return this; } @Override public AppUpdater setButtonUpdate(@StringRes int textResource) { this.btnUpdate = context.getString(textResource); return this; } @Override @Deprecated public AppUpdater setDialogButtonDismiss(@NonNull String text) { setButtonDismiss(text); return this; } @Override @Deprecated public AppUpdater setDialogButtonDismiss(@StringRes int textResource) { setButtonDismiss(textResource); return this; } @Override public AppUpdater setButtonDismiss(@NonNull String text) { this.btnDismiss = text; return this; } @Override public AppUpdater setButtonDismiss(@StringRes int textResource) { this.btnDismiss = context.getString(textResource); return this; } @Override @Deprecated public AppUpdater setDialogButtonDoNotShowAgain(@NonNull String text) { setButtonDoNotShowAgain(text); return this; } @Override @Deprecated public AppUpdater setDialogButtonDoNotShowAgain(@StringRes int textResource) { setButtonDoNotShowAgain(textResource); return this; } @Override public AppUpdater setButtonDoNotShowAgain(@NonNull String text) { this.btnDisable = text; return this; } @Override public AppUpdater setButtonDoNotShowAgain(@StringRes int textResource) { this.btnDisable = context.getString(textResource); return this; } @Override public AppUpdater setButtonUpdateClickListener(final DialogInterface.OnClickListener clickListener) { btnUpdateClickListener = clickListener; return this; } @Override public AppUpdater setButtonDismissClickListener(final DialogInterface.OnClickListener clickListener) { btnDismissClickListener = clickListener; return this; } @Override public AppUpdater setButtonDoNotShowAgainClickListener(final DialogInterface.OnClickListener clickListener) { btnDisableClickListener = clickListener; return this; } @Override public AppUpdater setIcon(@DrawableRes int iconRes) { this.iconResId = iconRes; return this; } @Override public AppUpdater init() { start(); return this; } @Override public void start() { latestAppVersion = new UtilsAsync.LatestAppVersion(context, false, updateFrom, gitHub, xmlOrJsonUrl, new LibraryListener() { @Override public void onSuccess(Update update) { if (context instanceof Activity && ((Activity) context).isFinishing()) { return; } Update installedUpdate = new Update(UtilsLibrary.getAppInstalledVersion(context), UtilsLibrary.getAppInstalledVersionCode(context)); if (UtilsLibrary.isUpdateAvailable(installedUpdate, update)) { Integer successfulChecks = libraryPreferences.getSuccessfulChecks(); if (UtilsLibrary.isAbleToShow(successfulChecks, showEvery)) { switch (display) { case DIALOG: final DialogInterface.OnClickListener updateClickListener = btnUpdateClickListener == null ? new UpdateClickListener(context, updateFrom, update.getUrlToDownload()) : btnUpdateClickListener; final DialogInterface.OnClickListener disableClickListener = btnDisableClickListener == null ? new DisableClickListener(context) : btnDisableClickListener; alertDialog = UtilsDisplay.showUpdateAvailableDialog(context, titleUpdate, getDescriptionUpdate(context, update, Display.DIALOG), btnDismiss, btnUpdate, btnDisable, updateClickListener, btnDismissClickListener, disableClickListener); alertDialog.show(); break; case SNACKBAR: snackbar = UtilsDisplay.showUpdateAvailableSnackbar(context, getDescriptionUpdate(context, update, Display.SNACKBAR), UtilsLibrary.getDurationEnumToBoolean(duration), updateFrom, update.getUrlToDownload()); snackbar.show(); break; case NOTIFICATION: UtilsDisplay.showUpdateAvailableNotification(context, titleUpdate, getDescriptionUpdate(context, update, Display.NOTIFICATION), updateFrom, update.getUrlToDownload(), iconResId); break; } } libraryPreferences.setSuccessfulChecks(successfulChecks + 1); } else if (showAppUpdated) { switch (display) { case DIALOG: alertDialog = UtilsDisplay.showUpdateNotAvailableDialog(context, titleNoUpdate, getDescriptionNoUpdate(context)); alertDialog.show(); break; case SNACKBAR: snackbar = UtilsDisplay.showUpdateNotAvailableSnackbar(context, getDescriptionNoUpdate(context), UtilsLibrary.getDurationEnumToBoolean(duration)); snackbar.show(); break; case NOTIFICATION: UtilsDisplay.showUpdateNotAvailableNotification(context, titleNoUpdate, getDescriptionNoUpdate(context), iconResId); break; } } } @Override public void onFailed(AppUpdaterError error) { if (error == AppUpdaterError.UPDATE_VARIES_BY_DEVICE) { Log.e("AppUpdater", "UpdateFrom.GOOGLE_PLAY isn't valid: update varies by device."); } else if (error == AppUpdaterError.GITHUB_USER_REPO_INVALID) { throw new IllegalArgumentException("GitHub user or repo is empty!"); } else if (error == AppUpdaterError.XML_URL_MALFORMED) { throw new IllegalArgumentException("XML file is not valid!"); } else if (error == AppUpdaterError.JSON_URL_MALFORMED) { throw new IllegalArgumentException("JSON file is not valid!"); } } }); latestAppVersion.execute(); } @Override public void stop() { if (latestAppVersion != null && !latestAppVersion.isCancelled()) { latestAppVersion.cancel(true); } } @Override public void dismiss() { if (alertDialog != null && alertDialog.isShowing()) { alertDialog.dismiss(); } if (snackbar != null && snackbar.isShown()) { snackbar.dismiss(); } } private String getDescriptionUpdate(Context context, Update update, Display display) { if (descriptionUpdate == null || TextUtils.isEmpty(descriptionUpdate)) { switch (display) { case DIALOG: if (update.getReleaseNotes() != null && !TextUtils.isEmpty(update.getReleaseNotes())) { if (TextUtils.isEmpty(descriptionUpdate)) return update.getReleaseNotes(); else return String.format(context.getResources().getString(R.string.appupdater_update_available_description_dialog_before_release_notes), update.getLatestVersion(), update.getReleaseNotes()); } else { return String.format(context.getResources().getString(R.string.appupdater_update_available_description_dialog), update.getLatestVersion(), UtilsLibrary.getAppName(context)); } case SNACKBAR: return String.format(context.getResources().getString(R.string.appupdater_update_available_description_snackbar), update.getLatestVersion()); case NOTIFICATION: return String.format(context.getResources().getString(R.string.appupdater_update_available_description_notification), update.getLatestVersion(), UtilsLibrary.getAppName(context)); } } return descriptionUpdate; } private String getDescriptionNoUpdate(Context context) { if (descriptionNoUpdate == null) { return String.format(context.getResources().getString(R.string.appupdater_update_not_available_description), UtilsLibrary.getAppName(context)); } else { return descriptionNoUpdate; } } }