mirror of
https://github.com/zhigang1992/react-native-code-push.git
synced 2026-06-16 02:44:33 +08:00
report acquisition status
This commit is contained in:
@@ -23,7 +23,9 @@ import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.AsyncTask;
|
||||
import android.provider.Settings;
|
||||
|
||||
import org.json.JSONArray;
|
||||
import org.json.JSONException;
|
||||
import org.json.JSONObject;
|
||||
|
||||
@@ -43,17 +45,24 @@ public class CodePush {
|
||||
|
||||
private String assetsBundleFileName;
|
||||
|
||||
private final String ASSETS_BUNDLE_PREFIX = "assets://";
|
||||
private final String BINARY_MODIFIED_TIME_KEY = "binaryModifiedTime";
|
||||
private final String CODE_PUSH_PREFERENCES = "CodePush";
|
||||
private final String DEPLOYMENT_FAILED_STATUS = "DeploymentFailed";
|
||||
private final String DEPLOYMENT_KEY_KEY = "deploymentKey";
|
||||
private final String DEPLOYMENT_SUCCEEDED_STATUS = "DeploymentSucceeded";
|
||||
private final String DOWNLOAD_PROGRESS_EVENT_NAME = "CodePushDownloadProgress";
|
||||
private final String FAILED_UPDATES_KEY = "CODE_PUSH_FAILED_UPDATES";
|
||||
private final String PENDING_UPDATE_KEY = "CODE_PUSH_PENDING_UPDATE";
|
||||
private final String LABEL_KEY = "label";
|
||||
private final String PACKAGE_HASH_KEY = "packageHash";
|
||||
private final String PENDING_UPDATE_HASH_KEY = "hash";
|
||||
private final String PENDING_UPDATE_IS_LOADING_KEY = "isLoading";
|
||||
private final String ASSETS_BUNDLE_PREFIX = "assets://";
|
||||
private final String CODE_PUSH_PREFERENCES = "CodePush";
|
||||
private final String DOWNLOAD_PROGRESS_EVENT_NAME = "CodePushDownloadProgress";
|
||||
private final String PENDING_UPDATE_KEY = "CODE_PUSH_PENDING_UPDATE";
|
||||
private final String RESOURCES_BUNDLE = "resources.arsc";
|
||||
private final String STATUS_REPORTS_KEY = "CODE_PUSH_STATUS_REPORTS";
|
||||
|
||||
// This needs to be kept in sync with https://github.com/facebook/react-native/blob/master/ReactAndroid/src/main/java/com/facebook/react/devsupport/DevSupportManager.java#L78
|
||||
private final String REACT_DEV_BUNDLE_CACHE_FILE_NAME = "ReactNativeDevBundle.js";
|
||||
private final String BINARY_MODIFIED_TIME_KEY = "binaryModifiedTime";
|
||||
|
||||
private CodePushPackage codePushPackage;
|
||||
private CodePushReactPackage codePushReactPackage;
|
||||
@@ -145,7 +154,7 @@ public class CodePush {
|
||||
String pacakgeAppVersion = CodePushUtils.tryGetString(packageMetadata, "appVersion");
|
||||
if (binaryModifiedDateDuringPackageInstall != null &&
|
||||
binaryModifiedDateDuringPackageInstall == binaryResourcesModifiedTime &&
|
||||
this.appVersion.equals(pacakgeAppVersion)) {
|
||||
(this.isUsingTestConfiguration() || this.appVersion.equals(pacakgeAppVersion))) {
|
||||
CodePushUtils.logBundleUrl(packageFilePath);
|
||||
return packageFilePath;
|
||||
} else {
|
||||
@@ -165,6 +174,36 @@ public class CodePush {
|
||||
}
|
||||
}
|
||||
|
||||
private String getPackageStatusReportIdentifier(WritableMap updatePackage) {
|
||||
// Because deploymentKeys can be dynamically switched, we use a
|
||||
// combination of the deploymentKey and label as the packageIdentifier.
|
||||
String deploymentKey = CodePushUtils.tryGetString(updatePackage, DEPLOYMENT_KEY_KEY);
|
||||
String label = CodePushUtils.tryGetString(updatePackage, LABEL_KEY);
|
||||
if (deploymentKey != null && label != null) {
|
||||
return deploymentKey + ":" + label;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private JSONArray getFailedUpdates() {
|
||||
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
|
||||
String failedUpdatesString = settings.getString(FAILED_UPDATES_KEY, null);
|
||||
if (failedUpdatesString == null) {
|
||||
return new JSONArray();
|
||||
}
|
||||
|
||||
try {
|
||||
JSONArray failedUpdates = new JSONArray(failedUpdatesString);
|
||||
return failedUpdates;
|
||||
} catch (JSONException e) {
|
||||
// Unrecognized data format, clear and replace with expected format.
|
||||
JSONArray emptyArray = new JSONArray();
|
||||
settings.edit().putString(FAILED_UPDATES_KEY, emptyArray.toString()).commit();
|
||||
return emptyArray;
|
||||
}
|
||||
}
|
||||
|
||||
private JSONObject getPendingUpdate() {
|
||||
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
|
||||
String pendingUpdateString = settings.getString(PENDING_UPDATE_KEY, null);
|
||||
@@ -217,22 +256,39 @@ public class CodePush {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFailedHash(String packageHash) {
|
||||
|
||||
private boolean isDeploymentStatusNotYetReported(String appVersionOrPackageIdentifier) {
|
||||
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
|
||||
String failedUpdatesString = settings.getString(FAILED_UPDATES_KEY, null);
|
||||
if (failedUpdatesString == null) {
|
||||
return false;
|
||||
String sentStatusReportsString = settings.getString(STATUS_REPORTS_KEY, null);
|
||||
if (sentStatusReportsString == null) {
|
||||
return true;
|
||||
} else {
|
||||
try {
|
||||
JSONObject sentStatusReports = new JSONObject(sentStatusReportsString);
|
||||
return !sentStatusReports.has(appVersionOrPackageIdentifier);
|
||||
} catch (JSONException e) {
|
||||
throw new CodePushUnknownException("Unable to parse sent status reports information " +
|
||||
sentStatusReportsString + " stored in SharedPreferences.", e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isFailedHash(String packageHash) {
|
||||
JSONArray failedUpdates = getFailedUpdates();
|
||||
for (int i = 0; i < failedUpdates.length(); i++) {
|
||||
JSONObject failedPackage = null;
|
||||
try {
|
||||
failedPackage = failedUpdates.getJSONObject(i);
|
||||
String failedPackageHash = failedPackage.getString(PACKAGE_HASH_KEY);
|
||||
if (packageHash.equals(failedPackageHash)) {
|
||||
return true;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new CodePushUnknownException("Unable to read failedUpdates data stored in SharedPreferences.", e);
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
JSONObject failedUpdates = new JSONObject(failedUpdatesString);
|
||||
return failedUpdates.has(packageHash);
|
||||
} catch (JSONException e) {
|
||||
// Should not happen.
|
||||
throw new CodePushUnknownException("Unable to parse failed updates information " +
|
||||
failedUpdatesString + " stored in SharedPreferences", e);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isPendingUpdate(String packageHash) {
|
||||
@@ -249,6 +305,24 @@ public class CodePush {
|
||||
}
|
||||
}
|
||||
|
||||
private void recordDeploymentStatusReported(String appVersionOrPackageIdentifier, String status) {
|
||||
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
|
||||
String sentStatusReportsString = settings.getString(STATUS_REPORTS_KEY, null);
|
||||
JSONObject sentStatusReports;
|
||||
try {
|
||||
if (sentStatusReportsString == null) {
|
||||
sentStatusReports = new JSONObject();
|
||||
} else {
|
||||
sentStatusReports = new JSONObject(sentStatusReportsString);
|
||||
}
|
||||
|
||||
sentStatusReports.put(appVersionOrPackageIdentifier, status);
|
||||
settings.edit().putString(STATUS_REPORTS_KEY, sentStatusReports.toString()).commit();
|
||||
} catch (JSONException e) {
|
||||
throw new CodePushUnknownException("Unable to save new entry in SharedPreferences under " + STATUS_REPORTS_KEY + ".", e);
|
||||
}
|
||||
}
|
||||
|
||||
private void removeFailedUpdates() {
|
||||
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
|
||||
settings.edit().remove(FAILED_UPDATES_KEY).commit();
|
||||
@@ -261,8 +335,8 @@ public class CodePush {
|
||||
|
||||
private void rollbackPackage() {
|
||||
try {
|
||||
String packageHash = codePushPackage.getCurrentPackageHash();
|
||||
saveFailedUpdate(packageHash);
|
||||
WritableMap failedPackage = codePushPackage.getCurrentPackage();
|
||||
saveFailedUpdate(failedPackage);
|
||||
} catch (IOException e) {
|
||||
throw new CodePushUnknownException("Attempted a rollback without having a current downloaded package", e);
|
||||
}
|
||||
@@ -276,29 +350,25 @@ public class CodePush {
|
||||
removePendingUpdate();
|
||||
}
|
||||
|
||||
private void saveFailedUpdate(String packageHash) {
|
||||
private void saveFailedUpdate(WritableMap failedPackage) {
|
||||
SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0);
|
||||
String failedUpdatesString = settings.getString(FAILED_UPDATES_KEY, null);
|
||||
JSONObject failedUpdates;
|
||||
JSONArray failedUpdates;
|
||||
if (failedUpdatesString == null) {
|
||||
failedUpdates = new JSONObject();
|
||||
failedUpdates = new JSONArray();
|
||||
} else {
|
||||
try {
|
||||
failedUpdates = new JSONObject(failedUpdatesString);
|
||||
failedUpdates = new JSONArray(failedUpdatesString);
|
||||
} catch (JSONException e) {
|
||||
// Should not happen.
|
||||
throw new CodePushMalformedDataException("Unable to parse failed updates information " +
|
||||
failedUpdatesString + " stored in SharedPreferences", e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
failedUpdates.put(packageHash, true);
|
||||
settings.edit().putString(FAILED_UPDATES_KEY, failedUpdates.toString()).commit();
|
||||
} catch (JSONException e) {
|
||||
// Should not happen unless the packageHash is null.
|
||||
throw new CodePushUnknownException("Unable to save package hash " +
|
||||
packageHash + " as a failed update", e);
|
||||
}
|
||||
|
||||
JSONObject failedPackageJSON = CodePushUtils.convertReadableToJsonObject(failedPackage);
|
||||
failedUpdates.put(failedPackageJSON);
|
||||
settings.edit().putString(FAILED_UPDATES_KEY, failedUpdates.toString()).commit();
|
||||
}
|
||||
|
||||
private void savePendingUpdate(String packageHash, boolean isLoading) {
|
||||
@@ -377,6 +447,9 @@ public class CodePush {
|
||||
configMap.putInt("buildVersion", buildVersion);
|
||||
configMap.putString("deploymentKey", deploymentKey);
|
||||
configMap.putString("serverUrl", serverUrl);
|
||||
configMap.putString("clientUniqueId",
|
||||
Settings.Secure.getString(mainActivity.getContentResolver(),
|
||||
android.provider.Settings.Secure.ANDROID_ID));
|
||||
promise.resolve(configMap);
|
||||
}
|
||||
|
||||
@@ -408,7 +481,60 @@ public class CodePush {
|
||||
|
||||
asyncTask.execute();
|
||||
}
|
||||
|
||||
|
||||
@ReactMethod
|
||||
public void getNewStatusReport(Promise promise) {
|
||||
// Check if the current appVersion has been reported.
|
||||
if (isDeploymentStatusNotYetReported(appVersion)) {
|
||||
recordDeploymentStatusReported(appVersion, DEPLOYMENT_SUCCEEDED_STATUS);
|
||||
WritableNativeMap reportMap = new WritableNativeMap();
|
||||
reportMap.putString("appVersion", appVersion);
|
||||
promise.resolve(reportMap);
|
||||
return;
|
||||
}
|
||||
|
||||
// Check if there was a rollback that was not yet reported
|
||||
JSONArray failedUpdates = getFailedUpdates();
|
||||
if (failedUpdates != null && failedUpdates.length() > 0) {
|
||||
try {
|
||||
JSONObject lastFailedPackageJSON = failedUpdates.getJSONObject(failedUpdates.length() - 1);
|
||||
WritableMap lastFailedPackage = CodePushUtils.convertJsonObjectToWriteable(lastFailedPackageJSON);
|
||||
String lastFailedPackageIdentifier = getPackageStatusReportIdentifier(lastFailedPackage);
|
||||
if (lastFailedPackage != null && isDeploymentStatusNotYetReported(lastFailedPackageIdentifier)) {
|
||||
recordDeploymentStatusReported(lastFailedPackageIdentifier, DEPLOYMENT_FAILED_STATUS);
|
||||
WritableNativeMap reportMap = new WritableNativeMap();
|
||||
reportMap.putMap("package", lastFailedPackage);
|
||||
reportMap.putString("status", DEPLOYMENT_FAILED_STATUS);
|
||||
promise.resolve(reportMap);
|
||||
return;
|
||||
}
|
||||
} catch (JSONException e) {
|
||||
throw new CodePushUnknownException("Unable to read failed updates information stored in SharedPreferences.", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Check if the current CodePush package has been reported
|
||||
try {
|
||||
WritableMap currentPackage = codePushPackage.getCurrentPackage();
|
||||
if (currentPackage != null) {
|
||||
String currentPackageIdentifier = getPackageStatusReportIdentifier(currentPackage);
|
||||
if (currentPackageIdentifier != null && isDeploymentStatusNotYetReported(currentPackageIdentifier)) {
|
||||
recordDeploymentStatusReported(currentPackageIdentifier, DEPLOYMENT_SUCCEEDED_STATUS);
|
||||
WritableNativeMap reportMap = new WritableNativeMap();
|
||||
reportMap.putMap("package", currentPackage);
|
||||
reportMap.putString("status", DEPLOYMENT_SUCCEEDED_STATUS);
|
||||
promise.resolve(reportMap);
|
||||
return;
|
||||
}
|
||||
}
|
||||
} catch (IOException e) {
|
||||
// No current package, resolve no report.
|
||||
promise.resolve("");
|
||||
}
|
||||
|
||||
promise.resolve("");
|
||||
}
|
||||
|
||||
@ReactMethod
|
||||
public void installUpdate(final ReadableMap updatePackage, final int installMode, final Promise promise) {
|
||||
AsyncTask asyncTask = new AsyncTask() {
|
||||
|
||||
Reference in New Issue
Block a user