Skip to content

Commit

Permalink
Merge pull request #1697 from microsoft/develop
Browse files Browse the repository at this point in the history
Version 5.0.2
  • Loading branch information
MikhailSuendukov authored Jun 27, 2023
2 parents d2e7ec7 + a7b768d commit de8553f
Show file tree
Hide file tree
Showing 12 changed files with 147 additions and 23 deletions.
7 changes: 7 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,12 @@
# App Center SDK for Android Change Log

## Version 5.0.2 (In development)

### AppCenter

* **[Improvement]** Support updates using AAB file uploaded to the portal.
* **[Fix]** Fix SDK crash if the `ConnectivityManager.getNetworkInfo` method call throws an exception.

## Version 5.0.1

### AppCenter
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ public void parse() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand All @@ -46,6 +47,7 @@ public void parse() throws JSONException {
assertFalse(releaseDetails.isMandatoryUpdate());
assertEquals("9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60", releaseDetails.getReleaseHash());
assertEquals("fd37a4b1-4937-45ef-97fb-b864154371f0", releaseDetails.getDistributionGroupId());
assertEquals(FileExtension.apk, releaseDetails.getFileExtension());
}

@Test(expected = JSONException.class)
Expand All @@ -59,6 +61,7 @@ public void missingId() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -76,6 +79,7 @@ public void invalidId() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -93,6 +97,7 @@ public void acceptIdAsString() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand All @@ -119,6 +124,7 @@ public void missingVersion() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -136,6 +142,7 @@ public void invalidVersion() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -152,6 +159,7 @@ public void missingShortVersion() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -168,6 +176,7 @@ public void missingReleaseNotes() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand Down Expand Up @@ -195,6 +204,7 @@ public void nullReleaseNotes() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand Down Expand Up @@ -224,6 +234,7 @@ public void nullReleaseNotesUrl() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand All @@ -250,6 +261,7 @@ public void missingApiLevel() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -267,6 +279,7 @@ public void acceptApiLevelAsString() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand Down Expand Up @@ -294,6 +307,7 @@ public void invalidApiLevel() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -310,6 +324,7 @@ public void missingDownloadUrl() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -327,6 +342,7 @@ public void missingDownloadUrlScheme() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -344,6 +360,7 @@ public void invalidDownloadUrlScheme() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -360,6 +377,7 @@ public void missingSize() throws JSONException {
"download_url: 'http://download.thinkbroadband.com/1GB.zip'," +
"mandatory_update: false," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -377,6 +395,7 @@ public void mandatoryUpdate() throws JSONException {
"size: 4242," +
"mandatory_update: true," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand All @@ -403,6 +422,7 @@ public void missingMandatoryUpdate() throws JSONException {
"size: 4242," +
"download_url: 'http://download.thinkbroadband.com/1GB.zip'," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand Down Expand Up @@ -436,6 +456,7 @@ public void emptyPackageHashes() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: []," +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -453,6 +474,7 @@ public void invalidPackageHashes() throws JSONException {
"size: 4242," +
"mandatory_update: false," +
"package_hashes: '9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60'" +
"fileExtension: 'apk'," +
"distribution_group_id: 'fd37a4b1-4937-45ef-97fb-b864154371f0'" +
"}";
ReleaseDetails.parse(json);
Expand All @@ -470,6 +492,7 @@ public void nullDistributionGroupId() throws JSONException {
"download_url: 'http://download.thinkbroadband.com/1GB.zip'," +
"size: 4242," +
"mandatory_update: false," +
"fileExtension: 'apk'," +
"package_hashes: ['9f52199c986d9210842824df695900e1656180946212bd5e8978501a5b732e60']" +
"}";
ReleaseDetails releaseDetails = ReleaseDetails.parse(json);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -77,14 +77,16 @@ public final class DistributeConstants {
static final String PRIVATE_UPDATE_SETUP_PATH_FORMAT = "/apps/%s/private-update-setup/";

/**
* Check latest private release API URL path. Contains variables: appSecret, release_hash, extra query string parameters.
* Check latest private release API URL path. Contains variables: is_install_page, appSecret, release_hash, extra query string parameters.
* is_install_page - API parameter for downloading the update apk file, even if an aab file was uploaded.
*/
static final String GET_LATEST_PRIVATE_RELEASE_PATH_FORMAT = "/sdk/apps/%s/releases/private/latest?release_hash=%s%s";
static final String GET_LATEST_PRIVATE_RELEASE_PATH_FORMAT = "/sdk/apps/%s/releases/private/latest?is_install_page=true&release_hash=%s%s";

/**
* Check latest public release API URL path. Contains variables: appSecret, release_hash, extra query string parameters.
* Check latest public release API URL path. Contains variables: is_install_page, appSecret, release_hash, extra query string parameters.
* is_install_page - API parameter for downloading the update apk file, even if an aab file was uploaded.
*/
static final String GET_LATEST_PUBLIC_RELEASE_PATH_FORMAT = "/public/sdk/apps/%s/releases/latest?release_hash=%s%s";
static final String GET_LATEST_PUBLIC_RELEASE_PATH_FORMAT = "/public/sdk/apps/%s/releases/latest?is_install_page=true&release_hash=%s%s";

/**
* API parameter for release hash.
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
package com.microsoft.appcenter.distribute;

public enum FileExtension {
aab,
apk
}
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,8 @@ public class ReleaseDetails {

private static final String MIN_API_LEVEL = "android_min_api_level";

private static final String FILE_EXTENSION = "fileExtension";

private static final String DOWNLOAD_URL = "download_url";

private static final String MANDATORY_UPDATE = "mandatory_update";
Expand Down Expand Up @@ -79,6 +81,11 @@ public class ReleaseDetails {
*/
private int minApiLevel;

/**
* The original update file extension.
*/
private FileExtension fileExtension;

/**
* The URL that hosts the binary for this release.
*/
Expand Down Expand Up @@ -117,6 +124,7 @@ static ReleaseDetails parse(String json) throws JSONException {
releaseDetails.releaseNotes = object.isNull(RELEASE_NOTES) ? null : object.getString(RELEASE_NOTES);
releaseDetails.releaseNotesUrl = object.isNull(RELEASE_NOTES_URL) ? null : Uri.parse(object.getString(RELEASE_NOTES_URL));
releaseDetails.minApiLevel = object.getInt(MIN_API_LEVEL);
releaseDetails.fileExtension = FileExtension.valueOf(object.getString(FILE_EXTENSION));
releaseDetails.downloadUrl = Uri.parse(object.getString(DOWNLOAD_URL));
String scheme = releaseDetails.downloadUrl.getScheme();
if (scheme == null || !scheme.startsWith("http")) {
Expand Down Expand Up @@ -195,6 +203,15 @@ int getMinApiLevel() {
return minApiLevel;
}

/**
* Get The original update file extension value.
*
* @return the FileExtension value.
*/
public FileExtension getFileExtension() {
return fileExtension;
}

/**
* Get the downloadUrl value.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,7 @@
import androidx.annotation.NonNull;
import androidx.annotation.WorkerThread;

import com.microsoft.appcenter.distribute.FileExtension;
import com.microsoft.appcenter.distribute.R;
import com.microsoft.appcenter.distribute.ReleaseDetails;
import com.microsoft.appcenter.distribute.download.AbstractReleaseDownloader;
Expand Down Expand Up @@ -249,6 +250,11 @@ synchronized void onDownloadError(RuntimeException e) {
}

private boolean isDownloadedFileValid() {
// As per the current system design, only the files with APK
// extension have their size correctly indicated in the release details.
if (mReleaseDetails.getFileExtension() != FileExtension.apk) {
return true;
}
try (ParcelFileDescriptor fileDescriptor = getDownloadManager().openDownloadedFile(mDownloadId)) {
return fileDescriptor.getStatSize() == mReleaseDetails.getSize();
} catch (IOException e) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -187,6 +187,7 @@ public void run() {

/* Cancels installation if this flag hasn't been reset by progress event. */
if (mUserConfirmationRequested) {
AppCenterLog.error(LOG_TAG, "Canceling installation due to lack of progress.");
onCancel();
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1284,7 +1284,7 @@ public void willNotReportReleaseInstallForPrivateGroupWithoutStoredReleaseHash()
Distribute.setUpdateTrack(UpdateTrack.PRIVATE);
start();
Distribute.getInstance().onActivityResumed(mActivity);
verify(mHttpClient).callAsync(matches("^https://.*?/sdk/apps/a/releases/private/latest\\?release_hash=" + TEST_HASH + "$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
verify(mHttpClient).callAsync(matches("^https://.*?/sdk/apps/a/releases/private/latest\\?is_install_page=true&release_hash=" + TEST_HASH + "$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
}

@Test
Expand All @@ -1301,7 +1301,7 @@ public void willNotReportReleaseInstallForPrivateGroupWhenReleaseHashesDoNotMatc
Distribute.setUpdateTrack(UpdateTrack.PRIVATE);
start();
Distribute.getInstance().onActivityResumed(mActivity);
verify(mHttpClient).callAsync(matches("^https://.*?/sdk/apps/a/releases/private/latest\\?release_hash=" + TEST_HASH + "$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
verify(mHttpClient).callAsync(matches("^https://.*?/sdk/apps/a/releases/private/latest\\?is_install_page=true&release_hash=" + TEST_HASH + "$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
}

@Test
Expand All @@ -1320,7 +1320,7 @@ public void reportReleaseInstallForPrivateGroupWhenReleaseHashesMatch() {
Distribute.setUpdateTrack(UpdateTrack.PRIVATE);
start();
Distribute.getInstance().onActivityResumed(mActivity);
verify(mHttpClient).callAsync(matches("^https://.*?/sdk/apps/a/releases/private/latest\\?release_hash=" + TEST_HASH + "&distribution_group_id=" + distributionGroupId + "&downloaded_release_id=4$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
verify(mHttpClient).callAsync(matches("^https://.*?/sdk/apps/a/releases/private/latest\\?is_install_page=true&release_hash=" + TEST_HASH + "&distribution_group_id=" + distributionGroupId + "&downloaded_release_id=4$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
}

@Test
Expand All @@ -1337,7 +1337,7 @@ public void reportReleaseInstallForPublicGroupWhenReleaseHashesMatch() {
/* Primary storage will be missing data. */
start();
Distribute.getInstance().onActivityResumed(mActivity);
verify(mHttpClient).callAsync(matches("^https://.*?/public/sdk/apps/a/releases/latest\\?release_hash=" + TEST_HASH + "&install_id=" + mInstallId + "&distribution_group_id=" + distributionGroupId + "&downloaded_release_id=4$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
verify(mHttpClient).callAsync(matches("^https://.*?/public/sdk/apps/a/releases/latest\\?is_install_page=true&release_hash=" + TEST_HASH + "&install_id=" + mInstallId + "&distribution_group_id=" + distributionGroupId + "&downloaded_release_id=4$"), eq("GET"), eq(headers), any(HttpClient.CallTemplate.class), any(ServiceCallback.class));
}

@Test
Expand Down
Loading

0 comments on commit de8553f

Please sign in to comment.