-
-
Notifications
You must be signed in to change notification settings - Fork 735
Push Translation #29
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Push Translation #29
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,10 +11,12 @@ | |
import android.content.Context; | ||
import android.content.pm.PackageInfo; | ||
import android.content.pm.PackageManager; | ||
import android.text.TextUtils; | ||
|
||
import java.util.Arrays; | ||
import java.util.Collections; | ||
import java.util.List; | ||
import java.util.Locale; | ||
import java.util.TimeZone; | ||
|
||
import bolts.Continuation; | ||
|
@@ -36,12 +38,13 @@ public class ParseInstallation extends ParseObject { | |
private static final String KEY_DEVICE_TOKEN = "deviceToken"; | ||
private static final String KEY_PUSH_TYPE = "pushType"; | ||
private static final String KEY_TIME_ZONE = "timeZone"; | ||
private static final String KEY_LOCALE = "localeIdentifier"; | ||
private static final String KEY_APP_VERSION = "appVersion"; | ||
/* package */ static final String KEY_CHANNELS = "channels"; | ||
|
||
private static final List<String> READ_ONLY_FIELDS = Collections.unmodifiableList( | ||
Arrays.asList(KEY_DEVICE_TYPE, KEY_INSTALLATION_ID, KEY_DEVICE_TOKEN, KEY_PUSH_TYPE, | ||
KEY_TIME_ZONE, KEY_APP_VERSION, KEY_APP_NAME, KEY_PARSE_VERSION, | ||
KEY_TIME_ZONE, KEY_LOCALE, KEY_APP_VERSION, KEY_APP_NAME, KEY_PARSE_VERSION, | ||
KEY_APP_IDENTIFIER)); | ||
|
||
// TODO(mengyan): Inject into ParseInstallationInstanceController | ||
|
@@ -108,6 +111,7 @@ public String getInstallationId() { | |
updateTimezone(); | ||
updateVersionInfo(); | ||
updateDeviceInfo(); | ||
updateLocaleIdentifier(); | ||
} | ||
} | ||
|
||
|
@@ -165,8 +169,8 @@ public Task<Void> then(Task<Void> task) throws Exception { | |
// time zones from devices reporting other formats. | ||
private void updateTimezone() { | ||
String zone = TimeZone.getDefault().getID(); | ||
if ((zone.indexOf('/') > 0 || zone.equals("GMT")) && !zone.equals(get("timeZone"))) { | ||
performPut("timeZone", zone); | ||
if ((zone.indexOf('/') > 0 || zone.equals("GMT")) && !zone.equals(get(KEY_TIME_ZONE))) { | ||
performPut(KEY_TIME_ZONE, zone); | ||
} | ||
} | ||
|
||
|
@@ -180,25 +184,65 @@ private void updateVersionInfo() { | |
String appVersion = pkgInfo.versionName; | ||
String appName = pm.getApplicationLabel(pm.getApplicationInfo(packageName, 0)).toString(); | ||
|
||
if (packageName != null && !packageName.equals(get("appIdentifier"))) { | ||
if (packageName != null && !packageName.equals(get(KEY_APP_IDENTIFIER))) { | ||
performPut(KEY_APP_IDENTIFIER, packageName); | ||
} | ||
if (appName != null && !appName.equals(get("appName"))) { | ||
if (appName != null && !appName.equals(get(KEY_APP_NAME))) { | ||
performPut(KEY_APP_NAME, appName); | ||
} | ||
if (appVersion != null && !appVersion.equals(get("appVersion"))) { | ||
if (appVersion != null && !appVersion.equals(get(KEY_APP_VERSION))) { | ||
performPut(KEY_APP_VERSION, appVersion); | ||
} | ||
} catch (PackageManager.NameNotFoundException e) { | ||
PLog.w(TAG, "Cannot load package info; will not be saved to installation"); | ||
} | ||
|
||
if (!VERSION_NAME.equals(get("parseVersion"))) { | ||
if (!VERSION_NAME.equals(get(KEY_PARSE_VERSION))) { | ||
performPut(KEY_PARSE_VERSION, VERSION_NAME); | ||
} | ||
} | ||
} | ||
|
||
/* | ||
* Save locale in the following format: | ||
* [language code]-[country code] | ||
* | ||
* The language codes are two-letter lowercase ISO language codes (such as "en") as defined by | ||
* <a href="http://en.wikipedia.org/wiki/ISO_639-1">ISO 639-1</a>. | ||
* The country codes are two-letter uppercase ISO country codes (such as "US") as defined by | ||
* <a href="http://en.wikipedia.org/wiki/ISO_3166-1_alpha-3">ISO 3166-1</a>. | ||
* | ||
* Note that Java uses several deprecated two-letter codes. The Hebrew ("he") language | ||
* code is rewritten as "iw", Indonesian ("id") as "in", and Yiddish ("yi") as "ji". This | ||
* rewriting happens even if you construct your own {@code Locale} object, not just for | ||
* instances returned by the various lookup methods. | ||
*/ | ||
private void updateLocaleIdentifier() { | ||
final Locale locale = Locale.getDefault(); | ||
|
||
String language = locale.getLanguage(); | ||
String country = locale.getCountry(); | ||
|
||
if (TextUtils.isEmpty(language)) { | ||
return; | ||
} | ||
|
||
// rewrite depreciated two-letter codes | ||
if (language.equals("iw")) language = "he"; // Hebrew | ||
if (language.equals("in")) language = "id"; // Indonesian | ||
if (language.equals("ji")) language = "yi"; // Yiddish | ||
|
||
String localeString = language; | ||
|
||
if (!TextUtils.isEmpty(country)) { | ||
localeString = String.format(Locale.US, "%s-%s", language, country); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's add a unit test for this use case. |
||
|
||
if (!localeString.equals(get(KEY_LOCALE))) { | ||
performPut(KEY_LOCALE, localeString); | ||
} | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's also verify that we update the locale if it's already set. |
||
} | ||
|
||
// TODO(mengyan): Move to ParseInstallationInstanceController | ||
/* package */ void updateDeviceInfo() { | ||
updateDeviceInfo(ParsePlugins.get().installationId()); | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,6 +23,7 @@ | |
import org.robolectric.res.builder.RobolectricPackageManager; | ||
|
||
import java.util.Arrays; | ||
import java.util.Locale; | ||
import java.util.TimeZone; | ||
|
||
import bolts.Task; | ||
|
@@ -46,17 +47,25 @@ public class ParseInstallationTest { | |
private static final String KEY_APP_NAME = "appName"; | ||
private static final String KEY_APP_IDENTIFIER = "appIdentifier"; | ||
private static final String KEY_TIME_ZONE = "timeZone"; | ||
private static final String KEY_LOCALE_IDENTIFIER = "localeIdentifier"; | ||
private static final String KEY_APP_VERSION = "appVersion"; | ||
|
||
private Locale defaultLocale; | ||
|
||
@Before | ||
public void setUp() { | ||
ParseObject.registerSubclass(ParseInstallation.class); | ||
|
||
defaultLocale = Locale.getDefault(); | ||
} | ||
|
||
@After | ||
public void tearDown() { | ||
ParseObject.unregisterSubclass(ParseInstallation.class); | ||
ParseCorePlugins.getInstance().reset(); | ||
ParsePlugins.reset(); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Set default Locale back to whatever it was before |
||
|
||
Locale.setDefault(defaultLocale); | ||
} | ||
|
||
@Test | ||
|
@@ -71,6 +80,7 @@ public void testImmutableKeys() { | |
"deviceTokenLastModified", | ||
"pushType", | ||
"timeZone", | ||
"localeIdentifier", | ||
"appVersion" | ||
}; | ||
|
||
|
@@ -146,24 +156,9 @@ public void testHandleFetchResultAsync() throws Exception { | |
|
||
@Test | ||
public void testUpdateBeforeSave() throws Exception { | ||
// Mock currentInstallationController to make setAsync work | ||
ParseCurrentInstallationController controller = | ||
mock(ParseCurrentInstallationController.class); | ||
when(controller.isCurrent(any(ParseInstallation.class))).thenReturn(true); | ||
ParseCorePlugins.getInstance().registerCurrentInstallationController(controller); | ||
// Mock package manager | ||
RobolectricPackageManager packageManager = | ||
spy(RuntimeEnvironment.getRobolectricPackageManager()); | ||
doReturn("parseTest").when(packageManager).getApplicationLabel(any(ApplicationInfo.class)); | ||
RuntimeEnvironment.setRobolectricPackageManager(packageManager); | ||
ParsePlugins.Android plugins = mock(ParsePlugins.Android.class); | ||
// Mock installationId | ||
InstallationId installationId = mock(InstallationId.class); | ||
when(installationId.get()).thenReturn("installationId"); | ||
when(plugins.installationId()).thenReturn(installationId); | ||
// Mock application context | ||
when(plugins.applicationContext()).thenReturn(RuntimeEnvironment.application); | ||
ParsePlugins.set(plugins); | ||
mocksForUpdateBeforeSave(); | ||
|
||
Locale.setDefault(new Locale("en", "US")); | ||
|
||
ParseInstallation installation = new ParseInstallation(); | ||
installation.updateBeforeSave(); | ||
|
@@ -183,7 +178,9 @@ public void testUpdateBeforeSave() throws Exception { | |
assertEquals(appVersion, installation.getString(KEY_APP_VERSION)); | ||
// Make sure we update device info | ||
assertEquals("android", installation.getString(KEY_DEVICE_TYPE)); | ||
assertEquals(installationId.get(), installation.getString(KEY_INSTALLATION_ID)); | ||
assertEquals("installationId", installation.getString(KEY_INSTALLATION_ID)); | ||
// Make sure we update the locale identifier | ||
assertEquals("en-US", installation.getString(KEY_LOCALE_IDENTIFIER)); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Let's specify a locale with There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I did this in There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. ah missed that! yeah let's do that so it's a bit more contextual. |
||
} | ||
|
||
// TODO(mengyan): Add other testUpdateBeforeSave cases to cover all branches | ||
|
@@ -255,6 +252,54 @@ public void testGetCurrentInstallation() throws Exception { | |
verify(controller, times(1)).getAsync(); | ||
} | ||
|
||
@Test | ||
public void testLocaleIdentifierSpecialCases() throws Exception { | ||
mocksForUpdateBeforeSave(); | ||
|
||
ParseInstallation installation = new ParseInstallation(); | ||
|
||
// Deprecated two-letter codes (Java issue). | ||
Locale.setDefault(new Locale("iw", "US")); | ||
installation.updateBeforeSave(); | ||
assertEquals("he-US", installation.getString(KEY_LOCALE_IDENTIFIER)); | ||
|
||
Locale.setDefault(new Locale("in", "US")); | ||
installation.updateBeforeSave(); | ||
assertEquals("id-US", installation.getString(KEY_LOCALE_IDENTIFIER)); | ||
|
||
Locale.setDefault(new Locale("ji", "US")); | ||
installation.updateBeforeSave(); | ||
assertEquals("yi-US", installation.getString(KEY_LOCALE_IDENTIFIER)); | ||
|
||
// No country code. | ||
Locale.setDefault(new Locale("en")); | ||
installation.updateBeforeSave(); | ||
assertEquals("en", installation.getString(KEY_LOCALE_IDENTIFIER)); | ||
} | ||
|
||
|
||
|
||
// TODO(mengyan): Add testFetchAsync, right now we can not test super methods inside | ||
// testFetchAsync | ||
|
||
private static void mocksForUpdateBeforeSave() { | ||
// Mock currentInstallationController to make setAsync work | ||
ParseCurrentInstallationController controller = | ||
mock(ParseCurrentInstallationController.class); | ||
when(controller.isCurrent(any(ParseInstallation.class))).thenReturn(true); | ||
ParseCorePlugins.getInstance().registerCurrentInstallationController(controller); | ||
// Mock package manager | ||
RobolectricPackageManager packageManager = | ||
spy(RuntimeEnvironment.getRobolectricPackageManager()); | ||
doReturn("parseTest").when(packageManager).getApplicationLabel(any(ApplicationInfo.class)); | ||
RuntimeEnvironment.setRobolectricPackageManager(packageManager); | ||
ParsePlugins.Android plugins = mock(ParsePlugins.Android.class); | ||
// Mock installationId | ||
InstallationId installationId = mock(InstallationId.class); | ||
when(installationId.get()).thenReturn("installationId"); | ||
when(plugins.installationId()).thenReturn(installationId); | ||
// Mock application context | ||
when(plugins.applicationContext()).thenReturn(RuntimeEnvironment.application); | ||
ParsePlugins.set(plugins); | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's add a unit test to verify that we're correctly persisting these 3 locales.