Skip to content
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

Feature App-defined Language implementation backported to 3.X.X version #1350

Merged
merged 29 commits into from
Jun 3, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0e32608
Added classes and interfaces for Language feat
tanaynigam May 13, 2021
5121c9e
Updated LanguageContext class
tanaynigam May 17, 2021
46443ec
Added network call to setLanguage method of OneSignal class
tanaynigam May 17, 2021
03fd006
Added Unit test scripts for setLanguage method
tanaynigam May 17, 2021
74504bf
Moved getCorrectedLanguage from OSUtils to LanguageProviderDevice
tanaynigam May 18, 2021
2750d61
Replace StateSynchronizer in OneSignal.setLanguage
tanaynigam May 27, 2021
6944777
Add OneSignal.setLanguage addTaskToQueue logic
tanaynigam May 27, 2021
96be3b3
Moved access of Language classes for OneSignalPrefs
tanaynigam May 18, 2021
22c0a43
Fix getLanguage OSInAppMessageController and NotificationChannelManager
tanaynigam May 18, 2021
2d3b7de
Add Singleton LanguageContext and Dependency Injection to constructor
tanaynigam May 18, 2021
868d9fa
Add LanguageContext Dependency to OSInAppMessageController
tanaynigam May 18, 2021
68d9095
Update NotificationChannelManager with LanguageContext instance
tanaynigam May 18, 2021
66fdc4f
Convert OneSignal preferences and languageContext to private
tanaynigam May 18, 2021
de9f029
Fix format Language classes
tanaynigam May 21, 2021
299830d
Remove null check and JSONException operation at OneSignal.setLanguage
tanaynigam May 21, 2021
97dec5b
Test Fix NotificationChannelManagerRunner.processChannelListWithMulti…
tanaynigam May 21, 2021
2d4d1a9
Add NonNull annotation to getLanguage implementations
tanaynigam May 25, 2021
96e2409
Move strings to constants
tanaynigam May 25, 2021
98fbefd
Move preferences.getString to variable for clarity
tanaynigam May 25, 2021
f5b635a
Fix OneSignal.setLanguage PrivacyConsentErrorMessage and OendingTaskR…
tanaynigam May 27, 2021
ec91758
Delete .DS_Store file
tanaynigam Jun 1, 2021
242ee10
Replace androidx imports to android.support
tanaynigam May 27, 2021
2344a51
Move OneSignal.setLanguage executable order
tanaynigam May 27, 2021
e9b5717
Fix htmlPathForMessage to non-static
tanaynigam May 27, 2021
6ed42c5
Fix Unit test issues
tanaynigam May 27, 2021
9480c91
Add languageContext initialization to OneSingal.setAppContext
tanaynigam May 28, 2021
45cb4ed
Add Simulated delay to FCM/GCM to fix Unit tests
tanaynigam May 28, 2021
94e3afa
Remove unnecessary languageContext initialization
tanaynigam Jun 1, 2021
678ff8b
Replace startInit to setAppContext
tanaynigam Jun 3, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
import android.support.annotation.RequiresApi;
import android.support.v4.app.NotificationManagerCompat;

