Skip to content

Commit

Permalink
Merge pull request #622 from Microsoft/develop
Browse files Browse the repository at this point in the history
Version 1.3.0
  • Loading branch information
guperrot authored Feb 14, 2018
2 parents fb73430 + eab5d63 commit 87b2298
Show file tree
Hide file tree
Showing 17 changed files with 973 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -109,7 +109,6 @@ static void openBrowser(@NonNull String url, @NonNull Activity activity) {
*
* @param uri initial uri.
* @param appendQuery parameter to append.
*
* @return uri string with appended query item.
*/
static String appendUri(@NonNull String uri, @NonNull String appendQuery) throws URISyntaxException {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,14 +9,17 @@
import android.os.AsyncTask;
import android.os.Build;

import com.microsoft.appcenter.utils.HandlerUtils;
import com.microsoft.appcenter.utils.AppCenterLog;
import com.microsoft.appcenter.utils.HandlerUtils;
import com.microsoft.appcenter.utils.storage.StorageHelper;

import java.util.NoSuchElementException;

import static android.content.Context.DOWNLOAD_SERVICE;
import static com.microsoft.appcenter.distribute.DistributeConstants.INVALID_DOWNLOAD_IDENTIFIER;
import static com.microsoft.appcenter.distribute.DistributeConstants.LOG_TAG;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DOWNLOADED_RELEASE_HASH;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DOWNLOADED_RELEASE_ID;

/**
* Inspect a pending or completed download.
Expand Down Expand Up @@ -154,6 +157,15 @@ protected DownloadProgress doInBackground(Void... params) {
} else {
distribute.completeWorkflow(mReleaseDetails);
}

/* Add downloaded release hash to report after installation. */
if (mReleaseDetails != null) {
AppCenterLog.debug(LOG_TAG, "Store downloaded release hash and id for later reporting.");
StorageHelper.PreferencesStorage.putString(PREFERENCE_KEY_DOWNLOADED_RELEASE_HASH, mReleaseDetails.getReleaseHash());
StorageHelper.PreferencesStorage.putInt(PREFERENCE_KEY_DOWNLOADED_RELEASE_ID, mReleaseDetails.getId());
} else {
AppCenterLog.debug(LOG_TAG, "Release details are missing or broken, will not store release hash and id for reporting.");
}
}
} finally {
cursor.close();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@

import static com.microsoft.appcenter.distribute.DistributeConstants.EXTRA_DISTRIBUTION_GROUP_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.EXTRA_REQUEST_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.EXTRA_TESTER_APP_UPDATE_SETUP_FAILED;
import static com.microsoft.appcenter.distribute.DistributeConstants.EXTRA_UPDATE_TOKEN;
import static com.microsoft.appcenter.distribute.DistributeConstants.EXTRA_UPDATE_SETUP_FAILED;
import static com.microsoft.appcenter.distribute.DistributeConstants.LOG_TAG;
Expand All @@ -27,11 +28,13 @@ public void onCreate(Bundle savedInstanceState) {
String distributionGroupId = intent.getStringExtra(EXTRA_DISTRIBUTION_GROUP_ID);
String updateToken = intent.getStringExtra(EXTRA_UPDATE_TOKEN);
String updateSetupFailed = intent.getStringExtra(EXTRA_UPDATE_SETUP_FAILED);
String testerAppUpdateSetupFailed = intent.getStringExtra(EXTRA_TESTER_APP_UPDATE_SETUP_FAILED);
AppCenterLog.debug(LOG_TAG, getLocalClassName() + ".getIntent()=" + intent);
AppCenterLog.debug(LOG_TAG, "Intent requestId=" + requestId);
AppCenterLog.debug(LOG_TAG, "Intent distributionGroupId=" + distributionGroupId);
AppCenterLog.debug(LOG_TAG, "Intent updateToken passed=" + (updateToken != null));
AppCenterLog.debug(LOG_TAG, "Intent updateSetupFailed passed=" + (updateSetupFailed != null));
AppCenterLog.debug(LOG_TAG, "Intent testerAppUpdateSetupFailed passed=" + (testerAppUpdateSetupFailed != null));

/* Store redirection parameters if both required values were passed. */
if (requestId != null && distributionGroupId != null) {
Expand All @@ -42,6 +45,11 @@ public void onCreate(Bundle savedInstanceState) {
Distribute.getInstance().storeUpdateSetupFailedParameter(requestId, updateSetupFailed);
}

/* If tester app update setup failed, store that info to later retry using the browser update setup */
if (requestId != null && testerAppUpdateSetupFailed != null) {
Distribute.getInstance().storeTesterAppUpdateSetupFailedParameter(requestId, testerAppUpdateSetupFailed);
}

/*
* Resume app exactly where it was before with no activity duplicate, or starting the
* launcher if application task finished or killed (equivalent to clicking from launcher
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,9 @@
import android.widget.Toast;

import com.microsoft.appcenter.AbstractAppCenterService;
import com.microsoft.appcenter.AppCenter;
import com.microsoft.appcenter.channel.Channel;
import com.microsoft.appcenter.distribute.channel.DistributeInfoTracker;
import com.microsoft.appcenter.http.DefaultHttpClient;
import com.microsoft.appcenter.http.HttpClient;
import com.microsoft.appcenter.http.HttpClientNetworkStateHandler;
Expand Down Expand Up @@ -77,16 +79,22 @@
import static com.microsoft.appcenter.distribute.DistributeConstants.LOG_TAG;
import static com.microsoft.appcenter.distribute.DistributeConstants.MEBIBYTE_IN_BYTES;
import static com.microsoft.appcenter.distribute.DistributeConstants.NOTIFICATION_CHANNEL_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PARAMETER_DISTRIBUTION_GROUP_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PARAMETER_INSTALL_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PARAMETER_RELEASE_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PARAMETER_UPDATE_SETUP_FAILED;
import static com.microsoft.appcenter.distribute.DistributeConstants.POSTPONE_TIME_THRESHOLD;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCES_NAME_MOBILE_CENTER;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DISTRIBUTION_GROUP_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DOWNLOADED_RELEASE_HASH;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DOWNLOADED_RELEASE_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DOWNLOAD_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DOWNLOAD_STATE;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_DOWNLOAD_TIME;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_POSTPONE_TIME;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_RELEASE_DETAILS;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_REQUEST_ID;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_TESTER_APP_UPDATE_SETUP_FAILED_MESSAGE_KEY;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_UPDATE_SETUP_FAILED_MESSAGE_KEY;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_UPDATE_SETUP_FAILED_PACKAGE_HASH_KEY;
import static com.microsoft.appcenter.distribute.DistributeConstants.PREFERENCE_KEY_UPDATE_TOKEN;
Expand Down Expand Up @@ -137,6 +145,11 @@ public class Distribute extends AbstractAppCenterService {
*/
private Activity mForegroundActivity;

/**
* Remember if we already tried to open the tester app to update setup.
*/
private boolean mTesterAppOpenedOrAborted;

/**
* Remember if we already tried to open the browser to update setup.
*/
Expand Down Expand Up @@ -234,6 +247,11 @@ public class Distribute extends AbstractAppCenterService {
*/
private String mLauncherActivityClassName;

/**
* Channel listener which adds extra fields to logs.
*/
private DistributeInfoTracker mDistributeInfoTracker;

/**
* Custom listener if any.
*/
Expand Down Expand Up @@ -424,6 +442,11 @@ public synchronized void onActivityPaused(Activity activity) {
@Override
protected synchronized void applyEnabledState(boolean enabled) {
if (enabled) {

/* Enable the distribute info tracker. */
String distributionGroupId = PreferencesStorage.getString(PREFERENCE_KEY_DISTRIBUTION_GROUP_ID);
mDistributeInfoTracker = new DistributeInfoTracker(distributionGroupId);
mChannel.addListener(mDistributeInfoTracker);
HandlerUtils.runOnUiThread(new Runnable() {

@Override
Expand All @@ -434,13 +457,19 @@ public void run() {
} else {

/* Clean all state on disabling, cancel everything. Keep only redirection parameters. */
mTesterAppOpenedOrAborted = false;
mBrowserOpenedOrAborted = false;
mWorkflowCompleted = false;
cancelPreviousTasks();
PreferencesStorage.remove(PREFERENCE_KEY_REQUEST_ID);
PreferencesStorage.remove(PREFERENCE_KEY_POSTPONE_TIME);
PreferencesStorage.remove(PREFERENCE_KEY_UPDATE_SETUP_FAILED_PACKAGE_HASH_KEY);
PreferencesStorage.remove(PREFERENCE_KEY_UPDATE_SETUP_FAILED_MESSAGE_KEY);
PreferencesStorage.remove(PREFERENCE_KEY_TESTER_APP_UPDATE_SETUP_FAILED_MESSAGE_KEY);

/* Disable the distribute info tracker. */
mChannel.removeListener(mDistributeInfoTracker);
mDistributeInfoTracker = null;
}
}

Expand Down Expand Up @@ -583,6 +612,7 @@ private synchronized void resumeDistributeWorkflow() {
AppCenterLog.info(LOG_TAG, "Re-attempting in-app updates setup and cleaning up failure info from storage.");
PreferencesStorage.remove(PREFERENCE_KEY_UPDATE_SETUP_FAILED_PACKAGE_HASH_KEY);
PreferencesStorage.remove(PREFERENCE_KEY_UPDATE_SETUP_FAILED_MESSAGE_KEY);
PreferencesStorage.remove(PREFERENCE_KEY_TESTER_APP_UPDATE_SETUP_FAILED_MESSAGE_KEY);
}
}

Expand Down Expand Up @@ -728,14 +758,28 @@ else if (mUnknownSourcesDialog != null) {
}
}

/* If not, open browser to update setup. */
if (!mBrowserOpenedOrAborted) {
/* If not, open native app (if installed) to update setup, unless it already failed. Otherwise, use the browser. */
String testerAppUpdateSetupFailedMessage = PreferencesStorage.getString(PREFERENCE_KEY_TESTER_APP_UPDATE_SETUP_FAILED_MESSAGE_KEY);
boolean shouldUseTesterAppForUpdateSetup = isAppCenterTesterAppInstalled() && TextUtils.isEmpty(testerAppUpdateSetupFailedMessage) && !mContext.getPackageName().equals(DistributeUtils.TESTER_APP_PACKAGE_NAME);
if (shouldUseTesterAppForUpdateSetup && !mTesterAppOpenedOrAborted) {
DistributeUtils.updateSetupUsingTesterApp(mForegroundActivity, mPackageInfo);
mTesterAppOpenedOrAborted = true;
} else if (!mBrowserOpenedOrAborted) {
DistributeUtils.updateSetupUsingBrowser(mForegroundActivity, mInstallUrl, mAppSecret, mPackageInfo);
mBrowserOpenedOrAborted = true;
}
}
}

private boolean isAppCenterTesterAppInstalled() {
try {
mContext.getPackageManager().getPackageInfo(DistributeUtils.TESTER_APP_PACKAGE_NAME, 0);
} catch (PackageManager.NameNotFoundException ignored) {
return false;
}
return true;
}

private void decryptAndGetReleaseDetails(String updateToken, String distributionGroupId, boolean mobileCenterFailOver) {

/* Decrypt token if any. */
Expand All @@ -759,6 +803,7 @@ private void decryptAndGetReleaseDetails(String updateToken, String distribution
/* If the group was from Mobile Center storage, save it in the new storage. */
if (mobileCenterFailOver) {
PreferencesStorage.putString(PREFERENCE_KEY_DISTRIBUTION_GROUP_ID, distributionGroupId);
mDistributeInfoTracker.updateDistributionGroupId(distributionGroupId);
}

/* Check latest release. */
Expand Down Expand Up @@ -816,6 +861,16 @@ synchronized void storeUpdateSetupFailedParameter(@NonNull String requestId, @No
}
}

/**
* Store a flag for failure to enable updates from the tester apps, to later reattempt using the browser update setup.
*/
synchronized void storeTesterAppUpdateSetupFailedParameter(@NonNull String requestId, @NonNull String updateSetupFailed) {
if (requestId.equals(PreferencesStorage.getString(PREFERENCE_KEY_REQUEST_ID))) {
AppCenterLog.debug(LOG_TAG, "Stored tester app update setup failed parameter.");
PreferencesStorage.putString(PREFERENCE_KEY_TESTER_APP_UPDATE_SETUP_FAILED_MESSAGE_KEY, updateSetupFailed);
}
}

/**
* Store update token and possibly trigger application update check.
*/
Expand All @@ -837,6 +892,7 @@ synchronized void storeRedirectionParameters(@NonNull String requestId, @NonNull
PreferencesStorage.putString(PREFERENCE_KEY_DISTRIBUTION_GROUP_ID, distributionGroupId);
AppCenterLog.debug(LOG_TAG, "Stored redirection parameters.");
PreferencesStorage.remove(PREFERENCE_KEY_REQUEST_ID);
mDistributeInfoTracker.updateDistributionGroupId(distributionGroupId);
cancelPreviousTasks();
getLatestReleaseDetails(distributionGroupId, updateToken);
} else {
Expand All @@ -859,9 +915,9 @@ synchronized void getLatestReleaseDetails(String distributionGroupId, String upd
String releaseHash = computeReleaseHash(mPackageInfo);
String url = mApiUrl;
if (updateToken == null) {
url += String.format(GET_LATEST_PUBLIC_RELEASE_PATH_FORMAT, mAppSecret, distributionGroupId, releaseHash);
url += String.format(GET_LATEST_PUBLIC_RELEASE_PATH_FORMAT, mAppSecret, distributionGroupId, releaseHash, getReportingParametersForUpdatedRelease(true, ""));
} else {
url += String.format(GET_LATEST_PRIVATE_RELEASE_PATH_FORMAT, mAppSecret, releaseHash);
url += String.format(GET_LATEST_PRIVATE_RELEASE_PATH_FORMAT, mAppSecret, releaseHash, getReportingParametersForUpdatedRelease(false, distributionGroupId));
}
Map<String, String> headers = new HashMap<>();
if (updateToken != null) {
Expand Down Expand Up @@ -956,6 +1012,7 @@ private synchronized void handleApiCallFailure(Object releaseCallId, Exception e
AppCenterLog.error(LOG_TAG, "Failed to check latest release:", e);
PreferencesStorage.remove(PREFERENCE_KEY_DISTRIBUTION_GROUP_ID);
PreferencesStorage.remove(PREFERENCE_KEY_UPDATE_TOKEN);
mDistributeInfoTracker.removeDistributionGroupId();
}
}
}
Expand All @@ -965,6 +1022,16 @@ private synchronized void handleApiCallFailure(Object releaseCallId, Exception e
* Handle API call success.
*/
private synchronized void handleApiCallSuccess(Object releaseCallId, String rawReleaseDetails, ReleaseDetails releaseDetails) {
String lastDownloadedReleaseHash = PreferencesStorage.getString(PREFERENCE_KEY_DOWNLOADED_RELEASE_HASH);
if (!TextUtils.isEmpty(lastDownloadedReleaseHash)) {
if (lastDownloadedReleaseHash.equals(DistributeUtils.computeReleaseHash(mPackageInfo))) {
AppCenterLog.debug(LOG_TAG, "Successfully reported app update for downloaded release hash (" + lastDownloadedReleaseHash + "), removing from store..");
PreferencesStorage.remove(PREFERENCE_KEY_DOWNLOADED_RELEASE_HASH);
PreferencesStorage.remove(PREFERENCE_KEY_DOWNLOADED_RELEASE_ID);
} else {
AppCenterLog.debug(LOG_TAG, "Stored release hash doesn't match current installation, probably downloaded but not installed yet, keep in store");
}
}

/* Check if state did not change. */
if (mCheckReleaseCallId == releaseCallId) {
Expand Down Expand Up @@ -1009,6 +1076,39 @@ private synchronized void handleApiCallSuccess(Object releaseCallId, String rawR
}
}

/**
* Get reporting parameters for updated release.
*
* @param isPublic are the parameters for public group or not.
* For public group we report install_id and release_id.
* For private group we report distribution_group_id and release_id.
* @param distributionGroupId distribution group id.
*/
@NonNull
private String getReportingParametersForUpdatedRelease(boolean isPublic, String distributionGroupId) {
String reportingParameters = "";
AppCenterLog.debug(LOG_TAG, "Check if we need to report release installation..");
String lastDownloadedReleaseHash = PreferencesStorage.getString(PREFERENCE_KEY_DOWNLOADED_RELEASE_HASH);
if (!TextUtils.isEmpty(lastDownloadedReleaseHash)) {
String currentInstalledReleaseHash = computeReleaseHash(mPackageInfo);
if (lastDownloadedReleaseHash.equals(currentInstalledReleaseHash)) {
AppCenterLog.debug(LOG_TAG, "Current release was updated but not reported yet, reporting..");
if (isPublic) {
reportingParameters += "&" + PARAMETER_INSTALL_ID + "=" + AppCenter.getInstallId().get();
} else {
reportingParameters += "&" + PARAMETER_DISTRIBUTION_GROUP_ID + "=" + distributionGroupId;
}
int lastDownloadedReleaseId = PreferencesStorage.getInt(PREFERENCE_KEY_DOWNLOADED_RELEASE_ID);
reportingParameters += "&" + PARAMETER_RELEASE_ID + "=" + lastDownloadedReleaseId;
} else {
AppCenterLog.debug(LOG_TAG, "New release was downloaded but not installed yet, skip reporting.");
}
} else {
AppCenterLog.debug(LOG_TAG, "Current release was already reported, skip reporting.");
}
return reportingParameters;
}

/**
* Check if the fetched release information should be installed.
*
Expand Down Expand Up @@ -1190,6 +1290,7 @@ private synchronized void handleUpdateFailedDialogReinstallAction(DialogInterfac

/* Clear the update setup failure info from storage, to re-attempt setup on reinstall. */
PreferencesStorage.remove(PREFERENCE_KEY_UPDATE_SETUP_FAILED_PACKAGE_HASH_KEY);
PreferencesStorage.remove(PREFERENCE_KEY_TESTER_APP_UPDATE_SETUP_FAILED_MESSAGE_KEY);
} else {
showDisabledToast();
}
Expand Down
Loading

0 comments on commit 87b2298

Please sign in to comment.