diff --git a/CHANGELOG.md b/CHANGELOG.md index 065e8727..7b8f661d 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,22 @@ Change Log ========== +Version 2.7.2 *(December 5, 2023)* +------------------------------------------- +#### New Features + +**Android specific** +* Supports [CleverTap Android SDK v5.2.1](https://github.com/CleverTap/clevertap-android-sdk/releases/tag/corev5.2.1_xpsv1.5.4). This supported version includes support for Custom Proxy Domain functionality. Check usage for cordova android [here](docs/Integrate-Android.md#integrate-custom-proxy-domain). + +**iOS specific** +* Supports [CleverTap iOS SDK v5.2.2](https://github.com/CleverTap/clevertap-ios-sdk/releases/tag/5.2.2). This supported version includes support for Custom Proxy Domain functionality. Check usage for cordova ios [here](docs/Integrate-iOS.md#integrate-custom-proxy-domain). + +#### Bug Fixes +* Fixes a crash in iOS 17/Xcode 15 related to alert inapps. + +**Common for both android and iOS** +* Adds new public API `setLocale(String locale)` for in-built support to send the custom locale(i.e.language and country) data to the dashboard. +* Adds support for Integration Debugger to view errors and events on the dashboard when the debugLevel is set to 3. + Version 2.7.1 *(August 17, 2023)* ------------------------------------------- #### New Features diff --git a/Samples/Cordova/ExampleProject/config.xml b/Samples/Cordova/ExampleProject/config.xml index 7bb57f14..d2275d30 100644 --- a/Samples/Cordova/ExampleProject/config.xml +++ b/Samples/Cordova/ExampleProject/config.xml @@ -24,8 +24,8 @@ - - + + diff --git a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/js/index.js b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/js/index.js index c481d9db..962e48c7 100644 --- a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/js/index.js +++ b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/js/index.js @@ -16,9 +16,73 @@ function log(param){ } function setupButtons() { + let variables = { + 'cordova_var_string': 'cordova_var_string_value', + 'cordova_var_map': { + cordova_var_map_string: 'cordova_var_map_value', + cordova_var_map_float: 10.11, + cordova_var_map_nested:{ + cordova_var_map_nested_float:3.14 + } + }, + 'cordova_var_int': 6, + 'cordova_var_float': 6.9, + 'cordova_var_boolean': true + }; + + let eventsMap = [ + + ["title","Android 13 Push Primer"], + ["promptPushPrimer",()=> CleverTap.promptPushPrimer({ + inAppType: 'alert', + titleText: 'Get Notified', + messageText: + 'Please enable notifications on your device to use Push Notifications.', + followDeviceOrientation: true, + positiveBtnText: 'Allow', + negativeBtnText: 'Cancel', + backgroundColor: '#FFFFFF', + btnBorderColor: '#FF0000', + titleTextColor: '#0000FF', + messageTextColor: '#000000', + btnTextColor: '#FFFFFF', + btnBackgroundColor: '#0000FF', + btnBorderRadius: '5', + imageUrl:"https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png", + fallbackToSettings: true + }) + ], + ["promptForPushPermission",()=> CleverTap.promptForPushPermission(true)], + ["isPushPermissionGranted",()=> CleverTap.isPushPermissionGranted(val => log("isPushPermissionGranted value is " + val))], + + ["title","Product Experiences"], + ["defineVariables", () => CleverTap.defineVariables(variables)], + ["syncVariables", () => CleverTap.syncVariables()], + ["syncVariablesinProd", () => CleverTap.syncVariablesinProd()], + ["fetchVariables", () => CleverTap.fetchVariables(success => log("fetchVariables success = " + success))], + ["getVariable", () => { + let key = prompt("Please enter key", "cordova_var_string"); + CleverTap.getVariable(key,val => log(key+" value is "+JSON.stringify(val))); + } + ], + ["getVariables", () => { + CleverTap.getVariables(val => log("getVariables value is "+val.cordova_var_map.cordova_var_map_nested.cordova_var_map_nested_float)); + } + ], + ["onVariablesChanged", () => { + CleverTap.onVariablesChanged(val => log("onVariablesChanged value is "+JSON.stringify(val))); + } + ], + ["onValueChanged", () => { + let key = prompt("Please enter key", "cordova_var_string"); + CleverTap.onValueChanged(key,val => log("onValueChanged value is "+JSON.stringify(val))); + } + ], + ["title","Events"], ["record Event With Name", () => CleverTap.recordEventWithName("foo")], + ["set Locale", () => CleverTap.setLocale("en_IN")], ["record Event With NameAndProps", () => CleverTap.recordEventWithNameAndProps("boo", {"bar": "zoo"})], ["record Charged Event With Details And Items", () => CleverTap.recordChargedEventWithDetailsAndItems({ "amount": 300, @@ -94,14 +158,7 @@ function setupButtons() { ["title","Feature flag"], ["get Feature Flag", () => CleverTap.getFeatureFlag("test", true, val => log("Value is " + val))], - - ["title","Product Experiences"], - ["get Feature Flag", () => CleverTap.getFeatureFlag("test", true, val => log("Value is " + val))], - -// defineVariables({ -// "cordova_var_string": "cordova_var_string_value" -// })], - + ["title","Device Identifiers"], ["get CleverTap ID", () => CleverTap.getCleverTapID(val => log("getCleverTapID is " + val))], @@ -290,8 +347,10 @@ function initListeners() { CleverTap.deleteInboxMessageForId("messageId") CleverTap.deleteInboxMessagesForIds(["id1", "id2"]) CleverTap.markReadInboxMessageForId("messageId") + CleverTap.markReadInboxMessagesForIds(["id1", "id2"]) CleverTap.pushInboxNotificationViewedEventForId("messageId") CleverTap.pushInboxNotificationClickedEventForId("messageId") + CleverTap.dismissInbox() } ) document.addEventListener('onCleverTapInboxMessagesDidUpdate', () => { @@ -306,7 +365,7 @@ function initListeners() { ) document.addEventListener('onCleverTapInboxItemClick', e => { log("onCleverTapInboxItemClick") - log(e.customExtras) + log(JSON.stringify(e)) } ) @@ -338,6 +397,15 @@ function initListeners() { log(e.customExtras) } ) + document.addEventListener('onCleverTapPushPermissionResponseReceived', e => { + log("onCleverTapPushPermissionResponseReceived") + log(e.accepted) + }) + + document.addEventListener('onCleverTapInAppNotificationShow', e => { + log("onCleverTapInAppNotificationShow") + log(e.customExtras) + }) } diff --git a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/plugins/clevertap-cordova/www/CleverTap.js b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/plugins/clevertap-cordova/www/CleverTap.js index 423025e4..a85b20e8 100644 --- a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/plugins/clevertap-cordova/www/CleverTap.js +++ b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/assets/www/plugins/clevertap-cordova/www/CleverTap.js @@ -7,6 +7,9 @@ cordova.define("clevertap-cordova.CleverTap", function(require, exports, module) // var CleverTap = function () { + const libName = 'Cordova'; + const libVersion = 20702; + cordova.exec(null, null, "CleverTapPlugin", "setLibrary", [libName, libVersion]); } /******************* @@ -74,11 +77,6 @@ CleverTap.prototype.setPushHuaweiToken = function (token) { cordova.exec(null, null, "CleverTapPlugin", "setPushHuaweiTokenAsString", [token]); } -// Change xiaomiCredentials -CleverTap.prototype.changeXiaomiCredentials = function (xiaomiAppID, xiaomiAppKey) { - cordova.exec(null, null, "CleverTapPlugin", "changeXiaomiCredentials", [xiaomiAppID, xiaomiAppKey]); -} - //Create Notification Channel for Android O CleverTap.prototype.createNotification = function (extras) { @@ -455,10 +453,22 @@ CleverTap.prototype.deleteInboxMessageForId = function (messageId) { cordova.exec(null, null, "CleverTapPlugin", "deleteInboxMessageForId", [messageId]); } +CleverTap.prototype.deleteInboxMessagesForIds = function (messageIds) { + cordova.exec(null, null, "CleverTapPlugin", "deleteInboxMessagesForIds", [messageIds]); +} + CleverTap.prototype.markReadInboxMessageForId = function (messageId) { cordova.exec(null, null, "CleverTapPlugin", "markReadInboxMessageForId", [messageId]); } +CleverTap.prototype.markReadInboxMessagesForIds = function (messageIds) { + cordova.exec(null, null, "CleverTapPlugin", "markReadInboxMessagesForIds", [messageIds]); +} + +CleverTap.prototype.dismissInbox= function () { + cordova.exec(null, null, "CleverTapPlugin", "dismissInbox", []); +} + CleverTap.prototype.pushInboxNotificationViewedEventForId = function (messageId) { cordova.exec(null, null, "CleverTapPlugin", "pushInboxNotificationViewedEventForId", [messageId]); } @@ -514,6 +524,9 @@ CleverTap.prototype.pushDisplayUnitClickedEventForID = function(unitId){ /**************************** * Feature Flag methods ****************************/ +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getFeatureFlag = function(name,defaultValue,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getFeatureFlag", [name,defaultValue]); } @@ -521,54 +534,179 @@ CleverTap.prototype.getFeatureFlag = function(name,defaultValue,successCallback) /**************************** * Product Config methods ****************************/ +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.setDefaultsMap = function(jsonMap){ cordova.exec(null, null, "CleverTapPlugin", "setDefaultsMap", [jsonMap]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.fetch = function(){ cordova.exec(null, null, "CleverTapPlugin", "fetch", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.fetchWithMinimumFetchIntervalInSeconds = function(interval){ cordova.exec(null, null, "CleverTapPlugin", "fetchWithMinimumFetchIntervalInSeconds", [interval]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.activate = function(){ cordova.exec(null, null, "CleverTapPlugin", "activate", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.fetchAndActivate = function(){ cordova.exec(null, null, "CleverTapPlugin", "fetchAndActivate", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.setMinimumFetchIntervalInSeconds = function(interval){ cordova.exec(null, null, "CleverTapPlugin", "setMinimumFetchIntervalInSeconds", [interval]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getLastFetchTimeStampInMillis = function(successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getLastFetchTimeStampInMillis", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getString = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getString", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getBoolean = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getBoolean", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getLong = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getLong", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getDouble = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getDouble", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.reset = function(){ cordova.exec(null, null, "CleverTapPlugin", "reset", []); } + +/**************************** + * Product Experiences methods + ****************************/ + +/** + Uploads variables to the server. Requires Development/Debug build/configuration. +*/ +CleverTap.prototype.syncVariables = function(){ + cordova.exec(null, null, "CleverTapPlugin", "syncVariables", []); +} + +/** +Uploads variables to the server. +@param {boolean} isProduction Provide `true` if variables must be sync in Productuon build/configuration. +*/ +CleverTap.prototype.syncVariablesinProd = function(isProduction){ + cordova.exec(null, null, "CleverTapPlugin", "syncVariablesinProd", [isProduction]); +} + +/** +Forces variables to update from the server. +*/ +CleverTap.prototype.fetchVariables = function(successCallback){ + cordova.exec(successCallback, null, "CleverTapPlugin", "fetchVariables", []); +} + +/** +Create variables. +@param {object} variables The JSON Object specifying the varibles to be created. +*/ +CleverTap.prototype.defineVariables = function (variables) { + cordova.exec(null, null, "CleverTapPlugin", "defineVariables", [variables]); +} + +/** +Get a variable or a group for the specified name. +@param {string} name - name. +*/ +CleverTap.prototype.getVariable = function (name, successCallback) { + cordova.exec(successCallback, null, "CleverTapPlugin", "getVariable", [name]); +} + +/** +Get all variables via a JSON object. +*/ +CleverTap.prototype.getVariables = function (successCallback) { + cordova.exec(successCallback, null, "CleverTapPlugin", "getVariables", []); +} + + /** +Adds a callback to be invoked when variables are initialised with server values. Will be called each time new values are fetched. +@param {function} handler The callback to add +*/ +CleverTap.prototype.onVariablesChanged = function (handler) { + cordova.exec(handler, null, "CleverTapPlugin", "onVariablesChanged", []); +} + +/** +Called when the value of the variable changes. +@param {name} string the name of the variable +@param {function} handler The callback to add +*/ +CleverTap.prototype.onValueChanged = function (name, handler) { + cordova.exec(handler, null, "CleverTapPlugin", "onValueChanged", [name]); +} + +/**************************** + * Android 13 Push Primer + ****************************/ + +CleverTap.prototype.promptPushPrimer = function(localInAppObject){ + cordova.exec(null, null, "CleverTapPlugin", "promptPushPrimer", [localInAppObject]); +} + +CleverTap.prototype.promptForPushPermission = function(showFallbackSettings){ + cordova.exec(null, null, "CleverTapPlugin", "promptForPushPermission", [showFallbackSettings]); +} + +CleverTap.prototype.isPushPermissionGranted = function(successCallback){ + cordova.exec(successCallback, null, "CleverTapPlugin", "isPushPermissionGranted", []); +} + +// Set Locale +// locale = string +CleverTap.prototype.setLocale = function (locale) { + cordova.exec(null, null, "CleverTapPlugin", "setLocale", [locale]); +} + function convertDateToEpochInProperties(items){ //Conversion of date object in suitable CleverTap format diff --git a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/java/com/clevertap/cordova/CleverTapPlugin.java b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/java/com/clevertap/cordova/CleverTapPlugin.java index 811104bb..a3d8217b 100644 --- a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/java/com/clevertap/cordova/CleverTapPlugin.java +++ b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/java/com/clevertap/cordova/CleverTapPlugin.java @@ -16,15 +16,27 @@ import android.util.Log; import android.location.Location; +import androidx.annotation.NonNull; +import com.clevertap.android.sdk.PushPermissionResponseListener; +import com.clevertap.android.sdk.inapp.CTInAppNotification; +import com.clevertap.android.sdk.inapp.CTLocalInApp; import com.clevertap.android.sdk.pushnotification.CTPushNotificationListener; import com.clevertap.android.sdk.pushnotification.amp.CTPushAmpListener; +import com.clevertap.android.sdk.variables.CTVariableUtils; +import com.clevertap.android.sdk.variables.Var; +import com.clevertap.android.sdk.variables.callbacks.VariableCallback; +import com.clevertap.android.sdk.variables.callbacks.VariablesChangedCallback; +import java.util.Objects; import java.util.Set; +import java.util.regex.Matcher; +import java.util.regex.Pattern; import org.apache.cordova.CordovaInterface; import org.apache.cordova.CordovaWebView; import org.apache.cordova.CordovaPlugin; import org.apache.cordova.CallbackContext; import org.apache.cordova.PluginResult; +import org.apache.cordova.PluginResult.Status; import org.json.JSONArray; import org.json.JSONException; import org.json.JSONObject; @@ -62,12 +74,14 @@ public class CleverTapPlugin extends CordovaPlugin implements SyncListener, InAppNotificationListener, CTInboxListener, InboxMessageButtonListener, InAppNotificationButtonListener, DisplayUnitListener, - CTFeatureFlagsListener, CTProductConfigListener, CTPushNotificationListener, CTPushAmpListener, InboxMessageListener { + CTFeatureFlagsListener, CTProductConfigListener, CTPushNotificationListener, CTPushAmpListener, InboxMessageListener, + PushPermissionResponseListener { private static final String LOG_TAG = "CLEVERTAP_PLUGIN"; private static String CLEVERTAP_API_ERROR; private static CleverTapAPI cleverTap; private boolean callbackDone = false; + public static Map variables = new HashMap<>(); @Override @@ -86,6 +100,7 @@ public void initialize(CordovaInterface cordova, CordovaWebView webView) { cleverTap.setCTProductConfigListener(this); cleverTap.setCTPushNotificationListener(this); cleverTap.setCTPushAmpListener(this); + cleverTap.registerPushPermissionNotificationResponseListener(this); cleverTap.setLibrary("Cordova"); try { @@ -111,6 +126,10 @@ public void onNewIntent(Intent intent) { if (intent.getAction() != null && intent.getAction().equals(Intent.ACTION_VIEW)) { Uri data = intent.getData(); if (data != null) { + if(!isDeepLinkValid(data)){ + Log.w(LOG_TAG, "Found malicious deep link. Not processing further."); + return; + } final String json = "{'deeplink':'" + data.toString() + "'}"; cordova.getActivity().runOnUiThread(new Runnable() { @@ -255,18 +274,6 @@ public void run() { } }); return true; - } else if (action.equals("changeXiaomiCredentials")) { - final String xiaomiAppID = args.getString(0); - final String xiaomiAppKey = args.getString(1); - cordova.getThreadPool().execute(new Runnable() { - public void run() { - cleverTap.changeXiaomiCredentials(xiaomiAppID, xiaomiAppKey); - PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); - _result.setKeepCallback(true); - callbackContext.sendPluginResult(_result); - } - }); - return true; } else if (action.equals("createNotification")) { final String extras = args.getString(0); JSONObject json = new JSONObject(extras); @@ -1396,6 +1403,65 @@ public void run() { } }); return true; + } else if (action.equals("markReadInboxMessagesForIds")) { + JSONArray jsonArray = null; + if (args.length() == 1) { + jsonArray = args.getJSONArray(0); + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + if (!haveError) { + final JSONArray finalJsonArray = jsonArray; + cordova.getThreadPool().execute(() -> { + try { + cleverTap.markReadInboxMessagesForIDs((ArrayList) toStringList(finalJsonArray)); + + PluginResult _result = new PluginResult(Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } catch (Exception e) { + PluginResult _result = new PluginResult(Status.ERROR, e.getLocalizedMessage()); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } + } else if (action.equals("deleteInboxMessagesForIds")) { + JSONArray jsonArray = null; + if (args.length() == 1) { + jsonArray = args.getJSONArray(0); + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + if (!haveError) { + final JSONArray finalJsonArray = jsonArray; + cordova.getThreadPool().execute(() -> { + try { + cleverTap.deleteInboxMessagesForIDs((ArrayList) toStringList(finalJsonArray)); + + PluginResult _result = new PluginResult(Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } catch (Exception e) { + PluginResult _result = new PluginResult(Status.ERROR, e.getLocalizedMessage()); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } + } else if (action.equals("dismissInbox")) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + cleverTap.dismissAppInbox(); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); } else if (action.equals("pushInboxNotificationViewedEventForId")) { final String messageId = (args.length() == 1 ? args.getString(0) : ""); @@ -1676,6 +1742,251 @@ public void run() { } }); return true; + } else if (action.equals("promptPushPrimer")) { + JSONObject pushPrimerJsonObject = null; + if (args.length() == 1) { + if (!args.isNull(0)) { + try { + pushPrimerJsonObject = processPushPrimerArgument(args.getJSONObject(0)); + if (pushPrimerJsonObject == null) + { + haveError = true; + errorMsg = "Invalid parameters in push primer config"; + } + } catch (Exception e) { + haveError = true; + errorMsg = e.getLocalizedMessage(); + } + } else { + haveError = true; + errorMsg = "object passed to promptPushPrimer can not be null!"; + } + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + + if (!haveError) { + final JSONObject finalPushPrimerJsonObject = pushPrimerJsonObject; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + cleverTap.promptPushPrimer(finalPushPrimerJsonObject); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } + } else if (action.equals("promptForPushPermission")) { + boolean showFallbackSettings = false; + + if (args.length() == 1) { + showFallbackSettings = args.getBoolean(0); + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + if (!haveError) { + final boolean finalShowFallbackSettings = showFallbackSettings; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + cleverTap.promptForPushPermission(finalShowFallbackSettings); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } + } else if (action.equals("isPushPermissionGranted")) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + boolean value = cleverTap.isPushPermissionGranted(); + PluginResult _result = new PluginResult(PluginResult.Status.OK, value); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } else if (action.equals("setLibrary")) { + String libName = args.getString(0); + int libVersion = args.getInt(1); + cordova.getThreadPool().execute(new Runnable() { + public void run() { + cleverTap.setCustomSdkVersion(libName,libVersion); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } else if (action.equals("syncVariables")) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + cleverTap.syncVariables(); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } else if (action.equals("syncVariablesinProd")) { + cordova.getThreadPool().execute(new Runnable() { + public void run() { + Log.d(LOG_TAG, "syncVariablesinProd is no-op in Android"); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } else if (action.equals("fetchVariables")) { + cordova.getThreadPool().execute(() -> { + cleverTap.fetchVariables(isSuccess -> { + PluginResult _result = new PluginResult(PluginResult.Status.OK, isSuccess); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + }); + + }); + return true; + } else if (action.equals("defineVariables")) { + Map variablesMap = null; + if (args.length() == 1) { + if (!args.isNull(0)) { + try { + variablesMap = toMap(args.getJSONObject(0)); + } catch (Exception e) { + haveError = true; + errorMsg = e.getLocalizedMessage(); + } + } else { + haveError = true; + errorMsg = "object passed to defineVariables can not be null!"; + } + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + + if (!haveError) { + final Map finalVariablesJsonObject = variablesMap; + cordova.getThreadPool().execute(() -> { + for (Map.Entry entry : finalVariablesJsonObject.entrySet()) { + String key = entry.getKey(); + Object value = entry.getValue(); + variables.put(key, cleverTap.defineVariable(key, value)); + } + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + }); + return true; + } + } else if (action.equals("getVariable")) { + String variableName = null; + + if (args.length() == 1) { + variableName = args.getString(0); + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + + if (!haveError) { + final String finalVariableName = variableName; + cordova.getThreadPool().execute(() -> { + try { + Object value = getVariableValue(finalVariableName); + PluginResult _result = getPluginResult(Status.OK, value); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } catch (Exception e) { + PluginResult _result = new PluginResult(Status.ERROR, e.getLocalizedMessage()); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } + } else if (action.equals("getVariables")) { + cordova.getThreadPool().execute(() -> { + JSONObject jsonVariables = getVariablesAsJson(); + PluginResult _result = new PluginResult(PluginResult.Status.OK, jsonVariables); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + }); + return true; + } else if (action.equals("onVariablesChanged")) { + cordova.getThreadPool().execute(() -> { + cleverTap.addVariablesChangedCallback(new VariablesChangedCallback() { + @Override + public void variablesChanged() { + JSONObject jsonVariables = getVariablesAsJson(); + PluginResult _result = new PluginResult(PluginResult.Status.OK,jsonVariables); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + }); + return true; + } else if (action.equals("onValueChanged")) { + + String variableName = null; + + if (args.length() == 1) { + variableName = args.getString(0); + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + + if (!haveError) { + final String finalVariableName = variableName; + cordova.getThreadPool().execute(() -> { + try { + if (variables.containsKey(finalVariableName)) { + Var variable = (Var) variables.get(finalVariableName); + variable.addValueChangedCallback(new VariableCallback() { + @Override + public void onValueChanged(final Var variable) { + Object value = getVariableValue(finalVariableName); + PluginResult _result = getPluginResult(Status.OK, value); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + + } + }); + } + } catch (Exception e) { + PluginResult _result = new PluginResult(Status.ERROR, e.getLocalizedMessage()); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } + } else if (action.equals("setLocale")) { + String variableName = null; + if(args.length() == 1) { + variableName = args.getString(0); + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + if (!haveError) { + final String finalVariableName = variableName; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + cleverTap.setLocale(finalVariableName); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } } result = new PluginResult(PluginResult.Status.ERROR, errorMsg); @@ -1684,6 +1995,43 @@ public void run() { return true; } + @NonNull + private JSONObject getVariablesAsJson() { + JSONObject jsonVariables = new JSONObject(); + for (String key : variables.keySet()) { + try { + jsonVariables.put(key,getVariableValue(key)); + } catch (Exception e) { + e.printStackTrace(); + } + } + return jsonVariables; + } + + @NonNull + private PluginResult getPluginResult(final Status ok, final Object value) { + PluginResult _result; + if (value instanceof Boolean) { + _result = new PluginResult(ok, (Boolean) value); + } else if (value instanceof Double) { + _result = new PluginResult(ok, ((Double) value).floatValue()); + } else if (value instanceof Float) { + _result = new PluginResult(ok, (Float) value); + } else if (value instanceof Integer) { + _result = new PluginResult(ok, (Integer) value); + } else if (value instanceof Long) { + _result = new PluginResult(ok, ((Long) value).intValue()); + } else if (value instanceof String) { + _result = new PluginResult(ok, (String) value); + } else if (value instanceof JSONObject) { + _result = new PluginResult(ok, (JSONObject) value); + } else { + _result = new PluginResult(PluginResult.Status.ERROR, "unknown value type"); + } + + return _result; + } + //DisplayUnitListener public void onDisplayUnitsLoaded(ArrayList units) { @@ -1749,6 +2097,16 @@ public void run() { }); } + @Override + public void onPushPermissionResponse(final boolean accepted) { + final String json = "{'accepted':" + accepted + "}"; + webView.getView().post(new Runnable() { + public void run() { + webView.loadUrl("javascript:cordova.fireDocumentEvent('onCleverTapPushPermissionResponseReceived'," + json + ");"); + } + }); + } + // SyncListener public void profileDataUpdated(JSONObject updates) { @@ -1792,13 +2150,34 @@ public void run() { }); } - public void onInboxItemClicked(CTInboxMessage message){ + @Override + public void onShow(CTInAppNotification inAppNotification) { + if(inAppNotification != null && inAppNotification.getJsonDescription() != null){ + //Read the values + final String json = "{'customExtras':" + inAppNotification.getJsonDescription().toString() + "}"; + webView.getView().post(new Runnable() { + public void run() { + webView.loadUrl("javascript:cordova.fireDocumentEvent('onCleverTapInAppNotificationShow'," + json + ");"); + } + }); + } + } + + public void onInboxItemClicked(CTInboxMessage message, int contentPageIndex, int buttonIndex){ if(message != null && message.getData() != null){ //Read the values - final String json = "{'customExtras':" + message.getData().toString() + "}"; + JSONObject jsonObject = new JSONObject(); + try { + jsonObject.put("data",message.getData()); + jsonObject.put("contentPageIndex",contentPageIndex); + jsonObject.put("buttonIndex",buttonIndex); + } catch (JSONException e) { + Log.e(LOG_TAG,"Failed to parse inbox message."); + } + webView.getView().post(new Runnable() { public void run() { - webView.loadUrl("javascript:cordova.fireDocumentEvent('onCleverTapInboxItemClick'," + json + ");"); + webView.loadUrl("javascript:cordova.fireDocumentEvent('onCleverTapInboxItemClick'," + jsonObject + ");"); } }); } @@ -2063,16 +2442,20 @@ private static HashMap toStringMap(JSONObject object) throws JSO return map; } - private JSONObject getJsonFromMap(Map map) throws JSONException { - JSONObject jsonData = new JSONObject(); - for (String key : map.keySet()) { - Object value = map.get(key); - if (value instanceof Map) { - value = getJsonFromMap((Map) value); + private Object getVariableValue(String name) { + if (variables.containsKey(name)) { + Var variable = (Var) variables.get(name); + Object variableValue = variable.value(); + Object value; + if (CTVariableUtils.DICTIONARY.equals(variable.kind())) { + value = new JSONObject((Map) variableValue); + } else { + value = variableValue; } - jsonData.put(key, value); + return value; } - return jsonData; + throw new IllegalArgumentException( + "Variable name = " + name + " does not exist. Make sure you set variable first."); } private JSONArray displayUnitListToJSONArray(ArrayList displayUnits) throws JSONException { @@ -2139,4 +2522,157 @@ private JSONObject toJson(Bundle bundle) { } return json; } + + private boolean isDeepLinkValid(Uri data) { + String link = Uri.decode(data.toString()); + String patternString = "[{}\\[\\]()\"';]|javascript"; + Pattern pattern = Pattern.compile(patternString); + Matcher matcher = pattern.matcher(link); + return !matcher.find(); + } + + private JSONObject processPushPrimerArgument(JSONObject jsonObject) { + CTLocalInApp.InAppType inAppType = null; + String titleText = null, messageText = null, positiveBtnText = null, negativeBtnText = null, + backgroundColor = null, btnBorderColor = null, titleTextColor = null, messageTextColor = null, + btnTextColor = null, imageUrl = null, btnBackgroundColor = null, btnBorderRadius = null; + boolean fallbackToSettings = false, followDeviceOrientation = false; + + final Iterator iterator = jsonObject.keys(); + while (iterator.hasNext()) { + try { + final String configKey = iterator.next(); + switch (configKey) { + case "inAppType": + inAppType = inAppTypeFromString(jsonObject.getString(configKey)); + break; + case "titleText": + titleText = jsonObject.getString(configKey); + break; + case "messageText": + messageText = jsonObject.getString(configKey); + break; + case "followDeviceOrientation": + followDeviceOrientation = jsonObject.getBoolean(configKey); + break; + case "positiveBtnText": + positiveBtnText = jsonObject.getString(configKey); + break; + case "negativeBtnText": + negativeBtnText = jsonObject.getString(configKey); + break; + case "fallbackToSettings": + fallbackToSettings = jsonObject.getBoolean(configKey); + break; + case "backgroundColor": + backgroundColor = jsonObject.getString(configKey); + break; + case "btnBorderColor": + btnBorderColor = jsonObject.getString(configKey); + break; + case "titleTextColor": + titleTextColor = jsonObject.getString(configKey); + break; + case "messageTextColor": + messageTextColor = jsonObject.getString(configKey); + break; + case "btnTextColor": + btnTextColor = jsonObject.getString(configKey); + break; + case "imageUrl": + imageUrl = jsonObject.getString(configKey); + break; + case "btnBackgroundColor": + btnBackgroundColor = jsonObject.getString(configKey); + break; + case "btnBorderRadius": + btnBorderRadius = jsonObject.getString(configKey); + break; + } + } catch (Throwable t) { + Log.e(LOG_TAG, "invalid parameters in push primer config" + t.getLocalizedMessage()); + return null; + } + } + + //creates the builder instance of localInApp with all the required parameters + CTLocalInApp.Builder.Builder6 builderWithRequiredParams = getLocalInAppBuilderWithRequiredParam( + inAppType, titleText, messageText, followDeviceOrientation, positiveBtnText, negativeBtnText + ); + + //adds the optional parameters to the builder instance + if (backgroundColor != null) { + builderWithRequiredParams.setBackgroundColor(backgroundColor); + } + if (btnBorderColor != null) { + builderWithRequiredParams.setBtnBorderColor(btnBorderColor); + } + if (titleTextColor != null) { + builderWithRequiredParams.setTitleTextColor(titleTextColor); + } + if (messageTextColor != null) { + builderWithRequiredParams.setMessageTextColor(messageTextColor); + } + if (btnTextColor != null) { + builderWithRequiredParams.setBtnTextColor(btnTextColor); + } + if (imageUrl != null) { + builderWithRequiredParams.setImageUrl(imageUrl); + } + if (btnBackgroundColor != null) { + builderWithRequiredParams.setBtnBackgroundColor(btnBackgroundColor); + } + if (btnBorderRadius != null) { + builderWithRequiredParams.setBtnBorderRadius(btnBorderRadius); + } + builderWithRequiredParams.setFallbackToSettings(fallbackToSettings); + + JSONObject localInAppConfig = builderWithRequiredParams.build(); + Log.i(LOG_TAG, "LocalInAppConfig for push primer prompt: " + localInAppConfig); + return localInAppConfig; + + + } + + /** + * Creates an instance of the {@link CTLocalInApp.Builder.Builder6} with the required parameters. + * + * @return the {@link CTLocalInApp.Builder.Builder6} instance + */ + private CTLocalInApp.Builder.Builder6 getLocalInAppBuilderWithRequiredParam(CTLocalInApp.InAppType inAppType, + String titleText, + String messageText, + boolean followDeviceOrientation, + String positiveBtnText, + String negativeBtnText) { + //throws exception if any of the required parameter is missing + if (inAppType == null || titleText == null || messageText == null || positiveBtnText == null + || negativeBtnText == null) { + throw new IllegalArgumentException("mandatory parameters are missing in push primer config"); + } + + CTLocalInApp.Builder builder = CTLocalInApp.builder(); + + return builder.setInAppType(inAppType) + .setTitleText(titleText) + .setMessageText(messageText) + .followDeviceOrientation(followDeviceOrientation) + .setPositiveBtnText(positiveBtnText) + .setNegativeBtnText(negativeBtnText); + } + + //returns InAppType type from the given string + private CTLocalInApp.InAppType inAppTypeFromString(String inAppType) { + if (inAppType == null) { + return null; + } + switch (inAppType) { + case "half-interstitial": + return CTLocalInApp.InAppType.HALF_INTERSTITIAL; + case "alert": + return CTLocalInApp.InAppType.ALERT; + default: + return null; + } + } } \ No newline at end of file diff --git a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/res/xml/config.xml b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/res/xml/config.xml index adf46fdc..f84203a2 100644 --- a/Samples/Cordova/ExampleProject/platforms/android/app/src/main/res/xml/config.xml +++ b/Samples/Cordova/ExampleProject/platforms/android/app/src/main/res/xml/config.xml @@ -21,8 +21,8 @@ - - + + diff --git a/Samples/Cordova/ExampleProject/platforms/android/cdv-gradle-config.json b/Samples/Cordova/ExampleProject/platforms/android/cdv-gradle-config.json index 4c9ad063..dda634fc 100644 --- a/Samples/Cordova/ExampleProject/platforms/android/cdv-gradle-config.json +++ b/Samples/Cordova/ExampleProject/platforms/android/cdv-gradle-config.json @@ -1,16 +1 @@ -{ - "MIN_SDK_VERSION": 21, - "SDK_VERSION": 32, - "COMPILE_SDK_VERSION": null, - "GRADLE_VERSION": "7.4.2", - "MIN_BUILD_TOOLS_VERSION": "32.0.0", - "AGP_VERSION": "7.2.1", - "KOTLIN_VERSION": "1.5.21", - "ANDROIDX_APP_COMPAT_VERSION": "1.4.2", - "ANDROIDX_WEBKIT_VERSION": "1.4.0", - "ANDROIDX_CORE_SPLASHSCREEN_VERSION": "1.0.0-rc01", - "GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION": "4.3.10", - "IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED": true, - "IS_GRADLE_PLUGIN_KOTLIN_ENABLED": false, - "MAX_SDK_VERSION": 32 -} +{"MIN_SDK_VERSION":21,"SDK_VERSION":33,"COMPILE_SDK_VERSION":null,"GRADLE_VERSION":"7.6","MIN_BUILD_TOOLS_VERSION":"33.0.2","AGP_VERSION":"7.4.2","KOTLIN_VERSION":"1.7.21","ANDROIDX_APP_COMPAT_VERSION":"1.6.1","ANDROIDX_WEBKIT_VERSION":"1.6.0","ANDROIDX_CORE_SPLASHSCREEN_VERSION":"1.0.0","GRADLE_PLUGIN_GOOGLE_SERVICES_VERSION":"4.3.15","IS_GRADLE_PLUGIN_GOOGLE_SERVICES_ENABLED":true,"IS_GRADLE_PLUGIN_KOTLIN_ENABLED":false,"PACKAGE_NAMESPACE":"com.clevertap.example","MAX_SDK_VERSION":33} diff --git a/Samples/Cordova/ExampleProject/platforms/android/platform_www/plugins/clevertap-cordova/www/CleverTap.js b/Samples/Cordova/ExampleProject/platforms/android/platform_www/plugins/clevertap-cordova/www/CleverTap.js index 423025e4..a85b20e8 100644 --- a/Samples/Cordova/ExampleProject/platforms/android/platform_www/plugins/clevertap-cordova/www/CleverTap.js +++ b/Samples/Cordova/ExampleProject/platforms/android/platform_www/plugins/clevertap-cordova/www/CleverTap.js @@ -7,6 +7,9 @@ cordova.define("clevertap-cordova.CleverTap", function(require, exports, module) // var CleverTap = function () { + const libName = 'Cordova'; + const libVersion = 20702; + cordova.exec(null, null, "CleverTapPlugin", "setLibrary", [libName, libVersion]); } /******************* @@ -74,11 +77,6 @@ CleverTap.prototype.setPushHuaweiToken = function (token) { cordova.exec(null, null, "CleverTapPlugin", "setPushHuaweiTokenAsString", [token]); } -// Change xiaomiCredentials -CleverTap.prototype.changeXiaomiCredentials = function (xiaomiAppID, xiaomiAppKey) { - cordova.exec(null, null, "CleverTapPlugin", "changeXiaomiCredentials", [xiaomiAppID, xiaomiAppKey]); -} - //Create Notification Channel for Android O CleverTap.prototype.createNotification = function (extras) { @@ -455,10 +453,22 @@ CleverTap.prototype.deleteInboxMessageForId = function (messageId) { cordova.exec(null, null, "CleverTapPlugin", "deleteInboxMessageForId", [messageId]); } +CleverTap.prototype.deleteInboxMessagesForIds = function (messageIds) { + cordova.exec(null, null, "CleverTapPlugin", "deleteInboxMessagesForIds", [messageIds]); +} + CleverTap.prototype.markReadInboxMessageForId = function (messageId) { cordova.exec(null, null, "CleverTapPlugin", "markReadInboxMessageForId", [messageId]); } +CleverTap.prototype.markReadInboxMessagesForIds = function (messageIds) { + cordova.exec(null, null, "CleverTapPlugin", "markReadInboxMessagesForIds", [messageIds]); +} + +CleverTap.prototype.dismissInbox= function () { + cordova.exec(null, null, "CleverTapPlugin", "dismissInbox", []); +} + CleverTap.prototype.pushInboxNotificationViewedEventForId = function (messageId) { cordova.exec(null, null, "CleverTapPlugin", "pushInboxNotificationViewedEventForId", [messageId]); } @@ -514,6 +524,9 @@ CleverTap.prototype.pushDisplayUnitClickedEventForID = function(unitId){ /**************************** * Feature Flag methods ****************************/ +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getFeatureFlag = function(name,defaultValue,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getFeatureFlag", [name,defaultValue]); } @@ -521,54 +534,179 @@ CleverTap.prototype.getFeatureFlag = function(name,defaultValue,successCallback) /**************************** * Product Config methods ****************************/ +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.setDefaultsMap = function(jsonMap){ cordova.exec(null, null, "CleverTapPlugin", "setDefaultsMap", [jsonMap]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.fetch = function(){ cordova.exec(null, null, "CleverTapPlugin", "fetch", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.fetchWithMinimumFetchIntervalInSeconds = function(interval){ cordova.exec(null, null, "CleverTapPlugin", "fetchWithMinimumFetchIntervalInSeconds", [interval]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.activate = function(){ cordova.exec(null, null, "CleverTapPlugin", "activate", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.fetchAndActivate = function(){ cordova.exec(null, null, "CleverTapPlugin", "fetchAndActivate", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.setMinimumFetchIntervalInSeconds = function(interval){ cordova.exec(null, null, "CleverTapPlugin", "setMinimumFetchIntervalInSeconds", [interval]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getLastFetchTimeStampInMillis = function(successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getLastFetchTimeStampInMillis", []); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getString = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getString", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getBoolean = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getBoolean", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getLong = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getLong", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.getDouble = function(key,successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "getDouble", [key]); } +/** + * @deprecated - Since version 2.7.0 and will be removed in the future versions of this SDK. + */ CleverTap.prototype.reset = function(){ cordova.exec(null, null, "CleverTapPlugin", "reset", []); } + +/**************************** + * Product Experiences methods + ****************************/ + +/** + Uploads variables to the server. Requires Development/Debug build/configuration. +*/ +CleverTap.prototype.syncVariables = function(){ + cordova.exec(null, null, "CleverTapPlugin", "syncVariables", []); +} + +/** +Uploads variables to the server. +@param {boolean} isProduction Provide `true` if variables must be sync in Productuon build/configuration. +*/ +CleverTap.prototype.syncVariablesinProd = function(isProduction){ + cordova.exec(null, null, "CleverTapPlugin", "syncVariablesinProd", [isProduction]); +} + +/** +Forces variables to update from the server. +*/ +CleverTap.prototype.fetchVariables = function(successCallback){ + cordova.exec(successCallback, null, "CleverTapPlugin", "fetchVariables", []); +} + +/** +Create variables. +@param {object} variables The JSON Object specifying the varibles to be created. +*/ +CleverTap.prototype.defineVariables = function (variables) { + cordova.exec(null, null, "CleverTapPlugin", "defineVariables", [variables]); +} + +/** +Get a variable or a group for the specified name. +@param {string} name - name. +*/ +CleverTap.prototype.getVariable = function (name, successCallback) { + cordova.exec(successCallback, null, "CleverTapPlugin", "getVariable", [name]); +} + +/** +Get all variables via a JSON object. +*/ +CleverTap.prototype.getVariables = function (successCallback) { + cordova.exec(successCallback, null, "CleverTapPlugin", "getVariables", []); +} + + /** +Adds a callback to be invoked when variables are initialised with server values. Will be called each time new values are fetched. +@param {function} handler The callback to add +*/ +CleverTap.prototype.onVariablesChanged = function (handler) { + cordova.exec(handler, null, "CleverTapPlugin", "onVariablesChanged", []); +} + +/** +Called when the value of the variable changes. +@param {name} string the name of the variable +@param {function} handler The callback to add +*/ +CleverTap.prototype.onValueChanged = function (name, handler) { + cordova.exec(handler, null, "CleverTapPlugin", "onValueChanged", [name]); +} + +/**************************** + * Android 13 Push Primer + ****************************/ + +CleverTap.prototype.promptPushPrimer = function(localInAppObject){ + cordova.exec(null, null, "CleverTapPlugin", "promptPushPrimer", [localInAppObject]); +} + +CleverTap.prototype.promptForPushPermission = function(showFallbackSettings){ + cordova.exec(null, null, "CleverTapPlugin", "promptForPushPermission", [showFallbackSettings]); +} + +CleverTap.prototype.isPushPermissionGranted = function(successCallback){ + cordova.exec(successCallback, null, "CleverTapPlugin", "isPushPermissionGranted", []); +} + +// Set Locale +// locale = string +CleverTap.prototype.setLocale = function (locale) { + cordova.exec(null, null, "CleverTapPlugin", "setLocale", [locale]); +} + function convertDateToEpochInProperties(items){ //Conversion of date object in suitable CleverTap format diff --git a/Samples/Cordova/ExampleProject/platforms/ios/www/plugins/clevertap-cordova/www/CleverTap.js b/Samples/Cordova/ExampleProject/platforms/ios/www/plugins/clevertap-cordova/www/CleverTap.js index 77b1e00b..a85b20e8 100644 --- a/Samples/Cordova/ExampleProject/platforms/ios/www/plugins/clevertap-cordova/www/CleverTap.js +++ b/Samples/Cordova/ExampleProject/platforms/ios/www/plugins/clevertap-cordova/www/CleverTap.js @@ -8,7 +8,7 @@ cordova.define("clevertap-cordova.CleverTap", function(require, exports, module) var CleverTap = function () { const libName = 'Cordova'; - const libVersion = 20603; + const libVersion = 20702; cordova.exec(null, null, "CleverTapPlugin", "setLibrary", [libName, libVersion]); } @@ -686,7 +686,7 @@ CleverTap.prototype.onValueChanged = function (name, handler) { } /**************************** - *Push Primer + * Android 13 Push Primer ****************************/ CleverTap.prototype.promptPushPrimer = function(localInAppObject){ @@ -701,6 +701,12 @@ CleverTap.prototype.isPushPermissionGranted = function(successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "isPushPermissionGranted", []); } +// Set Locale +// locale = string +CleverTap.prototype.setLocale = function (locale) { + cordova.exec(null, null, "CleverTapPlugin", "setLocale", [locale]); +} + function convertDateToEpochInProperties(items){ //Conversion of date object in suitable CleverTap format diff --git a/Samples/Cordova/ExampleProject/www/js/index.js b/Samples/Cordova/ExampleProject/www/js/index.js index b06d674e..962e48c7 100644 --- a/Samples/Cordova/ExampleProject/www/js/index.js +++ b/Samples/Cordova/ExampleProject/www/js/index.js @@ -82,6 +82,7 @@ function setupButtons() { ["title","Events"], ["record Event With Name", () => CleverTap.recordEventWithName("foo")], + ["set Locale", () => CleverTap.setLocale("en_IN")], ["record Event With NameAndProps", () => CleverTap.recordEventWithNameAndProps("boo", {"bar": "zoo"})], ["record Charged Event With Details And Items", () => CleverTap.recordChargedEventWithDetailsAndItems({ "amount": 300, diff --git a/docs/Integrate-Android.md b/docs/Integrate-Android.md index 66b22511..1479779a 100644 --- a/docs/Integrate-Android.md +++ b/docs/Integrate-Android.md @@ -155,6 +155,29 @@ Add encryption level in the `AndroidManifest.xml` as following, android:value="1" /> ``` +## Integrate Custom Proxy Domain +The custom proxy domain feature allows to proxy all events raised from the CleverTap SDK through your required domain, ideal for handling or relaying CleverTap events and Push Impression events with your application server. Refer following steps to configure the custom proxy domain(s) in the manifest file From Cordova SDK `v2.7.2` onwards: + +#### Configure Custom Proxy Domain(s) using Manifest file +1. Add your CleverTap Account credentials in the Manifest file against the `CLEVERTAP_ACCOUNT_ID` and `CLEVERTAP_TOKEN` keys. +2. Add the **CLEVERTAP_PROXY_DOMAIN** key with the proxy domain value for handling events through the custom proxy domain. +3. Add the **CLEVERTAP_SPIKY_PROXY_DOMAIN** key with proxy domain value for handling push impression events. + +```xml + + + + +``` + ## Integrate Javascript with the Plugin All calls to the CleverTap plugin should be made from your Javascript. diff --git a/docs/Integrate-iOS.md b/docs/Integrate-iOS.md index b4f9ee09..805159f7 100644 --- a/docs/Integrate-iOS.md +++ b/docs/Integrate-iOS.md @@ -23,6 +23,14 @@ Currently 2 levels of encryption are supported i.e None(0) and Medium(1). Encryp The only way to set encryption level is from the info.plist. Add the `CleverTapEncryptionLevel` String key to `info.plist` file where value 1 means Medium and 0 means None. Encryption Level will be None if any other value is provided. +## Integrate Custom Proxy Domain +The custom proxy domain feature allows to proxy all events raised from the CleverTap SDK through your required domain, ideal for handling or relaying CleverTap events and Push Impression events with your application server. Refer following steps to configure the custom proxy domain(s) in the `Info.plist` file. + +#### Configure Custom Proxy Domain(s) using Info.plist file +1. Add your CleverTap Account credentials in the *Info.plist* file against the `CleverTapAccountID` and `CleverTapToken` keys, if they are empty/do not exist. +2. Add the `CleverTapProxyDomain` key with the proxy domain value for handling events through the custom proxy domain e.g., *analytics.sdktesting.xyz*. +3. Add the `CleverTapSpikyProxyDomain` key with proxy domain value for handling push impression events e.g., *spiky-analytics.sdktesting.xyz*. + ## Integrate Javascript with the Plugin - Refer to our [Usage Documentation](/docs/Usage.md) for implementation. diff --git a/package.json b/package.json index 8c1d74bf..019a8182 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "clevertap-cordova", - "version": "2.7.1", + "version": "2.7.2", "description": "CleverTap Plugin for Cordova/PhoneGap", "cordova": { "id": "clevertap-cordova", diff --git a/plugin.xml b/plugin.xml index d158ec16..e7279c57 100644 --- a/plugin.xml +++ b/plugin.xml @@ -1,5 +1,5 @@ - + CleverTap CleverTap Plugin for Cordova/PhoneGap Commercial @@ -46,7 +46,7 @@ - + @@ -104,7 +104,7 @@ - + diff --git a/src/android/CleverTapPlugin.java b/src/android/CleverTapPlugin.java index 023fd40f..a3d8217b 100644 --- a/src/android/CleverTapPlugin.java +++ b/src/android/CleverTapPlugin.java @@ -1967,7 +1967,26 @@ public void onValueChanged(final Var variable) { }); return true; } - + } else if (action.equals("setLocale")) { + String variableName = null; + if(args.length() == 1) { + variableName = args.getString(0); + } else { + haveError = true; + errorMsg = "Expected 1 argument"; + } + if (!haveError) { + final String finalVariableName = variableName; + cordova.getThreadPool().execute(new Runnable() { + public void run() { + cleverTap.setLocale(finalVariableName); + PluginResult _result = new PluginResult(PluginResult.Status.NO_RESULT); + _result.setKeepCallback(true); + callbackContext.sendPluginResult(_result); + } + }); + return true; + } } result = new PluginResult(PluginResult.Status.ERROR, errorMsg); diff --git a/src/ios/CleverTapPlugin.m b/src/ios/CleverTapPlugin.m index 002efd59..da7fe61a 100644 --- a/src/ios/CleverTapPlugin.m +++ b/src/ios/CleverTapPlugin.m @@ -1636,6 +1636,20 @@ - (void)onPushPermissionResponse:(BOOL)accepted { [self.commandDelegate evalJs:js]; } +#pragma mark - Locale methods + +- (void)setLocale:(CDVInvokedUrlCommand *)command { + if (![[command argumentAtIndex:0] isKindOfClass:[NSString class]]) { + return; + } + + NSString *localeIdentifier = [command argumentAtIndex:0]; + if (localeIdentifier != nil && localeIdentifier.length > 0) { + NSLocale *userLocale = [NSLocale localeWithLocaleIdentifier:localeIdentifier]; + [clevertap setLocale:userLocale]; + } +} + #pragma mark Helper methods - (CTVar *)createVarForName:(NSString *)name andValue:(id)value { diff --git a/www/CleverTap.js b/www/CleverTap.js index c3044139..3270eeb8 100644 --- a/www/CleverTap.js +++ b/www/CleverTap.js @@ -7,7 +7,7 @@ var CleverTap = function () { const libName = 'Cordova'; - const libVersion = 20701; + const libVersion = 20702; cordova.exec(null, null, "CleverTapPlugin", "setLibrary", [libName, libVersion]); } @@ -700,6 +700,12 @@ CleverTap.prototype.isPushPermissionGranted = function(successCallback){ cordova.exec(successCallback, null, "CleverTapPlugin", "isPushPermissionGranted", []); } +// Set Locale +// locale = string +CleverTap.prototype.setLocale = function (locale) { + cordova.exec(null, null, "CleverTapPlugin", "setLocale", [locale]); +} + function convertDateToEpochInProperties(items){ //Conversion of date object in suitable CleverTap format