Skip to content

Commit 6168717

Browse files
authored
Merge pull request #380 from Microsoft/feature/add_release_hash_to_release_api_check
Add release_hash to query string when checking releases
2 parents 1da0e64 + 069c9f7 commit 6168717

File tree

8 files changed

+72
-143
lines changed

8 files changed

+72
-143
lines changed

sdk/mobile-center-distribute/src/main/java/com/microsoft/azure/mobile/distribute/Distribute.java

Lines changed: 42 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -77,6 +77,7 @@
7777
import static com.microsoft.azure.mobile.distribute.DistributeConstants.PREFERENCE_KEY_REQUEST_ID;
7878
import static com.microsoft.azure.mobile.distribute.DistributeConstants.PREFERENCE_KEY_UPDATE_TOKEN;
7979
import static com.microsoft.azure.mobile.distribute.DistributeConstants.SERVICE_NAME;
80+
import static com.microsoft.azure.mobile.distribute.DistributeUtils.computeReleaseHash;
8081
import static com.microsoft.azure.mobile.distribute.DistributeUtils.getStoredDownloadState;
8182
import static com.microsoft.azure.mobile.http.DefaultHttpClient.METHOD_GET;
8283

@@ -112,6 +113,11 @@ public class Distribute extends AbstractMobileCenterService {
112113
*/
113114
private String mAppSecret;
114115

116+
/**
117+
* Package info.
118+
*/
119+
private PackageInfo mPackageInfo;
120+
115121
/**
116122
* If not null we are in foreground inside this activity.
117123
*/
@@ -278,6 +284,11 @@ public synchronized void onStarted(@NonNull Context context, @NonNull String app
278284
super.onStarted(context, appSecret, channel);
279285
mContext = context;
280286
mAppSecret = appSecret;
287+
try {
288+
mPackageInfo = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0);
289+
} catch (PackageManager.NameNotFoundException e) {
290+
MobileCenterLog.error(LOG_TAG, "Could not get self package info.", e);
291+
}
281292
resumeDistributeWorkflow();
282293
}
283294

