-
Notifications
You must be signed in to change notification settings - Fork 617
Fad only show UI for basic config #3260
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 3 commits
cb85dd5
a3de8d5
19cb320
ce686d4
ef5dd9f
236ac9e
8327e02
f1c6c4c
a1a4369
b0f4ec3
615944d
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -14,6 +14,7 @@ | |
|
||
package com.google.firebase.app.distribution; | ||
|
||
import static com.google.firebase.app.distribution.FirebaseAppDistributionException.Status.AUTHENTICATION_CANCELED; | ||
import static com.google.firebase.app.distribution.FirebaseAppDistributionException.Status.AUTHENTICATION_FAILURE; | ||
import static com.google.firebase.app.distribution.FirebaseAppDistributionException.Status.UPDATE_NOT_AVAILABLE; | ||
import static com.google.firebase.app.distribution.TaskUtils.safeSetTaskException; | ||
|
@@ -27,6 +28,7 @@ | |
import androidx.annotation.Nullable; | ||
import androidx.annotation.VisibleForTesting; | ||
import com.google.android.gms.tasks.Task; | ||
import com.google.android.gms.tasks.TaskCompletionSource; | ||
import com.google.android.gms.tasks.Tasks; | ||
import com.google.firebase.FirebaseApp; | ||
import com.google.firebase.app.distribution.Constants.ErrorMessages; | ||
|
@@ -37,6 +39,7 @@ | |
import com.google.firebase.installations.FirebaseInstallationsApi; | ||
|
||
public class FirebaseAppDistribution { | ||
|
||
private static final int UNKNOWN_RELEASE_FILE_SIZE = -1; | ||
|
||
private final FirebaseApp firebaseApp; | ||
|
@@ -60,6 +63,7 @@ public class FirebaseAppDistribution { | |
private Task<AppDistributionRelease> cachedCheckForNewReleaseTask; | ||
private AlertDialog updateDialog; | ||
private boolean updateDialogShown; | ||
private AlertDialog signInDialog; | ||
|
||
/** Constructor for FirebaseAppDistribution */ | ||
@VisibleForTesting | ||
|
@@ -129,12 +133,16 @@ public UpdateTask updateIfNewReleaseAvailable() { | |
if (cachedUpdateIfNewReleaseTask != null && !cachedUpdateIfNewReleaseTask.isComplete()) { | ||
return cachedUpdateIfNewReleaseTask; | ||
} | ||
|
||
cachedUpdateIfNewReleaseTask = new UpdateTaskImpl(); | ||
} | ||
checkForNewRelease() | ||
.onSuccessTask( | ||
release -> { | ||
|
||
showSignInDialog() | ||
.onSuccessTask(unused -> signInTester()) | ||
.onSuccessTask(unused -> checkForNewRelease()) | ||
.continueWithTask( | ||
lfkellogg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
checkForNewReleaseTask -> { | ||
AppDistributionRelease release = | ||
checkForNewReleaseTask.getResult(); // error will propagate to on failure listener | ||
if (release == null) { | ||
postProgressToCachedUpdateIfNewReleaseTask( | ||
UpdateProgress.builder() | ||
|
@@ -143,30 +151,123 @@ public UpdateTask updateIfNewReleaseAvailable() { | |
.setUpdateStatus(UpdateStatus.NEW_RELEASE_NOT_AVAILABLE) | ||
.build()); | ||
setCachedUpdateIfNewReleaseResult(); | ||
return Tasks.forResult(null); | ||
UpdateTaskImpl updateTask = new UpdateTaskImpl(); | ||
updateTask.setResult(); | ||
return updateTask; | ||
} | ||
return showUpdateAlertDialog(release); | ||
return showUpdateAlertDialog(release) | ||
.onSuccessTask( | ||
r -> | ||
updateApp(true) | ||
.addOnProgressListener( | ||
this::postProgressToCachedUpdateIfNewReleaseTask) | ||
.addOnSuccessListener(unused -> setCachedUpdateIfNewReleaseResult()) | ||
.addOnFailureListener( | ||
this::setCachedUpdateIfNewReleaseCompletionError)); | ||
}) | ||
.addOnFailureListener( | ||
e -> { | ||
postProgressToCachedUpdateIfNewReleaseTask( | ||
UpdateProgress.builder() | ||
.setApkFileTotalBytes(UNKNOWN_RELEASE_FILE_SIZE) | ||
.setApkBytesDownloaded(UNKNOWN_RELEASE_FILE_SIZE) | ||
.setUpdateStatus(UpdateStatus.NEW_RELEASE_CHECK_FAILED) | ||
.build()); | ||
setCachedUpdateIfNewReleaseCompletionError( | ||
e, | ||
new FirebaseAppDistributionException( | ||
Constants.ErrorMessages.NETWORK_ERROR, | ||
FirebaseAppDistributionException.Status.NETWORK_FAILURE)); | ||
}); | ||
.addOnFailureListener(this::setCachedUpdateIfNewReleaseCompletionError); | ||
|
||
synchronized (updateIfNewReleaseTaskLock) { | ||
lfkellogg marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return cachedUpdateIfNewReleaseTask; | ||
} | ||
} | ||
|
||
private Task<Void> showSignInDialog() { | ||
if (isTesterSignedIn()) { | ||
return Tasks.forResult(null); | ||
} | ||
|
||
TaskCompletionSource<Void> showDialogTask = new TaskCompletionSource<>(); | ||
|
||
Activity currentActivity = lifecycleNotifier.getCurrentActivity(); | ||
if (currentActivity == null) { | ||
LogWrapper.getInstance().e("No foreground activity found."); | ||
showDialogTask.setException( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.APP_BACKGROUNDED, | ||
FirebaseAppDistributionException.Status.UPDATE_NOT_AVAILABLE)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Seems like there are scenarios like this where the status doesn't exactly align with what is going on (here its not that an update isn't available). Our logs do have the more specific case to give the user a better sense of whats going on, but do we want to look at these statuses to make them more specific? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is a really good call. I've added an error message enum to our API and made a note to add it to the API addendum. There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Agreed, good callout. There are a bunch of places like this where the error status and/or message does not align with the actual situation. I'm currently going through them all as part of the error handling cleanup, so @rachaprince if you want I can handle this in a followup since this was just moved code. For this case though, looking at the statuses, There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Actually I think your new "no foreground activity" error seems like a good one to add, could be useful elsewhere. |
||
} | ||
|
||
signInDialog = new AlertDialog.Builder(currentActivity).create(); | ||
Context context = firebaseApp.getApplicationContext(); | ||
signInDialog.setTitle(context.getString(R.string.signin_dialog_title)); | ||
signInDialog.setMessage(context.getString(R.string.singin_dialog_message)); | ||
|
||
signInDialog.setButton( | ||
AlertDialog.BUTTON_POSITIVE, | ||
context.getString(R.string.singin_yes_button), | ||
(dialogInterface, i) -> showDialogTask.setResult(null)); | ||
|
||
signInDialog.setButton( | ||
AlertDialog.BUTTON_NEGATIVE, | ||
context.getString(R.string.singin_no_button), | ||
(dialogInterface, i) -> | ||
showDialogTask.setException( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.AUTHENTICATION_CANCELED, AUTHENTICATION_CANCELED))); | ||
|
||
signInDialog.setOnCancelListener( | ||
dialogInterface -> | ||
showDialogTask.setException( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.AUTHENTICATION_CANCELED, AUTHENTICATION_CANCELED))); | ||
|
||
signInDialog.show(); | ||
rachaprince marked this conversation as resolved.
Show resolved
Hide resolved
|
||
return showDialogTask.getTask(); | ||
} | ||
|
||
private Task<Void> showUpdateAlertDialog(AppDistributionRelease newRelease) { | ||
rachaprince marked this conversation as resolved.
Show resolved
Hide resolved
|
||
TaskCompletionSource<Void> showUpdateDialogTask = new TaskCompletionSource<>(); | ||
Activity currentActivity = lifecycleNotifier.getCurrentActivity(); | ||
if (currentActivity == null) { | ||
LogWrapper.getInstance().e("No foreground activity found."); | ||
return getErrorUpdateTask( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.APP_BACKGROUNDED, | ||
FirebaseAppDistributionException.Status.UPDATE_NOT_AVAILABLE)); | ||
} | ||
|
||
Context context = firebaseApp.getApplicationContext(); | ||
|
||
updateDialog = new AlertDialog.Builder(currentActivity).create(); | ||
updateDialog.setTitle(context.getString(R.string.update_dialog_title)); | ||
|
||
StringBuilder message = | ||
new StringBuilder( | ||
String.format( | ||
"Version %s (%s) is available.", | ||
newRelease.getDisplayVersion(), newRelease.getVersionCode())); | ||
|
||
if (newRelease.getReleaseNotes() != null && !newRelease.getReleaseNotes().isEmpty()) { | ||
message.append(String.format("\n\nRelease notes: %s", newRelease.getReleaseNotes())); | ||
} | ||
updateDialog.setMessage(message); | ||
|
||
updateDialog.setButton( | ||
AlertDialog.BUTTON_POSITIVE, | ||
context.getString(R.string.update_yes_button), | ||
(dialogInterface, i) -> showUpdateDialogTask.setResult(null)); | ||
|
||
updateDialog.setButton( | ||
AlertDialog.BUTTON_NEGATIVE, | ||
context.getString(R.string.update_no_button), | ||
(dialogInterface, i) -> | ||
showUpdateDialogTask.setException( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.UPDATE_CANCELED, Status.INSTALLATION_CANCELED))); | ||
|
||
updateDialog.setOnCancelListener( | ||
dialogInterface -> | ||
showUpdateDialogTask.setException( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.UPDATE_CANCELED, Status.INSTALLATION_CANCELED))); | ||
|
||
updateDialog.show(); | ||
updateDialogShown = true; | ||
|
||
return showUpdateDialogTask.getTask(); | ||
} | ||
|
||
/** Signs in the App Distribution tester. Presents the tester with a Google sign in UI */ | ||
@NonNull | ||
public Task<Void> signInTester() { | ||
|
@@ -195,6 +296,13 @@ public synchronized Task<AppDistributionRelease> checkForNewRelease() { | |
}) | ||
.addOnFailureListener( | ||
e -> { | ||
postProgressToCachedUpdateIfNewReleaseTask( | ||
UpdateProgress.builder() | ||
.setApkBytesDownloaded(UNKNOWN_RELEASE_FILE_SIZE) | ||
.setApkFileTotalBytes(UNKNOWN_RELEASE_FILE_SIZE) | ||
.setUpdateStatus(UpdateStatus.NEW_RELEASE_CHECK_FAILED) | ||
.build()); | ||
|
||
rachaprince marked this conversation as resolved.
Show resolved
Hide resolved
|
||
if (e instanceof FirebaseAppDistributionException | ||
&& ((FirebaseAppDistributionException) e).getErrorCode() | ||
== AUTHENTICATION_FAILURE) { | ||
|
@@ -294,113 +402,39 @@ AppDistributionReleaseInternal getCachedNewRelease() { | |
} | ||
} | ||
|
||
private UpdateTaskImpl showUpdateAlertDialog(AppDistributionRelease newRelease) { | ||
Context context = firebaseApp.getApplicationContext(); | ||
Activity currentActivity = lifecycleNotifier.getCurrentActivity(); | ||
if (currentActivity == null) { | ||
LogWrapper.getInstance().e("No foreground activity found."); | ||
UpdateTaskImpl updateTask = new UpdateTaskImpl(); | ||
updateTask.setException( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.APP_BACKGROUNDED, | ||
FirebaseAppDistributionException.Status.UPDATE_NOT_AVAILABLE)); | ||
return updateTask; | ||
} | ||
updateDialog = new AlertDialog.Builder(currentActivity).create(); | ||
updateDialog.setTitle(context.getString(R.string.update_dialog_title)); | ||
|
||
StringBuilder message = | ||
new StringBuilder( | ||
String.format( | ||
"Version %s (%s) is available.", | ||
newRelease.getDisplayVersion(), newRelease.getVersionCode())); | ||
|
||
if (newRelease.getReleaseNotes() != null && !newRelease.getReleaseNotes().isEmpty()) { | ||
message.append(String.format("\n\nRelease notes: %s", newRelease.getReleaseNotes())); | ||
} | ||
|
||
updateDialog.setMessage(message); | ||
updateDialog.setButton( | ||
AlertDialog.BUTTON_POSITIVE, | ||
context.getString(R.string.update_yes_button), | ||
(dialogInterface, i) -> { | ||
synchronized (updateIfNewReleaseTaskLock) { | ||
// show download progress in notification manager | ||
updateApp(true) | ||
.addOnProgressListener(this::postProgressToCachedUpdateIfNewReleaseTask) | ||
.addOnSuccessListener(unused -> setCachedUpdateIfNewReleaseResult()) | ||
.addOnFailureListener(cachedUpdateIfNewReleaseTask::setException); | ||
} | ||
}); | ||
|
||
updateDialog.setButton( | ||
AlertDialog.BUTTON_NEGATIVE, | ||
context.getString(R.string.update_no_button), | ||
(dialogInterface, i) -> dismissUpdateDialogCallback()); | ||
|
||
updateDialog.setOnCancelListener( | ||
dialogInterface -> { | ||
dismissUpdateDialogCallback(); | ||
}); | ||
|
||
updateDialog.show(); | ||
updateDialogShown = true; | ||
synchronized (updateIfNewReleaseTaskLock) { | ||
return cachedUpdateIfNewReleaseTask; | ||
} | ||
} | ||
|
||
private void dismissUpdateDialogCallback() { | ||
synchronized (updateIfNewReleaseTaskLock) { | ||
postProgressToCachedUpdateIfNewReleaseTask( | ||
UpdateProgress.builder() | ||
.setApkFileTotalBytes(UNKNOWN_RELEASE_FILE_SIZE) | ||
.setApkBytesDownloaded(UNKNOWN_RELEASE_FILE_SIZE) | ||
.setUpdateStatus(UpdateStatus.UPDATE_CANCELED) | ||
.build()); | ||
setCachedUpdateIfNewReleaseCompletionError( | ||
new FirebaseAppDistributionException( | ||
ErrorMessages.UPDATE_CANCELED, Status.INSTALLATION_CANCELED)); | ||
} | ||
} | ||
|
||
private void setCachedUpdateIfNewReleaseCompletionError(FirebaseAppDistributionException e) { | ||
private void setCachedUpdateIfNewReleaseCompletionError(Exception e) { | ||
synchronized (updateIfNewReleaseTaskLock) { | ||
safeSetTaskException(cachedUpdateIfNewReleaseTask, e); | ||
} | ||
dismissUpdateDialog(); | ||
} | ||
|
||
private void setCachedUpdateIfNewReleaseCompletionError( | ||
Exception e, FirebaseAppDistributionException defaultFirebaseException) { | ||
if (e instanceof FirebaseAppDistributionException) { | ||
setCachedUpdateIfNewReleaseCompletionError((FirebaseAppDistributionException) e); | ||
} else { | ||
setCachedUpdateIfNewReleaseCompletionError(defaultFirebaseException); | ||
} | ||
dismissDialogs(); | ||
} | ||
|
||
private void postProgressToCachedUpdateIfNewReleaseTask(UpdateProgress progress) { | ||
synchronized (updateIfNewReleaseTaskLock) { | ||
cachedUpdateIfNewReleaseTask.updateProgress(progress); | ||
if (cachedUpdateIfNewReleaseTask != null && !cachedUpdateIfNewReleaseTask.isComplete()) { | ||
cachedUpdateIfNewReleaseTask.updateProgress(progress); | ||
} | ||
} | ||
} | ||
|
||
private void setCachedUpdateIfNewReleaseResult() { | ||
synchronized (updateIfNewReleaseTaskLock) { | ||
safeSetTaskResult(cachedUpdateIfNewReleaseTask); | ||
} | ||
dismissUpdateDialog(); | ||
dismissDialogs(); | ||
} | ||
|
||
private void dismissUpdateDialog() { | ||
private void dismissDialogs() { | ||
if (signInDialog != null && signInDialog.isShowing()) { | ||
rachaprince marked this conversation as resolved.
Show resolved
Hide resolved
|
||
signInDialog.dismiss(); | ||
} | ||
if (updateDialog != null) { | ||
updateDialog.dismiss(); | ||
updateDialogShown = false; | ||
} | ||
} | ||
|
||
private UpdateTask getErrorUpdateTask(Exception e) { | ||
private UpdateTaskImpl getErrorUpdateTask(Exception e) { | ||
UpdateTaskImpl updateTask = new UpdateTaskImpl(); | ||
updateTask.setException(e); | ||
return updateTask; | ||
|
Uh oh!
There was an error while loading. Please reload this page.