From 35539d15b453ea97e1138ce5d8eb466facac27fe Mon Sep 17 00:00:00 2001 From: Geoffrey Goh Date: Wed, 27 Jan 2016 00:23:02 -0800 Subject: [PATCH] feedback --- CodePush.h | 11 +++ CodePush.m | 86 ++++------------- CodePush.xcodeproj/project.pbxproj | 4 + CodePushStatusReport.m | 51 ++++++++++ .../microsoft/codepush/react/CodePush.java | 96 +++++-------------- .../codepush/react/CodePushStatusReport.java | 64 +++++++++++++ 6 files changed, 171 insertions(+), 141 deletions(-) create mode 100644 CodePushStatusReport.m create mode 100644 android/app/src/main/java/com/microsoft/codepush/react/CodePushStatusReport.java diff --git a/CodePush.h b/CodePush.h index 428c81b..923a5e8 100644 --- a/CodePush.h +++ b/CodePush.h @@ -88,6 +88,17 @@ failCallback:(void (^)(NSError *err))failCallback; @end +@interface CodePushStatusReport : NSObject + ++ (NSString *)getDeploymentKeyFromStatusReportIdentifier:(NSString *)statusReportIdentifier; ++ (NSString *)getPackageStatusReportIdentifier:(NSDictionary *)package; ++ (NSString *)getPreviousStatusReportIdentifier; ++ (NSString *)getVersionLabelFromStatusReportIdentifier:(NSString *)statusReportIdentifier; ++ (BOOL)isStatusReportIdentifierCodePushLabel:(NSString *)statusReportIdentifier; ++ (void)recordDeploymentStatusReported:(NSString *)appVersionOrPackageIdentifier; + +@end + typedef NS_ENUM(NSInteger, CodePushInstallMode) { CodePushInstallModeImmediate, CodePushInstallModeOnNextRestart, diff --git a/CodePush.m b/CodePush.m index 8302357..5d84b40 100644 --- a/CodePush.m +++ b/CodePush.m @@ -23,7 +23,6 @@ static NSString *const DeploymentSucceeded = @"DeploymentSucceeded"; // These keys represent the names we use to store data in NSUserDefaults static NSString *const FailedUpdatesKey = @"CODE_PUSH_FAILED_UPDATES"; -static NSString *const LastDeploymentReportKey = @"CODE_PUSH_LAST_DEPLOYMENT_REPORT"; static NSString *const PendingUpdateKey = @"CODE_PUSH_PENDING_UPDATE"; // These keys are already "namespaced" by the PendingUpdateKey, so @@ -33,8 +32,6 @@ static NSString *const PendingUpdateIsLoadingKey = @"isLoading"; // These keys are used to inspect/augment the metadata // that is associated with an update's package. -static NSString *const DeploymentKeyKey = @"deploymentKey"; -static NSString *const LabelKey = @"label"; static NSString *const PackageHashKey = @"packageHash"; static NSString *const PackageIsPendingKey = @"isPending"; @@ -161,36 +158,6 @@ static NSString *const PackageIsPendingKey = @"isPending"; [[NSNotificationCenter defaultCenter] removeObserver:self]; } -- (NSString *)getDeploymentKeyFromStatusReportIdentifier:(NSString *)statusReportIdentifier -{ - return [[statusReportIdentifier componentsSeparatedByString:@":"] firstObject]; -} - -- (NSString *)getPackageStatusReportIdentifier:(NSDictionary *)package -{ - // Because deploymentKeys can be dynamically switched, we use a - // combination of the deploymentKey and label as the packageIdentifier. - NSString *deploymentKey = [package objectForKey:DeploymentKeyKey]; - NSString *label = [package objectForKey:LabelKey]; - if (deploymentKey && label) { - return [[deploymentKey stringByAppendingString:@":"] stringByAppendingString:label]; - } else { - return nil; - } -} - -- (NSString *)getPreviousStatusReportIdentifier -{ - NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; - NSString *sentStatusReportIdentifier = [preferences objectForKey:LastDeploymentReportKey]; - return sentStatusReportIdentifier; -} - -- (NSString *)getVersionLabelFromStatusReportIdentifier:(NSString *)statusReportIdentifier -{ - return [[statusReportIdentifier componentsSeparatedByString:@":"] lastObject]; -} - - (instancetype)init { self = [super init]; @@ -277,11 +244,6 @@ static NSString *const PackageIsPendingKey = @"isPending"; return updateIsPending; } -- (BOOL)isStatusReportIdentifierCodePushLabel:(NSString *)statusReportIdentifier -{ - return statusReportIdentifier != nil && [statusReportIdentifier containsString:@":"]; -} - /* * This method updates the React Native bridge's bundle URL * to point at the latest CodePush update, and then restarts @@ -304,13 +266,6 @@ static NSString *const PackageIsPendingKey = @"isPending"; }); } -- (void)recordDeploymentStatusReported:(NSString *)appVersionOrPackageIdentifier -{ - NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; - [preferences setValue:appVersionOrPackageIdentifier forKey:LastDeploymentReportKey]; - [preferences synchronize]; -} - /* * This method is used when an update has failed installation * and the app needs to be rolled back to the previous bundle. @@ -556,16 +511,11 @@ RCT_EXPORT_METHOD(getNewStatusReport:(RCTPromiseResolveBlock)resolve if (failedUpdates) { NSDictionary *lastFailedPackage = [failedUpdates lastObject]; if (lastFailedPackage) { - NSString *lastFailedPackageIdentifier = [self getPackageStatusReportIdentifier:lastFailedPackage]; - NSString *previousStatusReportIdentifier = [self getPreviousStatusReportIdentifier]; - if (lastFailedPackageIdentifier && (previousStatusReportIdentifier == nil || ![previousStatusReportIdentifier isEqualToString:lastFailedPackageIdentifier])) { - [self recordDeploymentStatusReported:lastFailedPackageIdentifier]; - resolve(@{ - @"package": lastFailedPackage, - @"status": DeploymentFailed - }); - return; - } + resolve(@{ + @"package": lastFailedPackage, + @"status": DeploymentFailed + }); + return; } } } else if (_isFirstRunAfterUpdate) { @@ -573,21 +523,21 @@ RCT_EXPORT_METHOD(getNewStatusReport:(RCTPromiseResolveBlock)resolve NSError *error; NSDictionary *currentPackage = [CodePushPackage getCurrentPackage:&error]; if (!error && currentPackage) { - NSString *currentPackageIdentifier = [self getPackageStatusReportIdentifier:currentPackage]; - NSString *previousStatusReportIdentifier = [self getPreviousStatusReportIdentifier]; + NSString *currentPackageIdentifier = [CodePushStatusReport getPackageStatusReportIdentifier:currentPackage]; + NSString *previousStatusReportIdentifier = [CodePushStatusReport getPreviousStatusReportIdentifier]; if (currentPackageIdentifier) { if (previousStatusReportIdentifier == nil) { - [self recordDeploymentStatusReported:currentPackageIdentifier]; + [CodePushStatusReport recordDeploymentStatusReported:currentPackageIdentifier]; resolve(@{ @"package": currentPackage, @"status": DeploymentSucceeded }); return; } else if (![previousStatusReportIdentifier isEqualToString:currentPackageIdentifier]) { - [self recordDeploymentStatusReported:currentPackageIdentifier]; - if ([self isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) { - NSString *previousDeploymentKey = [self getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier]; - NSString *previousLabel = [self getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier]; + [CodePushStatusReport recordDeploymentStatusReported:currentPackageIdentifier]; + if ([CodePushStatusReport isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) { + NSString *previousDeploymentKey = [CodePushStatusReport getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier]; + NSString *previousLabel = [CodePushStatusReport getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier]; resolve(@{ @"package": currentPackage, @"status": DeploymentSucceeded, @@ -609,16 +559,16 @@ RCT_EXPORT_METHOD(getNewStatusReport:(RCTPromiseResolveBlock)resolve } else if (isRunningBinaryVersion || [_bridge.bundleURL.scheme hasPrefix:@"http"]) { // Check if the current appVersion has been reported. NSString *appVersion = [[CodePushConfig current] appVersion]; - NSString *previousStatusReportIdentifier = [self getPreviousStatusReportIdentifier]; + NSString *previousStatusReportIdentifier = [CodePushStatusReport getPreviousStatusReportIdentifier]; if (previousStatusReportIdentifier == nil) { - [self recordDeploymentStatusReported:appVersion]; + [CodePushStatusReport recordDeploymentStatusReported:appVersion]; resolve(@{ @"appVersion": appVersion }); return; } else if (![previousStatusReportIdentifier isEqualToString:appVersion]) { - [self recordDeploymentStatusReported:appVersion]; - if ([self isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) { - NSString *previousDeploymentKey = [self getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier]; - NSString *previousLabel = [self getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier]; + [CodePushStatusReport recordDeploymentStatusReported:appVersion]; + if ([CodePushStatusReport isStatusReportIdentifierCodePushLabel:previousStatusReportIdentifier]) { + NSString *previousDeploymentKey = [CodePushStatusReport getDeploymentKeyFromStatusReportIdentifier:previousStatusReportIdentifier]; + NSString *previousLabel = [CodePushStatusReport getVersionLabelFromStatusReportIdentifier:previousStatusReportIdentifier]; resolve(@{ @"appVersion": appVersion, @"previousDeploymentKey": previousDeploymentKey, diff --git a/CodePush.xcodeproj/project.pbxproj b/CodePush.xcodeproj/project.pbxproj index 6961441..72846f0 100644 --- a/CodePush.xcodeproj/project.pbxproj +++ b/CodePush.xcodeproj/project.pbxproj @@ -9,6 +9,7 @@ /* Begin PBXBuildFile section */ 13BE3DEE1AC21097009241FE /* CodePush.m in Sources */ = {isa = PBXBuildFile; fileRef = 13BE3DED1AC21097009241FE /* CodePush.m */; }; 1B23B9141BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m in Sources */ = {isa = PBXBuildFile; fileRef = 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */; }; + 5421FE311C58AD5A00986A55 /* CodePushStatusReport.m in Sources */ = {isa = PBXBuildFile; fileRef = 5421FE301C58AD5A00986A55 /* CodePushStatusReport.m */; }; 54A0026C1C0E2880004C3CEC /* aescrypt.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024C1C0E2880004C3CEC /* aescrypt.c */; }; 54A0026D1C0E2880004C3CEC /* aeskey.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024D1C0E2880004C3CEC /* aeskey.c */; }; 54A0026E1C0E2880004C3CEC /* aestab.c in Sources */ = {isa = PBXBuildFile; fileRef = 54A0024F1C0E2880004C3CEC /* aestab.c */; }; @@ -45,6 +46,7 @@ 13BE3DEC1AC21097009241FE /* CodePush.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = CodePush.h; sourceTree = ""; }; 13BE3DED1AC21097009241FE /* CodePush.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePush.m; sourceTree = ""; }; 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "RCTConvert+CodePushInstallMode.m"; sourceTree = ""; }; + 5421FE301C58AD5A00986A55 /* CodePushStatusReport.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = CodePushStatusReport.m; sourceTree = ""; }; 54A0024A1C0E2880004C3CEC /* aes.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes.h; sourceTree = ""; }; 54A0024B1C0E2880004C3CEC /* aes_via_ace.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = aes_via_ace.h; sourceTree = ""; }; 54A0024C1C0E2880004C3CEC /* aescrypt.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = aescrypt.c; sourceTree = ""; }; @@ -165,6 +167,7 @@ 1B23B9131BF9267B000BB2F0 /* RCTConvert+CodePushInstallMode.m */, 54FFEDDF1BF550630061DD23 /* CodePushDownloadHandler.m */, 810D4E6C1B96935000B397E9 /* CodePushPackage.m */, + 5421FE301C58AD5A00986A55 /* CodePushStatusReport.m */, 81D51F391B6181C2000DA084 /* CodePushConfig.m */, 13BE3DEC1AC21097009241FE /* CodePush.h */, 13BE3DED1AC21097009241FE /* CodePush.m */, @@ -239,6 +242,7 @@ 54FFEDE01BF550630061DD23 /* CodePushDownloadHandler.m in Sources */, 54A002711C0E2880004C3CEC /* hmac.c in Sources */, 54A002721C0E2880004C3CEC /* prng.c in Sources */, + 5421FE311C58AD5A00986A55 /* CodePushStatusReport.m in Sources */, 54A002731C0E2880004C3CEC /* pwd2key.c in Sources */, 54A002751C0E2880004C3CEC /* ioapi.c in Sources */, 54A002771C0E2880004C3CEC /* unzip.c in Sources */, diff --git a/CodePushStatusReport.m b/CodePushStatusReport.m new file mode 100644 index 0000000..fcd8a39 --- /dev/null +++ b/CodePushStatusReport.m @@ -0,0 +1,51 @@ +#import "CodePush.h" + +static NSString *const LastDeploymentReportKey = @"CODE_PUSH_LAST_DEPLOYMENT_REPORT"; +static NSString *const DeploymentKeyKey = @"deploymentKey"; +static NSString *const LabelKey = @"label"; + +@implementation CodePushStatusReport + ++ (NSString *)getDeploymentKeyFromStatusReportIdentifier:(NSString *)statusReportIdentifier +{ + return [[statusReportIdentifier componentsSeparatedByString:@":"] firstObject]; +} + ++ (NSString *)getPackageStatusReportIdentifier:(NSDictionary *)package +{ + // Because deploymentKeys can be dynamically switched, we use a + // combination of the deploymentKey and label as the packageIdentifier. + NSString *deploymentKey = [package objectForKey:DeploymentKeyKey]; + NSString *label = [package objectForKey:LabelKey]; + if (deploymentKey && label) { + return [[deploymentKey stringByAppendingString:@":"] stringByAppendingString:label]; + } else { + return nil; + } +} + ++ (NSString *)getPreviousStatusReportIdentifier +{ + NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; + NSString *sentStatusReportIdentifier = [preferences objectForKey:LastDeploymentReportKey]; + return sentStatusReportIdentifier; +} + ++ (NSString *)getVersionLabelFromStatusReportIdentifier:(NSString *)statusReportIdentifier +{ + return [[statusReportIdentifier componentsSeparatedByString:@":"] lastObject]; +} + ++ (BOOL)isStatusReportIdentifierCodePushLabel:(NSString *)statusReportIdentifier +{ + return statusReportIdentifier != nil && [statusReportIdentifier containsString:@":"]; +} + ++ (void)recordDeploymentStatusReported:(NSString *)appVersionOrPackageIdentifier +{ + NSUserDefaults *preferences = [NSUserDefaults standardUserDefaults]; + [preferences setValue:appVersionOrPackageIdentifier forKey:LastDeploymentReportKey]; + [preferences synchronize]; +} + +@end \ No newline at end of file diff --git a/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java index 7405adb..b2e9801 100644 --- a/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePush.java @@ -52,23 +52,22 @@ public class CodePush { 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 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 PENDING_UPDATE_KEY = "CODE_PUSH_PENDING_UPDATE"; private final String RESOURCES_BUNDLE = "resources.arsc"; - private final String LAST_DEPLOYMENT_REPORT_KEY = "CODE_PUSH_LAST_DEPLOYMENT_REPORT"; // 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"; + // Helper classes. private CodePushPackage codePushPackage; private CodePushReactPackage codePushReactPackage; + private CodePushStatusReport codePushStatusReport; private CodePushNativeModule codePushNativeModule; // Config properties. @@ -87,12 +86,12 @@ public class CodePush { public CodePush(String deploymentKey, Activity mainActivity, boolean isDebugMode) { SoLoader.init(mainActivity, false); - this.deploymentKey = deploymentKey; - this.codePushPackage = new CodePushPackage(mainActivity.getFilesDir().getAbsolutePath()); - this.mainActivity = mainActivity; this.applicationContext = mainActivity.getApplicationContext(); + this.codePushPackage = new CodePushPackage(mainActivity.getFilesDir().getAbsolutePath()); + this.codePushStatusReport = new CodePushStatusReport(this.applicationContext, CODE_PUSH_PREFERENCES); this.deploymentKey = deploymentKey; this.isDebugMode = isDebugMode; + this.mainActivity = mainActivity; PackageInfo pInfo = null; try { @@ -178,15 +177,6 @@ public class CodePush { } } - private String getDeploymentKeyFromStatusReportIdentifier(String statusReportIdentifier) { - String[] parsedIdentifier = statusReportIdentifier.split(":"); - if (parsedIdentifier.length > 0) { - return parsedIdentifier[0]; - } else { - return null; - } - } - private JSONArray getFailedUpdates() { SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0); String failedUpdatesString = settings.getString(FAILED_UPDATES_KEY, null); @@ -205,18 +195,6 @@ 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 JSONObject getPendingUpdate() { SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0); String pendingUpdateString = settings.getString(PENDING_UPDATE_KEY, null); @@ -235,20 +213,6 @@ public class CodePush { } } - private String getPreviousStatusReportIdentifier() { - SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0); - return settings.getString(LAST_DEPLOYMENT_REPORT_KEY, null); - } - - private String getVersionLabelFromStatusReportIdentifier(String statusReportIdentifier) { - String[] parsedIdentifier = statusReportIdentifier.split(":"); - if (parsedIdentifier.length > 1) { - return parsedIdentifier[1]; - } else { - return null; - } - } - public ReactPackage getReactPackage() { if (codePushReactPackage == null) { codePushReactPackage = new CodePushReactPackage(); @@ -319,15 +283,6 @@ public class CodePush { } } - private boolean isStatusReportIdentifierCodePushLabel(String statusReportIdentifier) { - return statusReportIdentifier != null && statusReportIdentifier.contains(":"); - } - - private void recordDeploymentStatusReported(String appVersionOrPackageIdentifier) { - SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0); - settings.edit().putString(LAST_DEPLOYMENT_REPORT_KEY, appVersionOrPackageIdentifier).commit(); - } - private void removeFailedUpdates() { SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0); settings.edit().remove(FAILED_UPDATES_KEY).commit(); @@ -481,16 +436,11 @@ public class CodePush { try { JSONObject lastFailedPackageJSON = failedUpdates.getJSONObject(failedUpdates.length() - 1); WritableMap lastFailedPackage = CodePushUtils.convertJsonObjectToWriteable(lastFailedPackageJSON); - String lastFailedPackageIdentifier = getPackageStatusReportIdentifier(lastFailedPackage); - String previousStatusReportIdentifier = getPreviousStatusReportIdentifier(); - if (lastFailedPackage != null && (previousStatusReportIdentifier == null || !previousStatusReportIdentifier.equals(lastFailedPackageIdentifier))) { - recordDeploymentStatusReported(lastFailedPackageIdentifier); - WritableNativeMap reportMap = new WritableNativeMap(); - reportMap.putMap("package", lastFailedPackage); - reportMap.putString("status", DEPLOYMENT_FAILED_STATUS); - promise.resolve(reportMap); - return; - } + 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); } @@ -499,21 +449,21 @@ public class CodePush { // Check if the current CodePush package has been reported WritableMap currentPackage = codePushPackage.getCurrentPackage(); if (currentPackage != null) { - String currentPackageIdentifier = getPackageStatusReportIdentifier(currentPackage); - String previousStatusReportIdentifier = getPreviousStatusReportIdentifier(); + String currentPackageIdentifier = codePushStatusReport.getPackageStatusReportIdentifier(currentPackage); + String previousStatusReportIdentifier = codePushStatusReport.getPreviousStatusReportIdentifier(); if (currentPackageIdentifier != null) { if (previousStatusReportIdentifier == null) { - recordDeploymentStatusReported(currentPackageIdentifier); + codePushStatusReport.recordDeploymentStatusReported(currentPackageIdentifier); WritableNativeMap reportMap = new WritableNativeMap(); reportMap.putMap("package", currentPackage); reportMap.putString("status", DEPLOYMENT_SUCCEEDED_STATUS); promise.resolve(reportMap); return; } else if (!previousStatusReportIdentifier.equals(currentPackageIdentifier)) { - recordDeploymentStatusReported(currentPackageIdentifier); - if (isStatusReportIdentifierCodePushLabel(previousStatusReportIdentifier)) { - String previousDeploymentKey = getDeploymentKeyFromStatusReportIdentifier(previousStatusReportIdentifier); - String previousLabel = getVersionLabelFromStatusReportIdentifier(previousStatusReportIdentifier); + codePushStatusReport.recordDeploymentStatusReported(currentPackageIdentifier); + if (codePushStatusReport.isStatusReportIdentifierCodePushLabel(previousStatusReportIdentifier)) { + String previousDeploymentKey = codePushStatusReport.getDeploymentKeyFromStatusReportIdentifier(previousStatusReportIdentifier); + String previousLabel = codePushStatusReport.getVersionLabelFromStatusReportIdentifier(previousStatusReportIdentifier); WritableNativeMap reportMap = new WritableNativeMap(); reportMap.putMap("package", currentPackage); reportMap.putString("status", DEPLOYMENT_SUCCEEDED_STATUS); @@ -534,18 +484,18 @@ public class CodePush { } } else if (isRunningBinaryVersion) { // Check if the current appVersion has been reported. - String previousStatusReportIdentifier = getPreviousStatusReportIdentifier(); + String previousStatusReportIdentifier = codePushStatusReport.getPreviousStatusReportIdentifier(); if (previousStatusReportIdentifier == null) { - recordDeploymentStatusReported(appVersion); + codePushStatusReport.recordDeploymentStatusReported(appVersion); WritableNativeMap reportMap = new WritableNativeMap(); reportMap.putString("appVersion", appVersion); promise.resolve(reportMap); return; } else if (!previousStatusReportIdentifier.equals(appVersion)) { - recordDeploymentStatusReported(appVersion); - if (isStatusReportIdentifierCodePushLabel(previousStatusReportIdentifier)) { - String previousDeploymentKey = getDeploymentKeyFromStatusReportIdentifier(previousStatusReportIdentifier); - String previousLabel = getVersionLabelFromStatusReportIdentifier(previousStatusReportIdentifier); + codePushStatusReport.recordDeploymentStatusReported(appVersion); + if (codePushStatusReport.isStatusReportIdentifierCodePushLabel(previousStatusReportIdentifier)) { + String previousDeploymentKey = codePushStatusReport.getDeploymentKeyFromStatusReportIdentifier(previousStatusReportIdentifier); + String previousLabel = codePushStatusReport.getVersionLabelFromStatusReportIdentifier(previousStatusReportIdentifier); WritableNativeMap reportMap = new WritableNativeMap(); reportMap.putString("appVersion", appVersion); reportMap.putString("previousDeploymentKey", previousDeploymentKey); diff --git a/android/app/src/main/java/com/microsoft/codepush/react/CodePushStatusReport.java b/android/app/src/main/java/com/microsoft/codepush/react/CodePushStatusReport.java new file mode 100644 index 0000000..3dd9d0f --- /dev/null +++ b/android/app/src/main/java/com/microsoft/codepush/react/CodePushStatusReport.java @@ -0,0 +1,64 @@ +package com.microsoft.codepush.react; + +import android.content.Context; +import android.content.SharedPreferences; + +import com.facebook.react.bridge.WritableMap; + +public class CodePushStatusReport { + + private Context applicationContext; + private final String CODE_PUSH_PREFERENCES; + private final String DEPLOYMENT_KEY_KEY = "deploymentKey"; + private final String LABEL_KEY = "label"; + private final String LAST_DEPLOYMENT_REPORT_KEY = "CODE_PUSH_LAST_DEPLOYMENT_REPORT"; + + public CodePushStatusReport(Context applicationContext, String codePushPreferencesKey) { + this.applicationContext = applicationContext; + this.CODE_PUSH_PREFERENCES = codePushPreferencesKey; + } + + public String getDeploymentKeyFromStatusReportIdentifier(String statusReportIdentifier) { + String[] parsedIdentifier = statusReportIdentifier.split(":"); + if (parsedIdentifier.length > 0) { + return parsedIdentifier[0]; + } else { + return null; + } + } + + public 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; + } + } + + public String getPreviousStatusReportIdentifier() { + SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0); + return settings.getString(LAST_DEPLOYMENT_REPORT_KEY, null); + } + + public String getVersionLabelFromStatusReportIdentifier(String statusReportIdentifier) { + String[] parsedIdentifier = statusReportIdentifier.split(":"); + if (parsedIdentifier.length > 1) { + return parsedIdentifier[1]; + } else { + return null; + } + } + + public boolean isStatusReportIdentifierCodePushLabel(String statusReportIdentifier) { + return statusReportIdentifier != null && statusReportIdentifier.contains(":"); + } + + public void recordDeploymentStatusReported(String appVersionOrPackageIdentifier) { + SharedPreferences settings = applicationContext.getSharedPreferences(CODE_PUSH_PREFERENCES, 0); + settings.edit().putString(LAST_DEPLOYMENT_REPORT_KEY, appVersionOrPackageIdentifier).commit(); + } +}