@@ -398,7 +409,7 @@ private synchronized void cancelPreviousTasks() {
398409
* Method that triggers the distribute workflow or proceed to the next step.
399410
*/
400411
private synchronized void resumeDistributeWorkflow() {
401-
if (mForegroundActivity != null && !mWorkflowCompleted && isInstanceEnabled()) {
412+
if (mPackageInfo != null && mForegroundActivity != null && !mWorkflowCompleted && isInstanceEnabled()) {
402413

403414
/* Don't go any further it this is a debug app. */
404415
if ((mContext.getApplicationInfo().flags & FLAG_DEBUGGABLE) == FLAG_DEBUGGABLE) {
@@ -440,15 +451,7 @@ private synchronized void resumeDistributeWorkflow() {
440451
if (downloadState != DOWNLOAD_STATE_COMPLETED && downloadState != DOWNLOAD_STATE_AVAILABLE && !mCheckedDownload) {
441452

442453
/* Discard release if application updated. Then immediately check release. */
443-
long lastUpdateTime;
444-
try {
445-
lastUpdateTime = mContext.getPackageManager().getPackageInfo(mContext.getPackageName(), 0).lastUpdateTime;
446-
} catch (PackageManager.NameNotFoundException e) {
447-
MobileCenterLog.debug(LOG_TAG, "Could not check last update time.", e);
448-
completeWorkflow();
449-
return;
450-
}
451-
if (lastUpdateTime > StorageHelper.PreferencesStorage.getLong(PREFERENCE_KEY_DOWNLOAD_TIME)) {
454+
if (mPackageInfo.lastUpdateTime > StorageHelper.PreferencesStorage.getLong(PREFERENCE_KEY_DOWNLOAD_TIME)) {
452455
MobileCenterLog.debug(LOG_TAG, "Discarding previous download as application updated.");
453456
cancelPreviousTasks();
454457
}
@@ -546,7 +549,7 @@ else if (mUnknownSourcesDialog != null) {
546549

547550
/* If not, open browser to update setup. */
548551
if (!mBrowserOpenedOrAborted) {
549-
DistributeUtils.updateSetupUsingBrowser(mForegroundActivity, mInstallUrl, mAppSecret);
552+
DistributeUtils.updateSetupUsingBrowser(mForegroundActivity, mInstallUrl, mAppSecret, mPackageInfo);
550553
mBrowserOpenedOrAborted = true;
551554
}
552555
}
@@ -623,7 +626,7 @@ synchronized void getLatestReleaseDetails(@NonNull String updateToken) {
623626
HttpClientRetryer retryer = new HttpClientRetryer(new DefaultHttpClient());
624627
NetworkStateHelper networkStateHelper = NetworkStateHelper.getSharedInstance(mContext);
625628
HttpClient httpClient = new HttpClientNetworkStateHandler(retryer, networkStateHelper);
626-
String url = mApiUrl + String.format(GET_LATEST_RELEASE_PATH_FORMAT, mAppSecret);
629+
String url = mApiUrl + String.format(GET_LATEST_RELEASE_PATH_FORMAT, mAppSecret, computeReleaseHash(mPackageInfo));
627630
Map<String, String> headers = new HashMap<>();
628631
headers.put(HEADER_API_TOKEN, updateToken);
629632
final Object releaseCallId = mCheckReleaseCallId = new Object();
@@ -738,38 +741,32 @@ else if (Build.VERSION.SDK_INT >= releaseDetails.getMinApiLevel()) {
738741

739742
/* Check version code is equals or higher and hash is different. */
740743
MobileCenterLog.debug(LOG_TAG, "Check if latest release is more recent.");
741-
PackageManager packageManager = mContext.getPackageManager();
742-
try {
743-
PackageInfo packageInfo = packageManager.getPackageInfo(mContext.getPackageName(), 0);
744-
if (isMoreRecent(packageInfo, releaseDetails)) {
745-
746-
/* Update cache. */
747-
PreferencesStorage.putString(PREFERENCE_KEY_RELEASE_DETAILS, rawReleaseDetails);
748-
749-
/* If previous release is mandatory and still processing, don't do anything right now. */
750-
if (mReleaseDetails != null && mReleaseDetails.isMandatoryUpdate()) {
751-
if (mReleaseDetails.getId() != releaseDetails.getId()) {
752-
MobileCenterLog.debug(LOG_TAG, "Latest release is more recent than the previous mandatory.");
753-
PreferencesStorage.putInt(PREFERENCE_KEY_DOWNLOAD_STATE, DOWNLOAD_STATE_AVAILABLE);
754-
} else {
755-
MobileCenterLog.debug(LOG_TAG, "The latest release is mandatory and already being processed.");
756-
}
757-
return;
758-
}
759-
760-
/* Show update dialog. */
761-
mReleaseDetails = releaseDetails;
762-
MobileCenterLog.debug(LOG_TAG, "Latest release is more recent.");
763-
PreferencesStorage.putInt(PREFERENCE_KEY_DOWNLOAD_STATE, DOWNLOAD_STATE_AVAILABLE);
764-
if (mForegroundActivity != null) {
765-
showUpdateDialog();
744+
if (isMoreRecent(releaseDetails)) {
745+
746+
/* Update cache. */
747+
PreferencesStorage.putString(PREFERENCE_KEY_RELEASE_DETAILS, rawReleaseDetails);
748+
749+
/* If previous release is mandatory and still processing, don't do anything right now. */
750+
if (mReleaseDetails != null && mReleaseDetails.isMandatoryUpdate()) {
751+
if (mReleaseDetails.getId() != releaseDetails.getId()) {
752+
MobileCenterLog.debug(LOG_TAG, "Latest release is more recent than the previous mandatory.");
753+
PreferencesStorage.putInt(PREFERENCE_KEY_DOWNLOAD_STATE, DOWNLOAD_STATE_AVAILABLE);
754+
} else {
755+
MobileCenterLog.debug(LOG_TAG, "The latest release is mandatory and already being processed.");
766756
}
767757
return;
768-
} else {
769-
MobileCenterLog.debug(LOG_TAG, "Latest release is not more recent.");
770758
}
771-
} catch (PackageManager.NameNotFoundException e) {
772-
MobileCenterLog.error(LOG_TAG, "Could not compare release versions.", e);
759+
760+
/* Show update dialog. */
761+
mReleaseDetails = releaseDetails;
762+
MobileCenterLog.debug(LOG_TAG, "Latest release is more recent.");
763+
PreferencesStorage.putInt(PREFERENCE_KEY_DOWNLOAD_STATE, DOWNLOAD_STATE_AVAILABLE);
764+
if (mForegroundActivity != null) {
765+
showUpdateDialog();
766+
}
767+
return;
768+
} else {
769+
MobileCenterLog.debug(LOG_TAG, "Latest release is not more recent.");
773770
}
774771
} else {
775772
MobileCenterLog.info(LOG_TAG, "This device is not compatible with the latest release.");
@@ -783,15 +780,14 @@ else if (Build.VERSION.SDK_INT >= releaseDetails.getMinApiLevel()) {
783780
/**
784781
* Check if the fetched release information should be installed.
785782
*
786-
* @param packageInfo current app version.
787783
* @param releaseDetails latest release on server.
788784
* @return true if latest release on server should be used.
789785
*/
790-
private boolean isMoreRecent(PackageInfo packageInfo, ReleaseDetails releaseDetails) {
791-
if (releaseDetails.getVersion() == packageInfo.versionCode) {
792-
return !releaseDetails.getReleaseHash().equals(DistributeUtils.computeReleaseHash(mContext, packageInfo));
786+
private boolean isMoreRecent(ReleaseDetails releaseDetails) {
787+
if (releaseDetails.getVersion() == mPackageInfo.versionCode) {
788+
return !releaseDetails.getReleaseHash().equals(DistributeUtils.computeReleaseHash(mPackageInfo));
793789
}
794-
return releaseDetails.getVersion() > packageInfo.versionCode;
790+
return releaseDetails.getVersion() > mPackageInfo.versionCode;
795791
}
796792

797793
/**

sdk/mobile-center-distribute/src/main/java/com/microsoft/azure/mobile/distribute/DistributeConstants.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ final class DistributeConstants {
4949
/**
5050
* Check latest release API URL path. Contains the app secret variable to replace.
5151
*/
52-
static final String GET_LATEST_RELEASE_PATH_FORMAT = "/sdk/apps/%s/releases/latest";
52+
static final String GET_LATEST_RELEASE_PATH_FORMAT = "/sdk/apps/%s/releases/latest?release_hash=%s";
5353

5454
/**
5555
* API parameter for release hash.

sdk/mobile-center-distribute/src/main/java/com/microsoft/azure/mobile/distribute/DistributeUtils.java

Lines changed: 8 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -2,10 +2,8 @@
22

33
import android.app.Activity;
44
import android.app.Notification;
5-
import android.content.Context;
65
import android.content.Intent;
76
import android.content.pm.PackageInfo;
8-
import android.content.pm.PackageManager;
97
import android.net.Uri;
108
import android.os.Build;
119
import android.support.annotation.NonNull;
@@ -90,18 +88,19 @@ static int getStoredDownloadState() {
9088
}
9189

9290
@NonNull
93-
static String computeReleaseHash(@NonNull Context context, @NonNull PackageInfo packageInfo) {
94-
return HashUtils.sha256(context.getPackageName() + ":" + packageInfo.versionName + ":" + packageInfo.versionCode);
91+
static String computeReleaseHash(@NonNull PackageInfo packageInfo) {
92+
return HashUtils.sha256(packageInfo.packageName + ":" + packageInfo.versionName + ":" + packageInfo.versionCode);
9593
}
9694

9795
/**
9896
* Update setup using browser.
9997
*
100-
* @param activity activity from which to start browser.
101-
* @param installUrl base install site URL.
102-
* @param appSecret application secret.
98+
* @param activity activity from which to start browser.
99+
* @param installUrl base install site URL.
100+
* @param appSecret application secret.
101+
* @param packageInfo package info.
103102
*/
104-
static void updateSetupUsingBrowser(Activity activity, String installUrl, String appSecret) {
103+
static void updateSetupUsingBrowser(Activity activity, String installUrl, String appSecret, PackageInfo packageInfo) {
105104

106105
/*
107106
* If network is disconnected, browser will fail so wait.
@@ -115,15 +114,7 @@ static void updateSetupUsingBrowser(Activity activity, String installUrl, String
115114
}
116115

117116
/* Compute hash. */
118-
String releaseHash;
119-
try {
120-
PackageManager packageManager = activity.getPackageManager();
121-
PackageInfo packageInfo = packageManager.getPackageInfo(activity.getPackageName(), 0);
122-
releaseHash = computeReleaseHash(activity, packageInfo);
123-
} catch (PackageManager.NameNotFoundException e) {
124-
MobileCenterLog.error(LOG_TAG, "Could not get package info", e);
125-
return;
126-
}
117+
String releaseHash = computeReleaseHash(packageInfo);
127118

128119
/* Generate request identifier. */
129120
String requestId = UUIDUtils.randomUUID().toString();

sdk/mobile-center-distribute/src/test/java/com/microsoft/azure/mobile/distribute/AbstractDistributeTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -127,6 +127,7 @@ public Void answer(InvocationOnMock invocation) throws Throwable {
127127
when(mActivity.getPackageManager()).thenReturn(mPackageManager);
128128
PackageInfo packageInfo = mock(PackageInfo.class);
129129
when(mPackageManager.getPackageInfo("com.contoso", 0)).thenReturn(packageInfo);
130+
Whitebox.setInternalState(packageInfo, "packageName", "com.contoso");
130131
Whitebox.setInternalState(packageInfo, "versionName", "1.2.3");
131132
Whitebox.setInternalState(packageInfo, "versionCode", 6);
132133

sdk/mobile-center-distribute/src/test/java/com/microsoft/azure/mobile/distribute/DistributeBeforeApiSuccessTest.java

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@
4646
import static org.junit.Assert.assertFalse;
4747
import static org.junit.Assert.assertTrue;
4848
import static org.mockito.Matchers.any;
49+
import static org.mockito.Matchers.anyInt;
4950
import static org.mockito.Matchers.anyMapOf;
5051
import static org.mockito.Matchers.anyString;
5152
import static org.mockito.Matchers.argThat;
@@ -114,6 +115,13 @@ public void doNothingIfInstallComesFromStore() throws Exception {
114115
testDistributeInactive();
115116
}
116117

118+
@Test
119+
@SuppressWarnings("WrongConstant")
120+
public void doNothingIfGetPackageInfoFails() throws Exception {
121+
when(mPackageManager.getPackageInfo(anyString(), anyInt())).thenThrow(new PackageManager.NameNotFoundException());
122+
testDistributeInactive();
123+
}
124+
117125
@Test
118126
public void storeTokenBeforeStart() throws Exception {
119127

sdk/mobile-center-distribute/src/test/java/com/microsoft/azure/mobile/distribute/DistributeBeforeDownloadTest.java

Lines changed: 0 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,6 @@
33
import android.app.Activity;
44
import android.content.Context;
55
import android.content.DialogInterface;
6-
import android.content.pm.PackageManager;
76
import android.os.Build;
87

98
import com.microsoft.azure.mobile.channel.Channel;
@@ -55,45 +54,6 @@
5554

5655
public class DistributeBeforeDownloadTest extends AbstractDistributeTest {
5756

58-
@Test
59-
public void failsToCompareVersion() throws Exception {
60-
61-
/* Mock we already have token. */
62-
when(PreferencesStorage.getString(PREFERENCE_KEY_UPDATE_TOKEN)).thenReturn("some token");
63-
HttpClientNetworkStateHandler httpClient = mock(HttpClientNetworkStateHandler.class);
64-
whenNew(HttpClientNetworkStateHandler.class).withAnyArguments().thenReturn(httpClient);
65-
when(httpClient.callAsync(anyString(), anyString(), anyMapOf(String.class, String.class), any(HttpClient.CallTemplate.class), any(ServiceCallback.class))).thenAnswer(new Answer<ServiceCall>() {
66-
67-
@Override
68-
public ServiceCall answer(InvocationOnMock invocation) throws Throwable {
69-
((ServiceCallback) invocation.getArguments()[4]).onCallSucceeded("mock");
70-
return mock(ServiceCall.class);
71-
}
72-
});
73-
HashMap<String, String> headers = new HashMap<>();
74-
headers.put(DistributeConstants.HEADER_API_TOKEN, "some token");
75-
ReleaseDetails releaseDetails = mock(ReleaseDetails.class);
76-
when(releaseDetails.getId()).thenReturn(4);
77-
when(ReleaseDetails.parse(anyString())).thenReturn(releaseDetails);
78-
when(mPackageManager.getPackageInfo("com.contoso", 0)).thenThrow(new PackageManager.NameNotFoundException());
79-
80-
/* Trigger call. */
81-
Distribute.getInstance().onStarted(mContext, "a", mock(Channel.class));
82-
Distribute.getInstance().onActivityResumed(mock(Activity.class));
83-
verify(httpClient).callAsync(anyString(), anyString(), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
84-
85-
/* Verify on failure we complete workflow. */
86-
verifyStatic();
87-
PreferencesStorage.remove(PREFERENCE_KEY_DOWNLOAD_STATE);
88-
verify(mDialogBuilder, never()).create();
89-
verify(mDialog, never()).show();
90-
91-
/* After that if we resume app nothing happens. */
92-
Distribute.getInstance().onActivityPaused(mock(Activity.class));
93-
Distribute.getInstance().onActivityResumed(mock(Activity.class));
94-
verify(httpClient).callAsync(anyString(), anyString(), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
95-
}
96-
9757
@Test
9858
public void moreRecentWithIncompatibleMinApiLevel() throws Exception {
9959

sdk/mobile-center-distribute/src/test/java/com/microsoft/azure/mobile/distribute/DistributeDownloadTest.java

Lines changed: 0 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -755,19 +755,4 @@ public Object answer(InvocationOnMock invocation) throws Throwable {
755755
/* Verify new release checked (for example what we installed was something else than the upgrade. */
756756
verify(mDialog, times(2)).show();
757757
}
758-
759-
@Test
760-
@SuppressWarnings("deprecation")
761-
public void failToCheckLastUpdateTimeOnRestart() throws PackageManager.NameNotFoundException {
762-
763-
/* Make the package manager fails on restart after download started. */
764-
waitDownloadTask();
765-
when(mPackageManager.getPackageInfo(mContext.getPackageName(), 0)).thenThrow(new PackageManager.NameNotFoundException());
766-
restartProcessAndSdk();
767-
Distribute.getInstance().onActivityResumed(mActivity);
768-
769-
/* Verify workflow completed on failure. */
770-
verifyStatic();
771-
PreferencesStorage.remove(PREFERENCE_KEY_DOWNLOAD_STATE);
772-
}
773758
}

0 commit comments

Comments
 (0)