import com.onesignal.language.LanguageContext;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
Expand Down Expand Up @@ -113,9 +115,9 @@ private static String createChannel(Context context, NotificationManager notific
JSONObject payloadWithText = channelPayload;
if (channelPayload.has("langs")) {
JSONObject langList = channelPayload.getJSONObject("langs");
String deviceLanguage = OSUtils.getCorrectedLanguage();
if (langList.has(deviceLanguage))
payloadWithText = langList.optJSONObject(deviceLanguage);
String language = LanguageContext.getInstance().getLanguage();
if (langList.has(language))
payloadWithText = langList.optJSONObject(language);
}

String channel_name = payloadWithText.optString("nm", "Miscellaneous");
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@

import com.onesignal.OSDynamicTriggerController.OSDynamicTriggerControllerObserver;
import com.onesignal.OneSignalRestClient.ResponseHandler;
import com.onesignal.language.LanguageContext;

import org.json.JSONArray;
import org.json.JSONException;
Expand All @@ -34,6 +35,7 @@ class OSInAppMessageController implements OSDynamicTriggerControllerObserver, OS
public static final String IN_APP_MESSAGES_JSON_KEY = "in_app_messages";
private static final String OS_SAVE_IN_APP_MESSAGE = "OS_SAVE_IN_APP_MESSAGE";
private static final Object LOCK = new Object();
private final LanguageContext languageContext;

OSTriggerController triggerController;
private OSSystemConditionController systemConditionController;
Expand Down Expand Up @@ -70,14 +72,15 @@ class OSInAppMessageController implements OSDynamicTriggerControllerObserver, OS
Date lastTimeInAppDismissed = null;
private int htmlNetworkRequestAttemptCount = 0;

protected OSInAppMessageController(OneSignalDbHelper dbHelper) {
protected OSInAppMessageController(OneSignalDbHelper dbHelper, LanguageContext languageContext) {
messages = new ArrayList<>();
dismissedMessages = OSUtils.newConcurrentSet();
messageDisplayQueue = new ArrayList<>();
impressionedMessages = OSUtils.newConcurrentSet();
clickedClickIds = OSUtils.newConcurrentSet();
triggerController = new OSTriggerController(this);
systemConditionController = new OSSystemConditionController(this);
this.languageContext = languageContext;

Set<String> tempDismissedSet = OneSignalPrefs.getStringSet(
OneSignalPrefs.PREFS_ONESIGNAL,
Expand Down Expand Up @@ -209,16 +212,16 @@ private void evaluateInAppMessages() {
}
}

private static @Nullable String variantIdForMessage(@NonNull OSInAppMessage message) {
String languageIdentifier = OSUtils.getCorrectedLanguage();
private @Nullable String variantIdForMessage(@NonNull OSInAppMessage message) {
String language = languageContext.getLanguage();

for (String variant : PREFERRED_VARIANT_ORDER) {
if (!message.variants.containsKey(variant))
continue;

HashMap<String, String> variantMap = message.variants.get(variant);
if (variantMap.containsKey(languageIdentifier))
return variantMap.get(languageIdentifier);
if (variantMap.containsKey(language))
return variantMap.get(language);
return variantMap.get("default");
}

Expand Down Expand Up @@ -655,7 +658,7 @@ public void run() {
OneSignal.onesignalLog(OneSignal.LOG_LEVEL.DEBUG, "persistInAppMessageForRedisplay: " + message.toString() + " with msg array data: " + redisplayedInAppMessages.toString());
}

private static @Nullable
private @Nullable
String htmlPathForMessage(OSInAppMessage message) {
String variantId = variantIdForMessage(message);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,21 +29,23 @@

import android.os.Build;

import com.onesignal.language.LanguageContext;

class OSInAppMessageControllerFactory {

private static final Object LOCK = new Object();

private OSInAppMessageController controller;

public OSInAppMessageController getController(OneSignalDbHelper dbHelper) {
public OSInAppMessageController getController(OneSignalDbHelper dbHelper, LanguageContext languageContext) {
if (controller == null) {
synchronized (LOCK) {
if (controller == null) {
// Make sure only Android 4.4 devices and higher can use IAMs
if (Build.VERSION.SDK_INT <= Build.VERSION_CODES.JELLY_BEAN_MR2)
controller = new OSInAppMessageDummyController(null);
controller = new OSInAppMessageDummyController(null, languageContext);
else
controller = new OSInAppMessageController(dbHelper);
controller = new OSInAppMessageController(dbHelper, languageContext);
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,8 @@
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;

import com.onesignal.language.LanguageContext;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
Expand All @@ -17,8 +19,8 @@ class OSInAppMessageDummyController extends OSInAppMessageController {
* This is a dummy controller that will be used for Android 4.3 and older devices
* All methods should be overridden and as empty as possible (few return exceptions)
*/
OSInAppMessageDummyController(OneSignalDbHelper dbHelper) {
super(dbHelper);
OSInAppMessageDummyController(OneSignalDbHelper dbHelper, LanguageContext languageContext) {
super(dbHelper, languageContext);
}

@Override
Expand Down
19 changes: 0 additions & 19 deletions OneSignalSDK/onesignal/src/main/java/com/onesignal/OSUtils.java
Original file line number Diff line number Diff line change
Expand Up @@ -60,7 +60,6 @@
import java.util.Collections;
import java.util.HashSet;
import java.util.Iterator;
import java.util.Locale;
import java.util.Set;
import java.util.UUID;
import java.util.concurrent.ConcurrentHashMap;
Expand Down Expand Up @@ -437,24 +436,6 @@ static String getResourceString(Context context, String key, String defaultStr)
return defaultStr;
}

static String getCorrectedLanguage() {
String lang = Locale.getDefault().getLanguage();

// https://github.com/OneSignal/OneSignal-Android-SDK/issues/64
if (lang.equals("iw"))
return "he";
if (lang.equals("in"))
return "id";
if (lang.equals("ji"))
return "yi";

// https://github.com/OneSignal/OneSignal-Android-SDK/issues/98
if (lang.equals("zh"))
return lang + "-" + Locale.getDefault().getCountry();

return lang;
}

static boolean isValidEmail(String email) {
if (email == null)
return false;
Expand Down
42 changes: 40 additions & 2 deletions OneSignalSDK/onesignal/src/main/java/com/onesignal/OneSignal.java
Original file line number Diff line number Diff line change
Expand Up @@ -49,6 +49,9 @@
import com.onesignal.influence.OSTrackerFactory;
import com.onesignal.influence.model.OSInfluence;
import com.onesignal.outcomes.OSOutcomeEventsFactory;
import com.onesignal.language.LanguageContext;
import com.onesignal.language.LanguageProviderAppDefined;
import com.onesignal.language.LanguageProviderDevice;

import org.json.JSONArray;
import org.json.JSONException;
Expand Down Expand Up @@ -416,6 +419,8 @@ static Activity getCurrentActivity() {
private static String userId = null, emailId = null;
private static int subscribableStatus;

private static LanguageContext languageContext = null;

// Is the init() of OneSignal SDK finished yet
private static boolean initDone;
static boolean isInitDone() {
Expand Down Expand Up @@ -460,7 +465,7 @@ public void onSessionEnding(@NonNull List<OSInfluence> lastInfluences) {

private static OSInAppMessageControllerFactory inAppMessageControllerFactory = new OSInAppMessageControllerFactory();
static OSInAppMessageController getInAppMessageController() {
return inAppMessageControllerFactory.getController(getDBHelperInstance());
return inAppMessageControllerFactory.getController(getDBHelperInstance(), languageContext);
}
private static OSLogger logger = new OSLogWrapper();
private static OneSignalAPIClient apiClient = new OneSignalRestClientWrapper();
Expand Down Expand Up @@ -647,6 +652,9 @@ public static void setAppContext(@NonNull Context context) {
ActivityLifecycleListener.registerActivityLifecycleCallbacks((Application)appContext);

if (wasAppContextNull) {
// Initialize languageContext
languageContext = new LanguageContext(preferences);

if (outcomeEventsFactory == null)
outcomeEventsFactory = new OSOutcomeEventsFactory(logger, apiClient, getDBHelperInstance(), preferences);

Expand Down Expand Up @@ -1394,7 +1402,7 @@ private static void registerUserTask() throws JSONException {
}
deviceInfo.put("device_os", Build.VERSION.RELEASE);
deviceInfo.put("timezone", getTimeZoneOffset());
deviceInfo.put("language", OSUtils.getCorrectedLanguage());
deviceInfo.put("language", languageContext.getLanguage());
deviceInfo.put("sdk", VERSION);
deviceInfo.put("sdk_type", sdkType);
deviceInfo.put("android_package", packageName);
Expand Down Expand Up @@ -1569,6 +1577,36 @@ public void run() {
emailLogout.run();
}

public static void setLanguage(@NonNull final String language) {
Runnable runSetLanguage = new Runnable() {
@Override
public void run() {
LanguageProviderAppDefined languageProviderAppDefined = new LanguageProviderAppDefined(preferences);
languageProviderAppDefined.setLanguage(language);
languageContext.setStrategy(languageProviderAppDefined);

try {
JSONObject deviceInfo = new JSONObject();
deviceInfo.put("language", languageContext.getLanguage());
OneSignalStateSynchronizer.updateDeviceInfo(deviceInfo);
} catch (JSONException exception) {
exception.printStackTrace();
}
}
};

// If either the app context is null or the waiting queue isn't done (to preserve operation order)
if (appContext == null || shouldRunTaskThroughQueue()) {
addTaskToQueue(new PendingTaskRunnable(runSetLanguage));
return;
}

if (shouldLogUserPrivacyConsentErrorMessageForMethodName("setLanguage()"))
return;

runSetLanguage.run();
}

public static void setExternalUserId(@NonNull final String externalId) {
setExternalUserId(externalId, null, null);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,41 @@
package com.onesignal.language;

import android.support.annotation.NonNull;
import android.util.Log;

import com.onesignal.OSSharedPreferences;

import static com.onesignal.language.LanguageProviderAppDefined.PREFS_OS_LANGUAGE;

/*
The Interface implements a getter and setter for the Language Provider.
It defaults to the device defined Language unless a language override is set.
*/
public class LanguageContext {
private LanguageProvider strategy;
private static LanguageContext instance = null;

public static LanguageContext getInstance() {
return instance;
}

public LanguageContext(OSSharedPreferences preferences) {
instance = this;
String languageAppDefined = preferences.getString(preferences.getPreferencesName(), PREFS_OS_LANGUAGE, null);
if (languageAppDefined != null) {
this.strategy = new LanguageProviderAppDefined(preferences);
}
else {
this.strategy = new LanguageProviderDevice();
}
}

public void setStrategy(LanguageProvider strategy) {
this.strategy = strategy;
}

@NonNull
public String getLanguage() {
return strategy.getLanguage();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
package com.onesignal.language;

import android.support.annotation.NonNull;

public interface LanguageProvider {
@NonNull
String getLanguage();
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
package com.onesignal.language;
import android.support.annotation.NonNull;

import com.onesignal.OSSharedPreferences;

public class LanguageProviderAppDefined implements LanguageProvider {
public static final String PREFS_OS_LANGUAGE = "PREFS_OS_LANGUAGE";

private static final String DEFAULT_LANGUAGE = "en";
private final OSSharedPreferences preferences;

public LanguageProviderAppDefined(OSSharedPreferences preferences) {
this.preferences = preferences;
}

public void setLanguage(String language) {
preferences.saveString(
preferences.getPreferencesName(),
PREFS_OS_LANGUAGE,
language);
}

@NonNull
public String getLanguage() {
return preferences.getString(
preferences.getPreferencesName(), PREFS_OS_LANGUAGE, DEFAULT_LANGUAGE);
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
package com.onesignal.language;

import android.support.annotation.NonNull;

import java.util.Locale;

public class LanguageProviderDevice implements LanguageProvider {
private static final String HEBREW_INCORRECT = "iw";
private static final String HEBREW_CORRECTED = "he";
private static final String INDONESIAN_INCORRECT = "in";
private static final String INDONESIAN_CORRECTED = "id";
private static final String YIDDISH_INCORRECT = "ji";
private static final String YIDDISH_CORRECTED = "yi";
private static final String CHINESE = "zh";

@NonNull
public String getLanguage() {
String language = Locale.getDefault().getLanguage();

switch (language) {
// https://github.com/OneSignal/OneSignal-Android-SDK/issues/64
case HEBREW_INCORRECT:
return HEBREW_CORRECTED;
case INDONESIAN_INCORRECT:
return INDONESIAN_CORRECTED;
case YIDDISH_INCORRECT:
return YIDDISH_CORRECTED;
// https://github.com/OneSignal/OneSignal-Android-SDK/issues/98
case CHINESE:
return language + "-" + Locale.getDefault().getCountry();
default:
return language;
}
}
}
Loading