From 07f69ba5a57ccc7edce8e0f0190897fc7f888265 Mon Sep 17 00:00:00 2001 From: William John Date: Mon, 29 Aug 2022 10:15:10 +0530 Subject: [PATCH 01/58] task-Update targetSDK/compileSDK version, update AGP to 7.2.2, Add POST_NOTIFICATION permission, update targetSDK/compileSDK version for sample app --- buildSrc/src/main/kotlin/Libs.kt | 6 +++--- gradle/wrapper/gradle-wrapper.properties | 8 +++----- sample/build.gradle | 4 ++-- sample/src/main/AndroidManifest.xml | 10 +++++----- 4 files changed, 13 insertions(+), 15 deletions(-) diff --git a/buildSrc/src/main/kotlin/Libs.kt b/buildSrc/src/main/kotlin/Libs.kt index d7e340627..36572e991 100644 --- a/buildSrc/src/main/kotlin/Libs.kt +++ b/buildSrc/src/main/kotlin/Libs.kt @@ -177,9 +177,9 @@ object Libs { object Android { // Android SDK - const val compileSdkVersionVal = 31 - const val targetSdkVersionVal = 31 - const val buildToolsVersionVal = "30.0.3" + const val compileSdkVersionVal = 33 + const val targetSdkVersionVal = 33 + const val buildToolsVersionVal = "33.0.0" const val minSdkVersionVal = 16 } diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 904359a5d..a5d373562 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,8 +1,6 @@ -#Wed Feb 17 20:00:46 IST 2021 +#Thu Aug 25 11:25:05 IST 2022 distributionBase=GRADLE_USER_HOME +distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.3-bin.zip distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-all.zip -#distributionUrl=https\://services.gradle.org/distributions/gradle-7.4-bin.zip -#in version.properties, do : plugin.android=7.4.0-alpha03 +zipStoreBase=GRADLE_USER_HOME diff --git a/sample/build.gradle b/sample/build.gradle index c1f1d46d9..8d20a3bb0 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -11,11 +11,11 @@ allprojects { } android { - compileSdkVersion 31 + compileSdkVersion 33 defaultConfig { applicationId "com.clevertap.demo" minSdkVersion 21 - targetSdkVersion 31 + targetSdkVersion 33 versionCode 10406 versionName "1.4.6-push-plus" multiDexEnabled true diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index b36ae3fef..8847d0928 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -8,6 +8,9 @@ + + + + android:value="TEST-449-68K-8Z6Z" /> - + android:value="TEST-3b6-c44" /> Date: Mon, 29 Aug 2022 10:35:01 +0530 Subject: [PATCH 02/58] chore(SDK-2058)-Update AGP to 7.2.2 --- versions.properties | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/versions.properties b/versions.properties index d386cc537..a55089699 100644 --- a/versions.properties +++ b/versions.properties @@ -7,7 +7,7 @@ #### suppress inspection "SpellCheckingInspection" for whole file #### suppress inspection "UnusedProperty" for whole file -plugin.android=4.2.1 +plugin.android=7.2.2 ## # available=4.2.2 ## # available=7.0.0-alpha01 ## # available=7.0.0-alpha02 From cd5102be80995a110ec861feeb0d9f6689c6c9f8 Mon Sep 17 00:00:00 2001 From: William John Date: Mon, 5 Sep 2022 18:13:55 +0530 Subject: [PATCH 03/58] task(SDK-2093,2094,2095)-Create a builder pattern to render local in-app(half-interstitial, alert type) --- clevertap-core/src/main/AndroidManifest.xml | 3 + .../clevertap/android/sdk/CTWebInterface.java | 3 + .../clevertap/android/sdk/CleverTapAPI.java | 18 +++ .../com/clevertap/android/sdk/Constants.java | 2 + .../sdk/inapp/CTInAppBaseFragment.java | 3 + .../sdk/inapp/CTInAppNotification.java | 41 +++++++ .../sdk/inapp/CTInAppNotificationButton.java | 11 ++ .../sdk/inapp/CTLocalInAppSettings.java | 106 ++++++++++++++++++ .../android/sdk/inapp/InAppController.java | 36 +++++- 9 files changed, 220 insertions(+), 3 deletions(-) create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java diff --git a/clevertap-core/src/main/AndroidManifest.xml b/clevertap-core/src/main/AndroidManifest.xml index e32b0c7f8..dbd82138a 100644 --- a/clevertap-core/src/main/AndroidManifest.xml +++ b/clevertap-core/src/main/AndroidManifest.xml @@ -2,6 +2,9 @@ + + + (instance); } + + //Handle push primer click and directly call requestPermissions() inside InAppActivity + /** * Method to be called from WebView Javascript to add profile properties in CleverTap * diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index e85643489..63e6b8a48 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -31,6 +31,7 @@ import com.clevertap.android.sdk.events.EventDetail; import com.clevertap.android.sdk.events.EventGroup; import com.clevertap.android.sdk.featureFlags.CTFeatureFlagsController; +import com.clevertap.android.sdk.inapp.CTLocalInAppSettings; import com.clevertap.android.sdk.inbox.CTInboxActivity; import com.clevertap.android.sdk.inbox.CTInboxMessage; import com.clevertap.android.sdk.inbox.CTMessageDAO; @@ -1029,6 +1030,23 @@ public static void tokenRefresh(Context context, String token, PushType pushType } } + public void promptPushPrimer(CTLocalInAppSettings builder){ + if (instances == null) { + return; + } + + for (String accountId : CleverTapAPI.instances.keySet()) { + CleverTapAPI instance = CleverTapAPI.instances.get(accountId); + try { + if (instance != null) { + instance.coreState.getInAppController().promptPushPrimer(builder); + } + } catch (Throwable t) { + // Ignore + } + } + } + // Initialize private CleverTapAPI(final Context context, final CleverTapInstanceConfig config, String cleverTapID) { this.context = context; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/Constants.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/Constants.java index 0d0b1128f..db30dfc2f 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/Constants.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/Constants.java @@ -215,6 +215,8 @@ public interface Constants { String BLACK = "#000000"; String WHITE = "#FFFFFF"; String BLUE = "#0000FF"; + String GREEN = "#00FF00"; + String LIGHT_BLUE = "#818ce5"; /** * Profile command constants. */ diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java index 519dda36d..daa65b920 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java @@ -140,6 +140,9 @@ void handleButtonClickAtIndex(int index) { didClick(data, button.getKeyValues()); +// check API and toolsSDK version, inapp type, whether the btn was meant for PN. +// requestPermissions() + String actionUrl = button.getActionUrl(); if (actionUrl != null) { fireUrlThroughIntent(actionUrl, data); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index 17a9dddb4..ed65f52a7 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -572,6 +572,47 @@ void prepareForDisplay() { listener.notificationReady(this); } + public CTInAppNotification configureWithLocalData(CTLocalInAppSettings ctLocalInAppSettings){ + this.id = "";// + this.campaignId = "";// + this.type = ctLocalInAppSettings.getInAppAlertType();//alert-template + this.excludeFromCaps = false;// + this.totalLifetimeCount = -1;// + this.totalDailyCount = -1;// + this.inAppType = CTInAppType.fromString(this.type); + this.isTablet = false;// + this.backgroundColor = Constants.WHITE; + this.isPortrait = true;// + this.isLandscape = true;// + this.timeToLive = System.currentTimeMillis() + 2 * Constants.ONE_DAY_IN_MILLIS; + + + this.title = ctLocalInAppSettings.getTitleText(); + this.titleColor = Constants.BLACK; + + this.message = ctLocalInAppSettings.getBodyText(); + this.messageColor = Constants.BLACK; + + this.hideCloseButton = true; + + //CTINAPPNOTIFMedia obj + + //Positive Button + CTInAppNotificationButton inAppNotificationPositiveButton = new CTInAppNotificationButton() + .initWithLocalData(ctLocalInAppSettings.getPositiveConfirmationBtnText(),ctLocalInAppSettings.getPositiveConfirmationBtnColor()); + if (inAppNotificationPositiveButton != null) { + this.buttons.add(inAppNotificationPositiveButton); + } + + //Negative Button + CTInAppNotificationButton inAppNotificationNegativeButton = new CTInAppNotificationButton() + .initWithLocalData(ctLocalInAppSettings.getNegativeConfirmationBtnText(),ctLocalInAppSettings.getPositiveConfirmationBtnColor()); + if (inAppNotificationNegativeButton != null) { + this.buttons.add(inAppNotificationNegativeButton); + } + return this; + } + private void configureWithJson(JSONObject jsonObject) { try { this.id = jsonObject.has(Constants.INAPP_ID_IN_PAYLOAD) ? jsonObject diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java index 58276dfb0..78240d321 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java @@ -213,6 +213,17 @@ CTInAppNotificationButton initWithJSON(JSONObject jsonObject) { return this; } + CTInAppNotificationButton initWithLocalData(String text, String btnBackgroundColor) { + this.text = text; + this.textColor = Constants.WHITE; + this.backgroundColor = btnBackgroundColor.isEmpty() ? btnBackgroundColor + : Constants.LIGHT_BLUE; + this.borderColor = Constants.GREEN; + this.borderRadius = "4";//From sample payload + + return this; + } + /** * Checks if custom Key Value pair is present or not * diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java new file mode 100644 index 000000000..fa6c74d4f --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java @@ -0,0 +1,106 @@ +package com.clevertap.android.sdk.inapp; + +import java.util.Objects; + +public class CTLocalInAppSettings { + + + public static final class Builder { + private String inAppAlertType; + private String titleText; + private String bodyText; + private String positiveConfirmationBtnText; + private String negativeConfirmationBtnText; + private String positiveConfirmationBtnColor; + + public Builder() { + } + + public CTLocalInAppSettings build(){ + return new CTLocalInAppSettings(this); + } + + public CTLocalInAppSettings.Builder setInAppAlertType(String inAppAlertType) { + this.inAppAlertType = inAppAlertType; + return this; + } + + public CTLocalInAppSettings.Builder setTitleText(String titleText){ + this.titleText = titleText; + return this; + } + + public CTLocalInAppSettings.Builder setBodyText(String bodyText){ + this.bodyText = bodyText; + return this; + } + + public CTLocalInAppSettings.Builder setPositiveConfirmationBtnText(String positiveConfirmationBtnText){ + this.positiveConfirmationBtnText = positiveConfirmationBtnText; + return this; + } + + public CTLocalInAppSettings.Builder setNegativeConfirmationBtnText(String negativeConfirmationBtnText){ + this.negativeConfirmationBtnText = negativeConfirmationBtnText; + return this; + } + + public CTLocalInAppSettings.Builder setPositiveConfirmationBtnColor(String positiveConfirmationBtnColor){ + this.positiveConfirmationBtnColor = positiveConfirmationBtnColor; + return this; + } + } + + private final String inAppAlertType; + private final String titleText; + private final String bodyText; + private final String positiveConfirmationBtnText; + private final String negativeConfirmationBtnText; + private final String positiveConfirmationBtnColor; + + private CTLocalInAppSettings(Builder builder) { + inAppAlertType = builder.inAppAlertType; + titleText = builder.titleText; + bodyText = builder.bodyText; + positiveConfirmationBtnText = builder.positiveConfirmationBtnText; + negativeConfirmationBtnText = builder.negativeConfirmationBtnText; + positiveConfirmationBtnColor = builder.positiveConfirmationBtnColor; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CTLocalInAppSettings that = (CTLocalInAppSettings) o; + return Objects.equals(inAppAlertType, that.inAppAlertType) && Objects.equals(titleText, that.titleText) && Objects.equals(bodyText, that.bodyText) && Objects.equals(positiveConfirmationBtnText, that.positiveConfirmationBtnText) && Objects.equals(negativeConfirmationBtnText, that.negativeConfirmationBtnText) && Objects.equals(positiveConfirmationBtnColor, that.positiveConfirmationBtnColor); + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + public String getInAppAlertType() { + return inAppAlertType; + } + + public String getTitleText() { + return titleText; + } + + public String getBodyText() { + return bodyText; + } + + public String getPositiveConfirmationBtnText() { + return positiveConfirmationBtnText; + } + + public String getNegativeConfirmationBtnText() { + return negativeConfirmationBtnText; + } + + public String getPositiveConfirmationBtnColor() { + return positiveConfirmationBtnColor; + } +} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index c0a1e7928..4e6f6b805 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -42,7 +42,9 @@ private final class NotificationPrepareRunnable implements Runnable { private final WeakReference inAppControllerWeakReference; - private final JSONObject jsonObject; + private JSONObject jsonObject; + + private CTLocalInAppSettings ctLocalInAppSettings; private final boolean videoSupport = Utils.haveVideoPlayerSupport; @@ -51,10 +53,22 @@ private final class NotificationPrepareRunnable implements Runnable { this.jsonObject = jsonObject; } + NotificationPrepareRunnable(InAppController inAppController, CTLocalInAppSettings ctLocalInAppSettings) { + this.inAppControllerWeakReference = new WeakReference<>(inAppController); + this.ctLocalInAppSettings = ctLocalInAppSettings; + } + @Override public void run() { - final CTInAppNotification inAppNotification = new CTInAppNotification() - .initWithJSON(jsonObject, videoSupport); + final CTInAppNotification inAppNotification; + if (jsonObject != null) {//If jsonObj is available then render in-app via JSON + inAppNotification = new CTInAppNotification() + .initWithJSON(jsonObject, videoSupport); + }else {//render in-app via local in-app builder + inAppNotification = new CTInAppNotification() + .configureWithLocalData(ctLocalInAppSettings); + } + if (inAppNotification.getError() != null) { logger .debug(config.getAccountId(), @@ -167,6 +181,10 @@ public void checkPendingInAppNotifications(Activity activity) { } } + public void promptPushPrimer(CTLocalInAppSettings ctLocalInAppSettings) {//Change method name here to avoid confusion + prepareNotificationForDisplay(ctLocalInAppSettings); + } + public void discardInApps() { this.inAppState = InAppState.DISCARDED; logger.verbose(config.getAccountId(), "InAppState is DISCARDED"); @@ -418,6 +436,18 @@ public Void call() { }); } + private void prepareNotificationForDisplay(final CTLocalInAppSettings ctLocalInAppSettings) { + logger.debug(config.getAccountId(), "Preparing local In-App using CTLocalInAppSettings for display");//Need correct error mssg + Task task = CTExecutorFactory.executors(config).postAsyncSafelyTask(Constants.TAG_FEATURE_IN_APPS); + task.execute("InappController#prepareNotificationForDisplay", new Callable() { + @Override + public Void call() { + new NotificationPrepareRunnable(InAppController.this, ctLocalInAppSettings).run(); + return null; + } + }); + } + private void showInAppNotificationIfAny() { if (!config.isAnalyticsOnly()) { Task task = CTExecutorFactory.executors(config).postAsyncSafelyTask(Constants.TAG_FEATURE_IN_APPS); From 02136212e699aa5c39607060c209daa7ec6eb2e7 Mon Sep 17 00:00:00 2001 From: William John Date: Mon, 5 Sep 2022 18:15:25 +0530 Subject: [PATCH 04/58] task(SDK-2093,2094,2095)-Update sample to show local IAM(half-interstitial & alter type) --- sample/src/main/AndroidManifest.xml | 3 --- .../clevertap/demo/ui/main/HomeScreenModel.kt | 4 ++++ .../demo/ui/main/HomeScreenViewModel.kt | 24 +++++++++++++++++-- 3 files changed, 26 insertions(+), 5 deletions(-) diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 8847d0928..8a3c6084d 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -8,9 +8,6 @@ - - - cleverTapAPI?.pushEvent("Send Input Box Reminder DOC true") "918"-> cleverTapAPI?.pushEvent("Send Input Box Reminder DOC false") "919"-> cleverTapAPI?.pushEvent("Send Three CTA Notification") + "100"-> { + val builder = CTLocalInAppSettings.Builder().setTitleText("Get Notified") + .setInAppAlertType("half-interstitial") + .setBodyText("Please enable notifications on your device to use Push Notifications.") + .setPositiveConfirmationBtnText("Allow") + .setNegativeConfirmationBtnText("Cancel") + .setPositiveConfirmationBtnColor(Constants.LIGHT_BLUE).build()//Add image,inapp type + cleverTapAPI?.promptPushPrimer(builder) + } + + "101"->{ + val builder = CTLocalInAppSettings.Builder().setTitleText("Get Notified") + .setInAppAlertType("alert-template") + .setBodyText("Please enable notifications on your device to use Push Notifications.") + .setPositiveConfirmationBtnText("Allow") + .setNegativeConfirmationBtnText("Cancel") + .setPositiveConfirmationBtnColor(Constants.LIGHT_BLUE).build()//Add image,inapp type + cleverTapAPI?.promptPushPrimer(builder) + } //"60" -> webViewClickListener?.onWebViewClick() From 87b1c5c91a52961bf77e363070f3cb93cc7e0a70 Mon Sep 17 00:00:00 2001 From: William John Date: Thu, 8 Sep 2022 11:12:05 +0530 Subject: [PATCH 05/58] task(SDK-2127)-Add alert dialog for opt-in nudge if permission is denied --- .../sdk/InAppNotificationActivity.java | 75 ++++++++++++++++++- .../java/com/clevertap/android/sdk/Utils.java | 18 +++++ .../sdk/inapp/AlertDialogPromptForSettings.kt | 33 ++++++++ .../sdk/inapp/CTInAppBaseFragment.java | 15 ++-- .../sdk/inapp/CTInAppNotification.java | 9 +++ ...vigateToAndroidSettingsForNotifications.kt | 20 +++++ .../src/main/res/values/strings.xml | 10 +++ 7 files changed, 174 insertions(+), 6 deletions(-) create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt create mode 100644 clevertap-core/src/main/res/values/strings.xml diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index e8faae6d7..f132e96cf 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -1,14 +1,23 @@ package com.clevertap.android.sdk; +import static com.clevertap.android.sdk.Utils.isAndroid13; + import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; import android.content.Intent; +import android.content.pm.PackageManager; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.view.WindowManager; +import android.widget.Toast; + +import androidx.annotation.NonNull; +import androidx.core.app.ActivityCompat; import androidx.fragment.app.FragmentActivity; + +import com.clevertap.android.sdk.inapp.AlertDialogPromptForSettings; import com.clevertap.android.sdk.inapp.CTInAppBaseFullFragment; import com.clevertap.android.sdk.inapp.CTInAppHtmlCoverFragment; import com.clevertap.android.sdk.inapp.CTInAppHtmlHalfInterstitialFragment; @@ -22,6 +31,8 @@ import com.clevertap.android.sdk.inapp.CTInAppNotification; import com.clevertap.android.sdk.inapp.CTInAppType; import com.clevertap.android.sdk.inapp.InAppListener; +import com.clevertap.android.sdk.inapp.NavigateToAndroidSettingsForNotifications; + import java.lang.ref.WeakReference; import java.util.HashMap; @@ -35,6 +46,13 @@ public final class InAppNotificationActivity extends FragmentActivity implements private WeakReference listenerWeakReference; + private static boolean neverAskAgainClicked; + + private static final int PERMISSION_REQUEST_CODE = 2; + + private static final String ANDROID_PERMISSION_STRING = "android.permission.POST_NOTIFICATIONS"; + + public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); int orientation = this.getResources().getConfiguration().orientation; @@ -146,6 +164,56 @@ void didClick(Bundle data, HashMap keyValueMap) { } } + public void prompt(){ + if (isAndroid13(InAppNotificationActivity.this)){ + requestPermission(); + } + } + + public void requestPermission() { + neverAskAgainClicked = !ActivityCompat.shouldShowRequestPermissionRationale( + InAppNotificationActivity.this, ANDROID_PERMISSION_STRING); + + if (neverAskAgainClicked) { + ActivityCompat.requestPermissions(this, + new String[]{ANDROID_PERMISSION_STRING}, PERMISSION_REQUEST_CODE); + }else{ + showFallbackAlertDialog(); + } + } + + @Override + public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { + super.onRequestPermissionsResult(requestCode, permissions, grantResults); + if (requestCode == PERMISSION_REQUEST_CODE) { + boolean granted = grantResults.length > 0 && grantResults[0] == + PackageManager.PERMISSION_GRANTED; + if (granted) { +// callback.onAccept();//Give callback when permission is granted + Toast.makeText(InAppNotificationActivity.this, + "Notification Permission is granted", Toast.LENGTH_SHORT).show(); + }else { +// callback.onReject(shouldShowSettings());//Give callback when permission is rejected + } + didDismiss(null); + } + } + + public void showFallbackAlertDialog() { + AlertDialogPromptForSettings.INSTANCE.show(this, new AlertDialogPromptForSettings.Callback() { + @Override + public void onAccept() { + NavigateToAndroidSettingsForNotifications.INSTANCE.show(getBaseContext()); + didDismiss(null); + } + + @Override + public void onDecline() { + didDismiss(null); + } + }); + } + void didDismiss(Bundle data) { if (isAlertVisible) { isAlertVisible = false; @@ -257,7 +325,11 @@ public void onClick(DialogInterface dialogInterface, int i) { fireUrlThroughIntent(actionUrl, data); return; } - didDismiss(data); + if (inAppNotification.isLocalInApp()) { + prompt(); + }else { + didDismiss(data); + } } }) .create(); @@ -304,6 +376,7 @@ public void onClick(DialogInterface dialogInterface, int i) { return; } didDismiss(data); + } }).create(); if (inAppNotification.getButtons().size() == 2) { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java index c55015013..c93226273 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java @@ -9,6 +9,7 @@ import android.app.ActivityManager.RunningAppProcessInfo; import android.content.Context; import android.content.Intent; +import android.content.pm.ApplicationInfo; import android.content.pm.PackageInfo; import android.content.pm.PackageManager; import android.content.pm.ResolveInfo; @@ -662,6 +663,23 @@ public static boolean isRenderFallback(RemoteMessage remoteMessage, Context cont } + public static boolean isAndroid13(Context context){ + return Build.VERSION.SDK_INT > 32 && getTargetSdkVersion(context) > 32; + } + + public static int getTargetSdkVersion(Context context) { + String packageName = context.getPackageName(); + PackageManager packageManager = context.getPackageManager(); + try { + ApplicationInfo applicationInfo = packageManager.getApplicationInfo(packageName, 0); + return applicationInfo.targetSdkVersion; + } catch (PackageManager.NameNotFoundException e) { + e.printStackTrace(); + } + + return Build.VERSION_CODES.JELLY_BEAN; + } + static { haveVideoPlayerSupport = checkForExoPlayer(); } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt new file mode 100644 index 000000000..12f8d452f --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt @@ -0,0 +1,33 @@ +package com.clevertap.android.sdk.inapp + +import android.app.Activity +import android.app.AlertDialog +import com.clevertap.android.sdk.R + +object AlertDialogPromptForSettings { + + interface Callback { + fun onAccept() + fun onDecline() + } + + fun show( + activity: Activity, + callback: Callback, + ) { + val title = activity.getString(R.string.permission_not_available_title) + + val message = activity.getString(R.string.permission_not_available_message) + + AlertDialog.Builder(activity) + .setTitle(title) + .setMessage(message) + .setPositiveButton(R.string.permission_not_available_open_settings_option) { dialog, which -> + callback.onAccept() + } + .setNegativeButton(android.R.string.no) { dialog, which -> + callback.onDecline() + } + .show() + } +} \ No newline at end of file diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java index daa65b920..fbe0b91ef 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java @@ -10,6 +10,7 @@ import androidx.fragment.app.Fragment; import com.clevertap.android.sdk.CleverTapInstanceConfig; import com.clevertap.android.sdk.Constants; +import com.clevertap.android.sdk.InAppNotificationActivity; import com.clevertap.android.sdk.Utils; import com.clevertap.android.sdk.customviews.CloseImageView; import java.lang.ref.WeakReference; @@ -143,12 +144,16 @@ void handleButtonClickAtIndex(int index) { // check API and toolsSDK version, inapp type, whether the btn was meant for PN. // requestPermissions() - String actionUrl = button.getActionUrl(); - if (actionUrl != null) { - fireUrlThroughIntent(actionUrl, data); - return; + if (index == 0 && inAppNotification.isLocalInApp()) { + ((InAppNotificationActivity) context).prompt(); + }else { + String actionUrl = button.getActionUrl(); + if (actionUrl != null) { + fireUrlThroughIntent(actionUrl, data); + return; + } + didDismiss(data); } - didDismiss(data); } catch (Throwable t) { config.getLogger().debug("Error handling notification button click: " + t.getCause()); didDismiss(null); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index ed65f52a7..33ea24de2 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -220,6 +220,8 @@ public CTInAppNotification[] newArray(int size) { private int widthPercentage; + private boolean isLocalInApp = false; + CTInAppNotification() { } @@ -267,6 +269,7 @@ private CTInAppNotification(Parcel in) { jsEnabled = in.readByte() != 0x00; isPortrait = in.readByte() != 0x00; isLandscape = in.readByte() != 0x00; + isLocalInApp = in.readByte() != 0x00; landscapeImageUrl = in.readString(); _landscapeImageCacheKey = in.readString(); timeToLive = in.readLong(); @@ -354,6 +357,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeByte((byte) (jsEnabled ? 0x01 : 0x00)); dest.writeByte((byte) (isPortrait ? 0x01 : 0x00)); dest.writeByte((byte) (isLandscape ? 0x01 : 0x00)); + dest.writeByte((byte) (isLocalInApp ? 0x01 : 0x00)); dest.writeString(landscapeImageUrl); dest.writeString(_landscapeImageCacheKey); dest.writeLong(timeToLive); @@ -391,6 +395,10 @@ String getError() { return error; } + public boolean isLocalInApp() { + return isLocalInApp; + } + byte[] getGifByteArray(CTInAppNotificationMedia inAppMedia) { return GifCache.getByteArray(inAppMedia.getCacheKey()); } @@ -584,6 +592,7 @@ public CTInAppNotification configureWithLocalData(CTLocalInAppSettings ctLocalIn this.backgroundColor = Constants.WHITE; this.isPortrait = true;// this.isLandscape = true;// + this.isLocalInApp = true; this.timeToLive = System.currentTimeMillis() + 2 * Constants.ONE_DAY_IN_MILLIS; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt new file mode 100644 index 000000000..8d3ee4e94 --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt @@ -0,0 +1,20 @@ +package com.clevertap.android.sdk.inapp + +import android.content.Context +import android.content.Intent + +object NavigateToAndroidSettingsForNotifications { + fun show(context: Context) { + val intent = Intent() + intent.action = "android.settings.APP_NOTIFICATION_SETTINGS" + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) + + //for Android 5-7 + intent.putExtra("app_package", context.getPackageName()) + intent.putExtra("app_uid", context.getApplicationInfo().uid) + + // for Android 8 and above + intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName()) + context.startActivity(intent) + } +} \ No newline at end of file diff --git a/clevertap-core/src/main/res/values/strings.xml b/clevertap-core/src/main/res/values/strings.xml new file mode 100644 index 000000000..88d2ad319 --- /dev/null +++ b/clevertap-core/src/main/res/values/strings.xml @@ -0,0 +1,10 @@ + + + + Permission Not Available + You have previously denied notification permission. Please go to settings to enable notifications. + Settings + + Notifications + Notifications + From 40be5c7958c521a3220fee14fac4303126dca800 Mon Sep 17 00:00:00 2001 From: William John Date: Mon, 12 Sep 2022 19:19:54 +0530 Subject: [PATCH 06/58] task(SDK-2154)-Add callbacks for soft/hard dialogs --- .../android/sdk/BaseCallbackManager.java | 4 +++ .../android/sdk/CallbackManager.java | 12 +++++++ .../clevertap/android/sdk/CleverTapAPI.java | 22 +++++++++++-- .../sdk/InAppNotificationActivity.java | 21 ++++++++---- .../sdk/InAppNotificationListener.java | 11 +++++++ ...ermissionNotificationResponseListener.java | 15 +++++++++ .../android/sdk/inapp/InAppController.java | 31 ++++++++++++++++- .../com/clevertap/demo/HomeScreenActivity.kt | 33 ++++++++++++++++--- 8 files changed, 135 insertions(+), 14 deletions(-) create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionNotificationResponseListener.java diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java index 689165295..8b7c5abf3 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java @@ -28,6 +28,8 @@ public abstract class BaseCallbackManager { public abstract InAppNotificationListener getInAppNotificationListener(); + public abstract PushPermissionNotificationResponseListener getPushPermissionNotificationResponseListener(); + public abstract CTInboxListener getInboxListener(); public abstract CTProductConfigListener getProductConfigListener(); @@ -60,6 +62,8 @@ public abstract void setInAppNotificationButtonListener( public abstract void setInAppNotificationListener(InAppNotificationListener inAppNotificationListener); + public abstract void setPushPermissionNotificationResponseListener(PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener); + public abstract void setInboxListener(CTInboxListener inboxListener); public abstract void setProductConfigListener( diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java index 9fbe514fe..b3ecedf52 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java @@ -28,6 +28,8 @@ public class CallbackManager extends BaseCallbackManager { private InAppNotificationListener inAppNotificationListener; + private PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener; + private CTInboxListener inboxListener; private final CleverTapInstanceConfig config; @@ -131,11 +133,21 @@ public InAppNotificationListener getInAppNotificationListener() { return inAppNotificationListener; } + @Override + public PushPermissionNotificationResponseListener getPushPermissionNotificationResponseListener() { + return pushPermissionNotificationResponseListener; + } + @Override public void setInAppNotificationListener(final InAppNotificationListener inAppNotificationListener) { this.inAppNotificationListener = inAppNotificationListener; } + @Override + public void setPushPermissionNotificationResponseListener(PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener) { + this.pushPermissionNotificationResponseListener = pushPermissionNotificationResponseListener; + } + @Override public CTInboxListener getInboxListener() { return inboxListener; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index 63e6b8a48..16e7dc554 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -1597,8 +1597,6 @@ public Map getHistory() { return coreState.getLocalDataStore().getEventHistory(context); } - //DeepLink - /** * Returns the InAppNotificationListener object * @@ -1619,6 +1617,26 @@ public void setInAppNotificationListener(InAppNotificationListener inAppNotifica coreState.getCallbackManager().setInAppNotificationListener(inAppNotificationListener); } + /** + * Returns the PushPermissionNotificationResponseListener object + * + * @return An {@link PushPermissionNotificationResponseListener} object + */ + @SuppressWarnings({"unused", "WeakerAccess"}) + public PushPermissionNotificationResponseListener getPushPermissionNotificationResponseListener() { + return coreState.getCallbackManager().getPushPermissionNotificationResponseListener(); + } + + /** + * This method sets the PushPermissionNotificationResponseListener + * + * @param pushPermissionNotificationResponseListener An {@link PushPermissionNotificationResponseListener} object + */ + @SuppressWarnings({"unused"}) + public void setPushPermissionNotificationResponseListener(PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener) { + coreState.getCallbackManager().setPushPermissionNotificationResponseListener(pushPermissionNotificationResponseListener); + } + /** * Returns the count of all inbox messages for the user * diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index f132e96cf..826844736 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -46,12 +46,16 @@ public final class InAppNotificationActivity extends FragmentActivity implements private WeakReference listenerWeakReference; - private static boolean neverAskAgainClicked; + private WeakReference permissionCallbackWeakReference; private static final int PERMISSION_REQUEST_CODE = 2; private static final String ANDROID_PERMISSION_STRING = "android.permission.POST_NOTIFICATIONS"; + public interface PermissionCallback { + void onAccept(); + void onReject(); + } public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); @@ -70,6 +74,8 @@ public void onCreate(Bundle savedInstanceState) { config = configBundle.getParcelable("config"); } setListener(CleverTapAPI.instanceWithConfig(this, config).getCoreState().getInAppController()); + + setPermissionCallback(CleverTapAPI.instanceWithConfig(this, config).getCoreState().getInAppController()); } catch (Throwable t) { Logger.v("Cannot find a valid notification bundle to show!", t); finish(); @@ -171,13 +177,14 @@ public void prompt(){ } public void requestPermission() { - neverAskAgainClicked = !ActivityCompat.shouldShowRequestPermissionRationale( + boolean neverAskAgainClicked = !ActivityCompat.shouldShowRequestPermissionRationale( InAppNotificationActivity.this, ANDROID_PERMISSION_STRING); if (neverAskAgainClicked) { ActivityCompat.requestPermissions(this, new String[]{ANDROID_PERMISSION_STRING}, PERMISSION_REQUEST_CODE); }else{ + permissionCallbackWeakReference.get().onReject(); showFallbackAlertDialog(); } } @@ -189,11 +196,9 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; if (granted) { -// callback.onAccept();//Give callback when permission is granted - Toast.makeText(InAppNotificationActivity.this, - "Notification Permission is granted", Toast.LENGTH_SHORT).show(); + permissionCallbackWeakReference.get().onAccept(); }else { -// callback.onReject(shouldShowSettings());//Give callback when permission is rejected + permissionCallbackWeakReference.get().onReject(); } didDismiss(null); } @@ -260,6 +265,10 @@ void setListener(InAppListener listener) { listenerWeakReference = new WeakReference<>(listener); } + public void setPermissionCallback(PermissionCallback callback){ + permissionCallbackWeakReference = new WeakReference<>(callback); + } + private CTInAppBaseFullFragment createContentFragment() { CTInAppType type = inAppNotification.getInAppType(); CTInAppBaseFullFragment viewFragment = null; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationListener.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationListener.java index fffc08d47..d912e8545 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationListener.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationListener.java @@ -1,6 +1,9 @@ package com.clevertap.android.sdk; import androidx.annotation.Nullable; + +import com.clevertap.android.sdk.inapp.CTInAppNotification; + import java.util.Map; /** @@ -19,6 +22,14 @@ public interface InAppNotificationListener { */ boolean beforeShow(Map extras); + /** + * This is called when an in-app notification is rendered. + * + * @param ctInAppNotification The CTInAppNotification object for this notification. + * {@link CTInAppNotification} object + */ + void onShow(CTInAppNotification ctInAppNotification); + /** * When an in-app notification is dismissed (either by the close button, or a call to action), * this method will be called. diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionNotificationResponseListener.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionNotificationResponseListener.java new file mode 100644 index 000000000..fe5340546 --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionNotificationResponseListener.java @@ -0,0 +1,15 @@ +package com.clevertap.android.sdk; + +/** + * A listener for notification permission. + */ +public interface PushPermissionNotificationResponseListener { + + /** + * This is called when user either grants allow/dismiss permission for notifications for Android 13+ + * + * @param accepted This boolean will return true if notification permission is granted and will retrun + * false if permission is denied. + */ + void response(boolean accepted);//Change method name here, sounds ambiguous +} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 4e6f6b805..5f376f498 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -19,6 +19,7 @@ import com.clevertap.android.sdk.InAppNotificationListener; import com.clevertap.android.sdk.Logger; import com.clevertap.android.sdk.ManifestInfo; +import com.clevertap.android.sdk.PushPermissionNotificationResponseListener; import com.clevertap.android.sdk.StorageHelper; import com.clevertap.android.sdk.Utils; import com.clevertap.android.sdk.task.CTExecutorFactory; @@ -35,7 +36,25 @@ import org.json.JSONArray; import org.json.JSONObject; -public class InAppController implements CTInAppNotification.CTInAppNotificationListener, InAppListener { +public class InAppController implements CTInAppNotification.CTInAppNotificationListener, InAppListener, InAppNotificationActivity.PermissionCallback { + + @Override + public void onAccept() { + Logger.i("OnAccept called"); + final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); + if (listener != null){ + listener.response(true); + } + } + + @Override + public void onReject() { + Logger.i("onReject Called"); + final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); + if (listener != null){ + listener.response(false); + } + } //InApp private final class NotificationPrepareRunnable implements Runnable { @@ -251,6 +270,16 @@ public Void call() { @Override public void inAppNotificationDidShow(CTInAppNotification inAppNotification, Bundle formData) { analyticsManager.pushInAppNotificationStateEvent(false, inAppNotification, formData); + + //Fire onShow() callback when InApp is shown. + try { + final InAppNotificationListener listener = callbackManager.getInAppNotificationListener(); + if (listener != null) { + listener.onShow(inAppNotification); + } + } catch (Throwable t) { + Logger.v(config.getAccountId(), "Failed to call the in-app notification listener", t); + } } //InApp diff --git a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt index 27d17eab2..4e80a002a 100644 --- a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt +++ b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt @@ -10,13 +10,11 @@ import android.os.Bundle import android.util.Log import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.commitNow -import com.clevertap.android.sdk.CTFeatureFlagsListener -import com.clevertap.android.sdk.CTInboxListener -import com.clevertap.android.sdk.CleverTapAPI +import com.clevertap.android.sdk.* import com.clevertap.android.sdk.CleverTapAPI.LogLevel.VERBOSE -import com.clevertap.android.sdk.SyncListener import com.clevertap.android.sdk.displayunits.DisplayUnitListener import com.clevertap.android.sdk.displayunits.model.CleverTapDisplayUnit +import com.clevertap.android.sdk.inapp.CTInAppNotification import com.clevertap.android.sdk.product_config.CTProductConfigListener import com.clevertap.demo.ui.main.HomeScreenFragment @@ -31,7 +29,7 @@ import org.json.JSONObject private const val TAG = "HomeScreenActivity" class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitListener, CTProductConfigListener, - CTFeatureFlagsListener, SyncListener { + CTFeatureFlagsListener, SyncListener, InAppNotificationListener, PushPermissionNotificationResponseListener { var cleverTapDefaultInstance: CleverTapAPI? = null @@ -142,6 +140,11 @@ class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitList setCTFeatureFlagsListener(this@HomeScreenActivity) //Initialize the inbox and wait for callbacks on overridden methods initializeInbox() + + inAppNotificationListener = this@HomeScreenActivity + + pushPermissionNotificationResponseListener = this@HomeScreenActivity + } //With CleverTap Android SDK v3.2.0 you can create additional instances to send data to multiple CleverTap accounts @@ -234,4 +237,24 @@ class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitList // Show Dialog mDialog.show() } + + override fun beforeShow(extras: MutableMap?): Boolean { + Log.i(TAG, "InApp---> beforeShow() called") + return true + } + + override fun onShow(ctInAppNotification: CTInAppNotification?) { + Log.i(TAG, "InApp---> onShow() called") + } + + override fun onDismissed( + extras: MutableMap?, + actionExtras: MutableMap? + ) { + Log.i(TAG, "InApp---> onDismissed() called") + } + + override fun response(accepted: Boolean) { + Log.i(TAG, "InApp---> response() called $accepted") + } } \ No newline at end of file From 6ec0e4e463e8701e77ffbe6359992e2ccc902350 Mon Sep 17 00:00:00 2001 From: William John Date: Mon, 12 Sep 2022 20:42:04 +0530 Subject: [PATCH 07/58] chore(SDK-2154)-Refactor InAppController.java --- .../sdk/inapp/CTLocalInAppSettings.java | 6 ++- .../android/sdk/inapp/InAppController.java | 37 +++++++++---------- 2 files changed, 23 insertions(+), 20 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java index fa6c74d4f..17b2f7cef 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java @@ -72,7 +72,11 @@ public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; CTLocalInAppSettings that = (CTLocalInAppSettings) o; - return Objects.equals(inAppAlertType, that.inAppAlertType) && Objects.equals(titleText, that.titleText) && Objects.equals(bodyText, that.bodyText) && Objects.equals(positiveConfirmationBtnText, that.positiveConfirmationBtnText) && Objects.equals(negativeConfirmationBtnText, that.negativeConfirmationBtnText) && Objects.equals(positiveConfirmationBtnColor, that.positiveConfirmationBtnColor); + return Objects.equals(inAppAlertType, that.inAppAlertType) && Objects.equals(titleText, that.titleText) + && Objects.equals(bodyText, that.bodyText) && + Objects.equals(positiveConfirmationBtnText, that.positiveConfirmationBtnText) + && Objects.equals(negativeConfirmationBtnText, that.negativeConfirmationBtnText) + && Objects.equals(positiveConfirmationBtnColor, that.positiveConfirmationBtnColor); } @Override diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 5f376f498..f9afe7067 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -36,25 +36,8 @@ import org.json.JSONArray; import org.json.JSONObject; -public class InAppController implements CTInAppNotification.CTInAppNotificationListener, InAppListener, InAppNotificationActivity.PermissionCallback { - - @Override - public void onAccept() { - Logger.i("OnAccept called"); - final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); - if (listener != null){ - listener.response(true); - } - } - - @Override - public void onReject() { - Logger.i("onReject Called"); - final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); - if (listener != null){ - listener.response(false); - } - } +public class InAppController implements CTInAppNotification.CTInAppNotificationListener, InAppListener, + InAppNotificationActivity.PermissionCallback { //InApp private final class NotificationPrepareRunnable implements Runnable { @@ -305,6 +288,22 @@ public void run() { displayNotification(inAppNotification); } + @Override + public void onAccept() { + final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); + if (listener != null){ + listener.response(true); + } + } + + @Override + public void onReject() { + final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); + if (listener != null){ + listener.response(false); + } + } + public void resumeInApps() { this.inAppState = InAppState.RESUMED; logger.verbose(config.getAccountId(), "InAppState is RESUMED"); From 31c2e29fe3bfb547654375140b40593927f11db4 Mon Sep 17 00:00:00 2001 From: William John Date: Tue, 13 Sep 2022 19:18:56 +0530 Subject: [PATCH 08/58] task(SDK-2154)-Add `requestPermission()` flow from InAppController.java to directly call hard permission request dialog --- .../clevertap/android/sdk/CleverTapAPI.java | 17 +++++++++++++++ .../sdk/InAppNotificationActivity.java | 21 +++++++++++++++++-- .../android/sdk/inapp/InAppController.java | 6 ++++++ .../clevertap/demo/ui/main/HomeScreenModel.kt | 3 ++- .../demo/ui/main/HomeScreenViewModel.kt | 4 ++++ 5 files changed, 48 insertions(+), 3 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index 16e7dc554..ae407acf9 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -1047,6 +1047,23 @@ public void promptPushPrimer(CTLocalInAppSettings builder){ } } + public void promptForNotificationPermission(){ + if (instances == null) { + return; + } + + for (String accountId : CleverTapAPI.instances.keySet()) { + CleverTapAPI instance = CleverTapAPI.instances.get(accountId); + try { + if (instance != null) { + instance.coreState.getInAppController().promptPermission(); + } + } catch (Throwable t) { + // Ignore + } + } + } + // Initialize private CleverTapAPI(final Context context, final CleverTapInstanceConfig config, String cleverTapID) { this.context = context; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index 826844736..44ed353a4 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -2,6 +2,7 @@ import static com.clevertap.android.sdk.Utils.isAndroid13; +import android.app.Activity; import android.app.AlertDialog; import android.content.Context; import android.content.DialogInterface; @@ -11,7 +12,6 @@ import android.net.Uri; import android.os.Bundle; import android.view.WindowManager; -import android.widget.Toast; import androidx.annotation.NonNull; import androidx.core.app.ActivityCompat; @@ -69,6 +69,7 @@ public void onCreate(Bundle savedInstanceState) { throw new IllegalArgumentException(); } inAppNotification = notif.getParcelable("inApp"); + boolean displayHardNotificationDialog = notif.getBoolean("displayHardPermissionDialog",false); Bundle configBundle = notif.getBundle("configBundle"); if (configBundle != null) { config = configBundle.getParcelable("config"); @@ -76,6 +77,10 @@ public void onCreate(Bundle savedInstanceState) { setListener(CleverTapAPI.instanceWithConfig(this, config).getCoreState().getInAppController()); setPermissionCallback(CleverTapAPI.instanceWithConfig(this, config).getCoreState().getInAppController()); + if (displayHardNotificationDialog){ + prompt(); + return; + } } catch (Throwable t) { Logger.v("Cannot find a valid notification bundle to show!", t); finish(); @@ -219,13 +224,25 @@ public void onDecline() { }); } + public static void startPrompt(Activity activity, CleverTapInstanceConfig config){ + if (!activity.getClass().equals(InAppNotificationActivity.class)) { + Intent intent = new Intent(activity, InAppNotificationActivity.class); + intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); + Bundle configBundle = new Bundle(); + configBundle.putParcelable("config", config); + intent.putExtra("configBundle", configBundle); + intent.putExtra("displayHardPermissionDialog", true); + activity.startActivity(intent); + } + } + void didDismiss(Bundle data) { if (isAlertVisible) { isAlertVisible = false; } finish(); InAppListener listener = getListener(); - if (listener != null && getBaseContext() != null) { + if (listener != null && getBaseContext() != null && inAppNotification != null && data != null) { listener.inAppNotificationDidDismiss(getBaseContext(), inAppNotification, data); } } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index f9afe7067..94d4ff9c0 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -32,6 +32,7 @@ import java.util.HashMap; import java.util.HashSet; import java.util.List; +import java.util.Objects; import java.util.concurrent.Callable; import org.json.JSONArray; import org.json.JSONObject; @@ -187,6 +188,11 @@ public void promptPushPrimer(CTLocalInAppSettings ctLocalInAppSettings) {//Chang prepareNotificationForDisplay(ctLocalInAppSettings); } + public void promptPermission(){ + InAppNotificationActivity.startPrompt(Objects.requireNonNull(CoreMetaData.getCurrentActivity()), + config); + } + public void discardInApps() { this.inAppState = InAppState.DISCARDED; logger.verbose(config.getAccountId(), "InAppState is DISCARDED"); diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt index 6ca46058a..8e06c5b24 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt @@ -66,7 +66,8 @@ object HomeScreenModel { ), "PROMPT LOCAL IN-APP" to listOf( "Generate Half-Interstitial Local InApp", - "Generate Alert Local InApp" + "Generate Alert Local InApp", + "Generate hard permission dialog" ) ) } diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index 2fe603335..e490dfe54 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -343,6 +343,10 @@ class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() cleverTapAPI?.promptPushPrimer(builder) } + "102"->{ + cleverTapAPI?.promptForNotificationPermission() + } + //"60" -> webViewClickListener?.onWebViewClick() } From 9b0fa7e47815885aae4c52b605cbcafbeea4df30 Mon Sep 17 00:00:00 2001 From: William John Date: Thu, 15 Sep 2022 13:31:41 +0530 Subject: [PATCH 09/58] task(SDK-2167)-Add WebView JS interface method to directly call hard permission flow from HTML fragment --- .../com/clevertap/android/sdk/CTWebInterface.java | 15 +++++++++++++-- .../android/sdk/InAppNotificationActivity.java | 3 +-- 2 files changed, 14 insertions(+), 4 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java index c281fc172..ee6c7b1bf 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java @@ -20,8 +20,19 @@ public CTWebInterface(CleverTapAPI instance) { this.weakReference = new WeakReference<>(instance); } - - //Handle push primer click and directly call requestPermissions() inside InAppActivity + /** + * Method to be called from WebView Javascript to request permission for notification + * for Android 13 and above + */ + @JavascriptInterface + public void promptForNotificationPermission() { + CleverTapAPI cleverTapAPI = weakReference.get(); + if (cleverTapAPI == null) { + Logger.d("CleverTap Instance is null."); + } else { + cleverTapAPI.promptForNotificationPermission(); + } + } /** * Method to be called from WebView Javascript to add profile properties in CleverTap diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index 44ed353a4..1a6f8c402 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -227,7 +227,6 @@ public void onDecline() { public static void startPrompt(Activity activity, CleverTapInstanceConfig config){ if (!activity.getClass().equals(InAppNotificationActivity.class)) { Intent intent = new Intent(activity, InAppNotificationActivity.class); - intent.setFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT); Bundle configBundle = new Bundle(); configBundle.putParcelable("config", config); intent.putExtra("configBundle", configBundle); @@ -242,7 +241,7 @@ void didDismiss(Bundle data) { } finish(); InAppListener listener = getListener(); - if (listener != null && getBaseContext() != null && inAppNotification != null && data != null) { + if (listener != null && getBaseContext() != null && inAppNotification != null) { listener.inAppNotificationDidDismiss(getBaseContext(), inAppNotification, data); } } From 9aad906918c33fc241a94c85cfd5fbabfe04c6a8 Mon Sep 17 00:00:00 2001 From: William John Date: Wed, 21 Sep 2022 17:31:38 +0530 Subject: [PATCH 10/58] task(SDK-1970)-Refactor local in-app builder to use mandatory/optional parameters --- .../clevertap/android/sdk/CleverTapAPI.java | 23 +- .../com/clevertap/android/sdk/DeviceInfo.java | 4 +- .../sdk/inapp/CTAlertLocalInAppBuilder.java | 129 +++++++++ .../CTHalfInterstitialLocalInAppBuilder.java | 248 ++++++++++++++++++ .../sdk/inapp/CTInAppNotification.java | 97 +++++-- .../sdk/inapp/CTInAppNotificationButton.java | 20 +- .../sdk/inapp/CTLocalInAppSettings.java | 110 -------- .../android/sdk/inapp/InAppController.java | 46 +++- .../demo/ui/main/HomeScreenViewModel.kt | 37 +-- 9 files changed, 536 insertions(+), 178 deletions(-) create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java delete mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index ae407acf9..d6c51a2cc 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -31,7 +31,8 @@ import com.clevertap.android.sdk.events.EventDetail; import com.clevertap.android.sdk.events.EventGroup; import com.clevertap.android.sdk.featureFlags.CTFeatureFlagsController; -import com.clevertap.android.sdk.inapp.CTLocalInAppSettings; +import com.clevertap.android.sdk.inapp.CTAlertLocalInAppBuilder; +import com.clevertap.android.sdk.inapp.CTHalfInterstitialLocalInAppBuilder; import com.clevertap.android.sdk.inbox.CTInboxActivity; import com.clevertap.android.sdk.inbox.CTInboxMessage; import com.clevertap.android.sdk.inbox.CTMessageDAO; @@ -1030,21 +1031,13 @@ public static void tokenRefresh(Context context, String token, PushType pushType } } - public void promptPushPrimer(CTLocalInAppSettings builder){ - if (instances == null) { - return; - } + public void promptHalfInterstitialPushPrimer(CTHalfInterstitialLocalInAppBuilder + halfInterstitialLocalInAppBuilder){ + coreState.getInAppController().promptPushPrimer(halfInterstitialLocalInAppBuilder); + } - for (String accountId : CleverTapAPI.instances.keySet()) { - CleverTapAPI instance = CleverTapAPI.instances.get(accountId); - try { - if (instance != null) { - instance.coreState.getInAppController().promptPushPrimer(builder); - } - } catch (Throwable t) { - // Ignore - } - } + public void promptAlertPushPrimer(CTAlertLocalInAppBuilder alertLocalInAppBuilder){ + coreState.getInAppController().promptPushPrimer(alertLocalInAppBuilder); } public void promptForNotificationPermission(){ diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java index cdbaaa2ca..4bfe83fa6 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java @@ -391,12 +391,12 @@ private double toTwoPlaces(double n) { /** * Device is a smart phone */ - static final int SMART_PHONE = 1; + public static final int SMART_PHONE = 1; /** * Device is a tablet */ - static final int TABLET = 2; + public static final int TABLET = 2; /** * Device is a television diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java new file mode 100644 index 000000000..b97237add --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java @@ -0,0 +1,129 @@ +package com.clevertap.android.sdk.inapp; + +import androidx.annotation.NonNull; + +import java.util.Objects; + +public class CTAlertLocalInAppBuilder { + + private final String titleText; + private final String bodyText; + private final boolean followDeviceOrientation; + private final String positiveBtnText; + private final String negativeBtnText; + + CTAlertLocalInAppBuilder(Builder.Builder1 builder) { + this.titleText = builder.titleText; + this.bodyText = builder.bodyText; + this.followDeviceOrientation = builder.followDeviceOrientation; + this.positiveBtnText = builder.positiveBtnText; + this.negativeBtnText = builder.negativeBtnText; + } + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + public Builder1 titleText(String titleText) { + return new Builder1(titleText); + } + public static final class Builder1 { + final String titleText; + String bodyText; + boolean followDeviceOrientation; + String positiveBtnText; + String negativeBtnText; + + private Builder1(String titleText) { + this.titleText = titleText; + } + public Builder2 bodyText(String bodyText) { + this.bodyText = bodyText; + return new Builder2(Builder1.this); + } + } + public static final class Builder2 { + final Builder1 builder; + + private Builder2(Builder1 builder) { + this.builder = builder; + } + public Builder3 followDeviceOrientation(boolean followDeviceOrientation) { + this.builder.followDeviceOrientation = followDeviceOrientation; + return new Builder3(this.builder); + } + } + public static final class Builder3 { + final Builder1 builder; + + private Builder3(Builder1 builder) { + this.builder = builder; + } + public Builder4 positiveBtnText(String positiveBtnText) { + this.builder.positiveBtnText = positiveBtnText; + return new Builder4(this.builder); + } + } + public static final class Builder4 { + final Builder1 builder; + + private Builder4(Builder1 builder) { + this.builder = builder; + } + public Builder5 negativeBtnText(String negativeBtnText) { + this.builder.negativeBtnText = negativeBtnText; + return new Builder5(this.builder); + } + } + public static final class Builder5 { + final Builder1 builder; + + private Builder5(Builder1 builder) { + this.builder = builder; + } + public CTAlertLocalInAppBuilder build() { + return new CTAlertLocalInAppBuilder(this.builder); + } + } + } + + public String titleText() { + return this.titleText; + } + public String bodyText() { + return this.bodyText; + } + public boolean followDeviceOrientation() { + return this.followDeviceOrientation; + } + public String positiveBtnText() { + return this.positiveBtnText; + } + public String negativeBtnText() { + return this.negativeBtnText; + } + + @NonNull + @Override + public String toString() { + return "CTAlertLocalInAppBuilder(titleText=" + this.titleText + ", bodyText=" + this.bodyText + + ", followDeviceOrientation=" + this.followDeviceOrientation + ", positiveBtnText=" + + this.positiveBtnText + ", negativeBtnText=" + this.negativeBtnText + ")"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CTAlertLocalInAppBuilder that = (CTAlertLocalInAppBuilder) o; + return followDeviceOrientation == that.followDeviceOrientation && + Objects.equals(titleText, that.titleText) && Objects.equals(bodyText, that.bodyText) && + Objects.equals(positiveBtnText, that.positiveBtnText) && + Objects.equals(negativeBtnText, that.negativeBtnText); + } + + @Override + public int hashCode() { + return Objects.hash(titleText, bodyText, followDeviceOrientation, positiveBtnText, negativeBtnText); + } +} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java new file mode 100644 index 000000000..80a471a28 --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java @@ -0,0 +1,248 @@ +package com.clevertap.android.sdk.inapp; + + +import androidx.annotation.NonNull; + +import java.util.Objects; + +public class CTHalfInterstitialLocalInAppBuilder { + + private final String titleText; + private final String titleTextColor; + private final String bodyText; + private final String bodyTextColor; + private final String backgroundColor; + private final boolean followDeviceOrientation; + private final String positiveBtnText; + private final String negativeBtnText; + private final String btnTextColor; + private final String btnBackgroundColor; + private final String btnBorderColor;// Optional + private final String btnBorderRadius;// Optional + private boolean doesSupportTablet; + + CTHalfInterstitialLocalInAppBuilder(Builder.Builder1 builder) { + this.titleText = builder.titleText; + this.titleTextColor = builder.titleTextColor; + this.bodyText = builder.bodyText; + this.bodyTextColor = builder.bodyTextColor; + this.backgroundColor = builder.backgroundColor; + this.followDeviceOrientation = builder.followDeviceOrientation; + this.positiveBtnText = builder.positiveBtnText; + this.negativeBtnText = builder.negativeBtnText; + this.btnTextColor = builder.btnTextColor; + this.btnBackgroundColor = builder.btnBackgroundColor; + this.btnBorderColor = builder.btnBorderColor; + this.btnBorderRadius = builder.btnBorderRadius; + } + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + public Builder1 titleText(String titleText) { + return new Builder1(titleText); + } + public static final class Builder1 { + final String titleText; + String titleTextColor; + String bodyText; + String bodyTextColor; + String backgroundColor; + boolean followDeviceOrientation; + String positiveBtnText; + String negativeBtnText; + String btnTextColor; + String btnBackgroundColor; + String btnBorderColor; + String btnBorderRadius; + + private Builder1(String titleText) { + this.titleText = titleText; + } + public Builder2 titleTextColor(String titleTextColor) { + this.titleTextColor = titleTextColor; + return new Builder2(Builder1.this); + } + } + public static final class Builder2 { + final Builder1 builder; + + private Builder2(Builder1 builder) { + this.builder = builder; + } + public Builder3 bodyText(String bodyText) { + this.builder.bodyText = bodyText; + return new Builder3(this.builder); + } + } + public static final class Builder3 { + final Builder1 builder; + + private Builder3(Builder1 builder) { + this.builder = builder; + } + public Builder4 bodyTextColor(String bodyTextColor) { + this.builder.bodyTextColor = bodyTextColor; + return new Builder4(this.builder); + } + } + public static final class Builder4 { + final Builder1 builder; + + private Builder4(Builder1 builder) { + this.builder = builder; + } + public Builder5 backgroundColor(String backgroundColor) { + this.builder.backgroundColor = backgroundColor; + return new Builder5(this.builder); + } + } + public static final class Builder5 { + final Builder1 builder; + + private Builder5(Builder1 builder) { + this.builder = builder; + } + public Builder6 followDeviceOrientation(boolean followDeviceOrientation) { + this.builder.followDeviceOrientation = followDeviceOrientation; + return new Builder6(this.builder); + } + } + public static final class Builder6 { + final Builder1 builder; + + private Builder6(Builder1 builder) { + this.builder = builder; + } + public Builder7 positiveBtnText(String positiveBtnText) { + this.builder.positiveBtnText = positiveBtnText; + return new Builder7(this.builder); + } + } + public static final class Builder7 { + final Builder1 builder; + + private Builder7(Builder1 builder) { + this.builder = builder; + } + public Builder8 negativeBtnText(String negativeBtnText) { + this.builder.negativeBtnText = negativeBtnText; + return new Builder8(this.builder); + } + } + public static final class Builder8 { + final Builder1 builder; + + private Builder8(Builder1 builder) { + this.builder = builder; + } + public Builder9 btnTextColor(String btnTextColor) { + this.builder.btnTextColor = btnTextColor; + return new Builder9(this.builder); + } + } + public static final class Builder9 { + final Builder1 builder; + + private Builder9(Builder1 builder) { + this.builder = builder; + } + public Builder10 btnBackgroundColor(String btnBackgroundColor) { + this.builder.btnBackgroundColor = btnBackgroundColor; + return new Builder10(this.builder); + } + } + public static final class Builder10 { + final Builder1 builder; + + private Builder10(Builder1 builder) { + this.builder = builder; + } + public Builder10 btnBorderColor(String btnBorderColor){ + this.builder.btnBorderColor = btnBorderColor; + return this; + } + public Builder10 btnBorderRadius(String btnBorderRadius){ + this.builder.btnBorderRadius = btnBorderRadius; + return this; + } + public CTHalfInterstitialLocalInAppBuilder build() { + return new CTHalfInterstitialLocalInAppBuilder(this.builder); + } + } + } + + public String titleText() { + return this.titleText; + } + public String titleTextColor() { + return this.titleTextColor; + } + public String bodyText() { + return this.bodyText; + } + public String bodyTextColor() { + return this.bodyTextColor; + } + public String backgroundColor() { + return this.backgroundColor; + } + public boolean followDeviceOrientation() { + return this.followDeviceOrientation; + } + public String positiveBtnText() { + return this.positiveBtnText; + } + public String negativeBtnText() { + return this.negativeBtnText; + } + public String btnTextColor() { + return this.btnTextColor; + } + public String btnBackgroundColor() { + return this.btnBackgroundColor; + } + public String btnBorderColor() { + return this.btnBorderColor; + } + public String btnBorderRadius() { + return this.btnBorderRadius; + } + + @NonNull + @Override + public String toString() { + return "CTHalfInterstitialLocalInAppBuilder(titleText=" + this.titleText + ", titleTextColor=" + + this.titleTextColor + ", bodyText=" + this.bodyText + ", bodyTextColor=" + this.bodyTextColor + + ", backgroundColor=" + this.backgroundColor + ", followDeviceOrientation=" + + this.followDeviceOrientation + ", positiveBtnText=" + this.positiveBtnText + + ", negativeBtnText=" + this.negativeBtnText + ", btnTextColor=" + + this.btnTextColor + ", btnBackgroundColor=" + this.btnBackgroundColor + + ", btnBorderColor=" + this.btnBorderColor + ", btnBorderRadius=" + this.btnBorderRadius + ")"; + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CTHalfInterstitialLocalInAppBuilder that = (CTHalfInterstitialLocalInAppBuilder) o; + return followDeviceOrientation == that.followDeviceOrientation && + Objects.equals(titleText, that.titleText) && Objects.equals(titleTextColor, that.titleTextColor) + && Objects.equals(bodyText, that.bodyText) && Objects.equals(bodyTextColor, that.bodyTextColor) + && Objects.equals(backgroundColor, that.backgroundColor) && + Objects.equals(positiveBtnText, that.positiveBtnText) && + Objects.equals(negativeBtnText, that.negativeBtnText) && + Objects.equals(btnTextColor, that.btnTextColor) && + Objects.equals(btnBackgroundColor, that.btnBackgroundColor) && + Objects.equals(btnBorderColor, that.btnBorderColor) && + Objects.equals(btnBorderRadius, that.btnBorderRadius); + } + + @Override + public int hashCode() { + return Objects.hash(titleText, titleTextColor, bodyText, bodyTextColor, backgroundColor, + followDeviceOrientation, positiveBtnText, negativeBtnText, btnTextColor, + btnBackgroundColor, btnBorderColor, btnBorderRadius); + } +} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index 33ea24de2..dbc02b704 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -9,6 +9,7 @@ import androidx.annotation.RestrictTo; import androidx.annotation.RestrictTo.Scope; import com.clevertap.android.sdk.Constants; +import com.clevertap.android.sdk.DeviceInfo; import com.clevertap.android.sdk.Logger; import com.clevertap.android.sdk.Utils; import com.clevertap.android.sdk.utils.ImageCache; @@ -222,6 +223,9 @@ public CTInAppNotification[] newArray(int size) { private boolean isLocalInApp = false; + private static final String HALF_INTERSTITIAL_LOCAL_IN_APP = "half-interstitial"; + private static final String ALERT_LOCAL_IN_APP = "alert-template"; + CTInAppNotification() { } @@ -579,47 +583,104 @@ void prepareForDisplay() { } listener.notificationReady(this); } + public CTInAppNotification configureAlertLocalInApp(CTAlertLocalInAppBuilder alertLocalInAppBuilder, + int deviceInfo){ + this.id = ""; + this.campaignId = ""; + this.type = ALERT_LOCAL_IN_APP; + this.inAppType = CTInAppType.fromString(this.type); + this.isTablet = deviceInfo == DeviceInfo.TABLET; + this.isPortrait = true; + this.isLandscape = alertLocalInAppBuilder.followDeviceOrientation(); + this.isLocalInApp = true; + this.timeToLive = System.currentTimeMillis() + 2 * Constants.ONE_DAY_IN_MILLIS; + this.title = alertLocalInAppBuilder.titleText() != null ? alertLocalInAppBuilder.titleText() : ""; + this.message = alertLocalInAppBuilder.bodyText() != null ? alertLocalInAppBuilder.bodyText() : ""; + + setupInAppActionButtons(alertLocalInAppBuilder.positiveBtnText(), + alertLocalInAppBuilder.negativeBtnText(), + null,null,null,null); + + return this; + } + + public CTInAppNotification configureHalfInterstitialLocalInApp (CTHalfInterstitialLocalInAppBuilder + halfInterstitialLocalInAppBuilder, int deviceInfo){ + //check how many times have they called via local builder. +// boolean,count TODO - public CTInAppNotification configureWithLocalData(CTLocalInAppSettings ctLocalInAppSettings){ - this.id = "";// - this.campaignId = "";// - this.type = ctLocalInAppSettings.getInAppAlertType();//alert-template - this.excludeFromCaps = false;// + this.id = ""; + this.campaignId = ""; + this.type = HALF_INTERSTITIAL_LOCAL_IN_APP; + + + this.excludeFromCaps = false;//Check this withInAppFC Manager this.totalLifetimeCount = -1;// this.totalDailyCount = -1;// + this.inAppType = CTInAppType.fromString(this.type); - this.isTablet = false;// - this.backgroundColor = Constants.WHITE; - this.isPortrait = true;// - this.isLandscape = true;// + this.isTablet = deviceInfo == DeviceInfo.TABLET; + + this.backgroundColor = halfInterstitialLocalInAppBuilder.backgroundColor() != null ? + halfInterstitialLocalInAppBuilder.backgroundColor() : Constants.WHITE; + + this.isPortrait = true; + this.isLandscape = halfInterstitialLocalInAppBuilder.followDeviceOrientation(); + this.isLocalInApp = true; this.timeToLive = System.currentTimeMillis() + 2 * Constants.ONE_DAY_IN_MILLIS; + this.title = halfInterstitialLocalInAppBuilder.titleText() != null ? + halfInterstitialLocalInAppBuilder.titleText() : ""; + this.titleColor = halfInterstitialLocalInAppBuilder.titleTextColor() !=null ? + halfInterstitialLocalInAppBuilder.titleTextColor() + : Constants.BLACK; - this.title = ctLocalInAppSettings.getTitleText(); - this.titleColor = Constants.BLACK; - - this.message = ctLocalInAppSettings.getBodyText(); - this.messageColor = Constants.BLACK; + this.message = halfInterstitialLocalInAppBuilder.bodyText() != null ? + halfInterstitialLocalInAppBuilder.bodyText() : ""; + this.messageColor = halfInterstitialLocalInAppBuilder.bodyTextColor() != null ? + halfInterstitialLocalInAppBuilder.bodyTextColor() + : Constants.BLACK; this.hideCloseButton = true; - //CTINAPPNOTIFMedia obj + //CTINAPPNOTIFMedia obj//1.local image in case of offline//TODO + //2.support for URI + //3. In case of failure in loading img should we load a placeholder img in layout. + + setupInAppActionButtons(halfInterstitialLocalInAppBuilder.positiveBtnText(), + halfInterstitialLocalInAppBuilder.negativeBtnText(), + halfInterstitialLocalInAppBuilder.btnBackgroundColor(), + halfInterstitialLocalInAppBuilder.btnTextColor(), + halfInterstitialLocalInAppBuilder.btnBorderColor(), + halfInterstitialLocalInAppBuilder.btnBorderRadius()); + + return this; + } + + private void setupInAppActionButtons(String positiveBtnText, String negativeBtnText, + String btnBackgroundColor, + String btnTextColor, String btnBorderColor, + String btnBorderRadius){ //Positive Button CTInAppNotificationButton inAppNotificationPositiveButton = new CTInAppNotificationButton() - .initWithLocalData(ctLocalInAppSettings.getPositiveConfirmationBtnText(),ctLocalInAppSettings.getPositiveConfirmationBtnColor()); + .initWithLocalData(positiveBtnText, + btnBackgroundColor,btnTextColor,btnBorderColor,btnBorderRadius); + if (inAppNotificationPositiveButton != null) { this.buttons.add(inAppNotificationPositiveButton); } //Negative Button CTInAppNotificationButton inAppNotificationNegativeButton = new CTInAppNotificationButton() - .initWithLocalData(ctLocalInAppSettings.getNegativeConfirmationBtnText(),ctLocalInAppSettings.getPositiveConfirmationBtnColor()); + .initWithLocalData(negativeBtnText, + btnBackgroundColor,btnTextColor, + btnBorderColor,btnBorderRadius); + if (inAppNotificationNegativeButton != null) { this.buttons.add(inAppNotificationNegativeButton); } - return this; } private void configureWithJson(JSONObject jsonObject) { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java index 78240d321..546cfe1c6 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java @@ -207,20 +207,26 @@ CTInAppNotificationButton initWithJSON(JSONObject jsonObject) { } } } + + //check if action is request for permission(rfp) and innit variable here. } catch (JSONException e) { this.error = "Invalid JSON"; } return this; } - CTInAppNotificationButton initWithLocalData(String text, String btnBackgroundColor) { - this.text = text; - this.textColor = Constants.WHITE; - this.backgroundColor = btnBackgroundColor.isEmpty() ? btnBackgroundColor - : Constants.LIGHT_BLUE; - this.borderColor = Constants.GREEN; - this.borderRadius = "4";//From sample payload + CTInAppNotificationButton initWithLocalData(String btnText, String btnBackgroundColor, + String btnTextColor, String btnBorderColor, + String btnBorderRadius) { + + this.text = btnText != null ? btnText : ""; + this.backgroundColor = btnBackgroundColor != null ? btnBackgroundColor + : Constants.BLUE; + this.textColor = btnTextColor != null ? btnTextColor : Constants.BLUE; + this.borderColor = btnBorderColor !=null ? btnBorderColor : Constants.WHITE; + this.borderRadius = btnBorderRadius != null ? btnBorderRadius : "2";//Adding default value as 2 instead of an empty value. + // If the value is empty then action btn defaults to standard btn without any customizations return this; } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java deleted file mode 100644 index 17b2f7cef..000000000 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppSettings.java +++ /dev/null @@ -1,110 +0,0 @@ -package com.clevertap.android.sdk.inapp; - -import java.util.Objects; - -public class CTLocalInAppSettings { - - - public static final class Builder { - private String inAppAlertType; - private String titleText; - private String bodyText; - private String positiveConfirmationBtnText; - private String negativeConfirmationBtnText; - private String positiveConfirmationBtnColor; - - public Builder() { - } - - public CTLocalInAppSettings build(){ - return new CTLocalInAppSettings(this); - } - - public CTLocalInAppSettings.Builder setInAppAlertType(String inAppAlertType) { - this.inAppAlertType = inAppAlertType; - return this; - } - - public CTLocalInAppSettings.Builder setTitleText(String titleText){ - this.titleText = titleText; - return this; - } - - public CTLocalInAppSettings.Builder setBodyText(String bodyText){ - this.bodyText = bodyText; - return this; - } - - public CTLocalInAppSettings.Builder setPositiveConfirmationBtnText(String positiveConfirmationBtnText){ - this.positiveConfirmationBtnText = positiveConfirmationBtnText; - return this; - } - - public CTLocalInAppSettings.Builder setNegativeConfirmationBtnText(String negativeConfirmationBtnText){ - this.negativeConfirmationBtnText = negativeConfirmationBtnText; - return this; - } - - public CTLocalInAppSettings.Builder setPositiveConfirmationBtnColor(String positiveConfirmationBtnColor){ - this.positiveConfirmationBtnColor = positiveConfirmationBtnColor; - return this; - } - } - - private final String inAppAlertType; - private final String titleText; - private final String bodyText; - private final String positiveConfirmationBtnText; - private final String negativeConfirmationBtnText; - private final String positiveConfirmationBtnColor; - - private CTLocalInAppSettings(Builder builder) { - inAppAlertType = builder.inAppAlertType; - titleText = builder.titleText; - bodyText = builder.bodyText; - positiveConfirmationBtnText = builder.positiveConfirmationBtnText; - negativeConfirmationBtnText = builder.negativeConfirmationBtnText; - positiveConfirmationBtnColor = builder.positiveConfirmationBtnColor; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CTLocalInAppSettings that = (CTLocalInAppSettings) o; - return Objects.equals(inAppAlertType, that.inAppAlertType) && Objects.equals(titleText, that.titleText) - && Objects.equals(bodyText, that.bodyText) && - Objects.equals(positiveConfirmationBtnText, that.positiveConfirmationBtnText) - && Objects.equals(negativeConfirmationBtnText, that.negativeConfirmationBtnText) - && Objects.equals(positiveConfirmationBtnColor, that.positiveConfirmationBtnColor); - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - public String getInAppAlertType() { - return inAppAlertType; - } - - public String getTitleText() { - return titleText; - } - - public String getBodyText() { - return bodyText; - } - - public String getPositiveConfirmationBtnText() { - return positiveConfirmationBtnText; - } - - public String getNegativeConfirmationBtnText() { - return negativeConfirmationBtnText; - } - - public String getPositiveConfirmationBtnColor() { - return positiveConfirmationBtnColor; - } -} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 94d4ff9c0..3c7e0dad2 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -15,6 +15,7 @@ import com.clevertap.android.sdk.Constants; import com.clevertap.android.sdk.ControllerManager; import com.clevertap.android.sdk.CoreMetaData; +import com.clevertap.android.sdk.DeviceInfo; import com.clevertap.android.sdk.InAppNotificationActivity; import com.clevertap.android.sdk.InAppNotificationListener; import com.clevertap.android.sdk.Logger; @@ -47,7 +48,8 @@ private final class NotificationPrepareRunnable implements Runnable { private JSONObject jsonObject; - private CTLocalInAppSettings ctLocalInAppSettings; + private CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder; + private CTAlertLocalInAppBuilder alertLocalInAppBuilder; private final boolean videoSupport = Utils.haveVideoPlayerSupport; @@ -56,9 +58,16 @@ private final class NotificationPrepareRunnable implements Runnable { this.jsonObject = jsonObject; } - NotificationPrepareRunnable(InAppController inAppController, CTLocalInAppSettings ctLocalInAppSettings) { + NotificationPrepareRunnable(InAppController inAppController, + CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder) { this.inAppControllerWeakReference = new WeakReference<>(inAppController); - this.ctLocalInAppSettings = ctLocalInAppSettings; + this.halfInterstitialLocalInAppBuilder = halfInterstitialLocalInAppBuilder; + } + + NotificationPrepareRunnable(InAppController inAppController, + CTAlertLocalInAppBuilder alertLocalInAppBuilder) { + this.inAppControllerWeakReference = new WeakReference<>(inAppController); + this.alertLocalInAppBuilder = alertLocalInAppBuilder; } @Override @@ -68,8 +77,12 @@ public void run() { inAppNotification = new CTInAppNotification() .initWithJSON(jsonObject, videoSupport); }else {//render in-app via local in-app builder - inAppNotification = new CTInAppNotification() - .configureWithLocalData(ctLocalInAppSettings); + inAppNotification = halfInterstitialLocalInAppBuilder != null ? new CTInAppNotification() + .configureHalfInterstitialLocalInApp(halfInterstitialLocalInAppBuilder, + DeviceInfo.getDeviceType(context)) : + new CTInAppNotification() + .configureAlertLocalInApp(alertLocalInAppBuilder, + DeviceInfo.getDeviceType(context)); } if (inAppNotification.getError() != null) { @@ -184,8 +197,12 @@ public void checkPendingInAppNotifications(Activity activity) { } } - public void promptPushPrimer(CTLocalInAppSettings ctLocalInAppSettings) {//Change method name here to avoid confusion - prepareNotificationForDisplay(ctLocalInAppSettings); + public void promptPushPrimer(CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder){ + prepareNotificationForDisplay(halfInterstitialLocalInAppBuilder,null); + } + + public void promptPushPrimer(CTAlertLocalInAppBuilder alertLocalInAppBuilder){ + prepareNotificationForDisplay(null,alertLocalInAppBuilder); } public void promptPermission(){ @@ -470,13 +487,20 @@ public Void call() { }); } - private void prepareNotificationForDisplay(final CTLocalInAppSettings ctLocalInAppSettings) { - logger.debug(config.getAccountId(), "Preparing local In-App using CTLocalInAppSettings for display");//Need correct error mssg + private void prepareNotificationForDisplay(CTHalfInterstitialLocalInAppBuilder + halfInterstitialLocalInAppBuilder, CTAlertLocalInAppBuilder alertLocalInAppBuilder){ + logger.debug(config.getAccountId(), "Preparing local In-App for display"); Task task = CTExecutorFactory.executors(config).postAsyncSafelyTask(Constants.TAG_FEATURE_IN_APPS); - task.execute("InappController#prepareNotificationForDisplay", new Callable() { + task.execute("InappController#prepareLocalNotificationForDisplay", new Callable() { @Override public Void call() { - new NotificationPrepareRunnable(InAppController.this, ctLocalInAppSettings).run(); + if (halfInterstitialLocalInAppBuilder != null) { + new NotificationPrepareRunnable(InAppController.this, + halfInterstitialLocalInAppBuilder).run(); + }else if (alertLocalInAppBuilder != null){ + new NotificationPrepareRunnable(InAppController.this, + alertLocalInAppBuilder).run(); + } return null; } }); diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index e490dfe54..abc491fee 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -7,7 +7,8 @@ import androidx.lifecycle.ViewModel import com.clevertap.android.sdk.CTInboxStyleConfig import com.clevertap.android.sdk.CleverTapAPI import com.clevertap.android.sdk.Constants -import com.clevertap.android.sdk.inapp.CTLocalInAppSettings +import com.clevertap.android.sdk.inapp.CTAlertLocalInAppBuilder +import com.clevertap.android.sdk.inapp.CTHalfInterstitialLocalInAppBuilder import java.util.* class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() { @@ -324,23 +325,29 @@ class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() "918"-> cleverTapAPI?.pushEvent("Send Input Box Reminder DOC false") "919"-> cleverTapAPI?.pushEvent("Send Three CTA Notification") "100"-> { - val builder = CTLocalInAppSettings.Builder().setTitleText("Get Notified") - .setInAppAlertType("half-interstitial") - .setBodyText("Please enable notifications on your device to use Push Notifications.") - .setPositiveConfirmationBtnText("Allow") - .setNegativeConfirmationBtnText("Cancel") - .setPositiveConfirmationBtnColor(Constants.LIGHT_BLUE).build()//Add image,inapp type - cleverTapAPI?.promptPushPrimer(builder) + val builder = CTHalfInterstitialLocalInAppBuilder.builder() + .titleText("Get Notified") + .titleTextColor(Constants.WHITE) + .bodyText("Please enable notifications on your device to use Push Notifications.") + .bodyTextColor(Constants.WHITE) + .backgroundColor(Constants.BLACK) + .followDeviceOrientation(false) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .btnTextColor(Constants.WHITE) + .btnBackgroundColor(Constants.LIGHT_BLUE) + .build() + cleverTapAPI?.promptHalfInterstitialPushPrimer(builder) } "101"->{ - val builder = CTLocalInAppSettings.Builder().setTitleText("Get Notified") - .setInAppAlertType("alert-template") - .setBodyText("Please enable notifications on your device to use Push Notifications.") - .setPositiveConfirmationBtnText("Allow") - .setNegativeConfirmationBtnText("Cancel") - .setPositiveConfirmationBtnColor(Constants.LIGHT_BLUE).build()//Add image,inapp type - cleverTapAPI?.promptPushPrimer(builder) + val builder = CTAlertLocalInAppBuilder.builder().titleText("Get Notified") + .bodyText("Please enable notifications on your device to use Push Notifications.") + .followDeviceOrientation(true) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .build() + cleverTapAPI?.promptAlertPushPrimer(builder) } "102"->{ From 8cf6f096df61e45d94edd7319120a8d6121f825c Mon Sep 17 00:00:00 2001 From: William John Date: Tue, 27 Sep 2022 11:52:24 +0530 Subject: [PATCH 11/58] task(SDK-1970)-Refactor half-interstitial builder, add support for image support in local IAM --- .../CTHalfInterstitialLocalInAppBuilder.java | 147 ++++++++++-------- .../sdk/inapp/CTInAppNotification.java | 24 ++- .../sdk/inapp/CTInAppNotificationMedia.java | 14 ++ .../demo/ui/main/HomeScreenViewModel.kt | 11 +- 4 files changed, 116 insertions(+), 80 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java index 80a471a28..717f5603a 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java @@ -19,31 +19,32 @@ public class CTHalfInterstitialLocalInAppBuilder { private final String btnBackgroundColor; private final String btnBorderColor;// Optional private final String btnBorderRadius;// Optional - private boolean doesSupportTablet; - - CTHalfInterstitialLocalInAppBuilder(Builder.Builder1 builder) { - this.titleText = builder.titleText; - this.titleTextColor = builder.titleTextColor; - this.bodyText = builder.bodyText; - this.bodyTextColor = builder.bodyTextColor; - this.backgroundColor = builder.backgroundColor; - this.followDeviceOrientation = builder.followDeviceOrientation; - this.positiveBtnText = builder.positiveBtnText; - this.negativeBtnText = builder.negativeBtnText; - this.btnTextColor = builder.btnTextColor; - this.btnBackgroundColor = builder.btnBackgroundColor; - this.btnBorderColor = builder.btnBorderColor; - this.btnBorderRadius = builder.btnBorderRadius; + private final String image;// Optional + + CTHalfInterstitialLocalInAppBuilder(Builder.LocalInAppBuilder localInAppBuilder) { + this.titleText = localInAppBuilder.titleText; + this.titleTextColor = localInAppBuilder.titleTextColor; + this.bodyText = localInAppBuilder.bodyText; + this.bodyTextColor = localInAppBuilder.bodyTextColor; + this.backgroundColor = localInAppBuilder.backgroundColor; + this.followDeviceOrientation = localInAppBuilder.followDeviceOrientation; + this.positiveBtnText = localInAppBuilder.positiveBtnText; + this.negativeBtnText = localInAppBuilder.negativeBtnText; + this.btnTextColor = localInAppBuilder.btnTextColor; + this.btnBackgroundColor = localInAppBuilder.btnBackgroundColor; + this.btnBorderColor = localInAppBuilder.btnBorderColor; + this.btnBorderRadius = localInAppBuilder.btnBorderRadius; + this.image = localInAppBuilder.image; } public static Builder builder() { return new Builder(); } public static final class Builder { - public Builder1 titleText(String titleText) { - return new Builder1(titleText); + public LocalInAppBuilder titleText(String titleText) { + return new LocalInAppBuilder(titleText); } - public static final class Builder1 { + public static final class LocalInAppBuilder { final String titleText; String titleTextColor; String bodyText; @@ -56,114 +57,119 @@ public static final class Builder1 { String btnBackgroundColor; String btnBorderColor; String btnBorderRadius; + String image; - private Builder1(String titleText) { + private LocalInAppBuilder(String titleText) { this.titleText = titleText; } - public Builder2 titleTextColor(String titleTextColor) { + public TitleTextColorBuilder titleTextColor(String titleTextColor) { this.titleTextColor = titleTextColor; - return new Builder2(Builder1.this); + return new TitleTextColorBuilder(LocalInAppBuilder.this); } } - public static final class Builder2 { - final Builder1 builder; + public static final class TitleTextColorBuilder { + final LocalInAppBuilder builder; - private Builder2(Builder1 builder) { + private TitleTextColorBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder3 bodyText(String bodyText) { + public BodyTextBuilder bodyText(String bodyText) { this.builder.bodyText = bodyText; - return new Builder3(this.builder); + return new BodyTextBuilder(this.builder); } } - public static final class Builder3 { - final Builder1 builder; + public static final class BodyTextBuilder { + final LocalInAppBuilder builder; - private Builder3(Builder1 builder) { + private BodyTextBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder4 bodyTextColor(String bodyTextColor) { + public BodyTextColorBuilder bodyTextColor(String bodyTextColor) { this.builder.bodyTextColor = bodyTextColor; - return new Builder4(this.builder); + return new BodyTextColorBuilder(this.builder); } } - public static final class Builder4 { - final Builder1 builder; + public static final class BodyTextColorBuilder { + final LocalInAppBuilder builder; - private Builder4(Builder1 builder) { + private BodyTextColorBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder5 backgroundColor(String backgroundColor) { + public BackgroundColorBuilder backgroundColor(String backgroundColor) { this.builder.backgroundColor = backgroundColor; - return new Builder5(this.builder); + return new BackgroundColorBuilder(this.builder); } } - public static final class Builder5 { - final Builder1 builder; + public static final class BackgroundColorBuilder { + final LocalInAppBuilder builder; - private Builder5(Builder1 builder) { + private BackgroundColorBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder6 followDeviceOrientation(boolean followDeviceOrientation) { + public FollowDeviceOrientationBuilder followDeviceOrientation(boolean followDeviceOrientation) { this.builder.followDeviceOrientation = followDeviceOrientation; - return new Builder6(this.builder); + return new FollowDeviceOrientationBuilder(this.builder); } } - public static final class Builder6 { - final Builder1 builder; + public static final class FollowDeviceOrientationBuilder { + final LocalInAppBuilder builder; - private Builder6(Builder1 builder) { + private FollowDeviceOrientationBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder7 positiveBtnText(String positiveBtnText) { + public PositiveBtnTextBuilder positiveBtnText(String positiveBtnText) { this.builder.positiveBtnText = positiveBtnText; - return new Builder7(this.builder); + return new PositiveBtnTextBuilder(this.builder); } } - public static final class Builder7 { - final Builder1 builder; + public static final class PositiveBtnTextBuilder { + final LocalInAppBuilder builder; - private Builder7(Builder1 builder) { + private PositiveBtnTextBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder8 negativeBtnText(String negativeBtnText) { + public NegativeBtnTextBuilder negativeBtnText(String negativeBtnText) { this.builder.negativeBtnText = negativeBtnText; - return new Builder8(this.builder); + return new NegativeBtnTextBuilder(this.builder); } } - public static final class Builder8 { - final Builder1 builder; + public static final class NegativeBtnTextBuilder { + final LocalInAppBuilder builder; - private Builder8(Builder1 builder) { + private NegativeBtnTextBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder9 btnTextColor(String btnTextColor) { + public BtnTextColorBuilder btnTextColor(String btnTextColor) { this.builder.btnTextColor = btnTextColor; - return new Builder9(this.builder); + return new BtnTextColorBuilder(this.builder); } } - public static final class Builder9 { - final Builder1 builder; + public static final class BtnTextColorBuilder { + final LocalInAppBuilder builder; - private Builder9(Builder1 builder) { + private BtnTextColorBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder10 btnBackgroundColor(String btnBackgroundColor) { + public LocalInAppOptionalBuilder btnBackgroundColor(String btnBackgroundColor) { this.builder.btnBackgroundColor = btnBackgroundColor; - return new Builder10(this.builder); + return new LocalInAppOptionalBuilder(this.builder); } } - public static final class Builder10 { - final Builder1 builder; + public static final class LocalInAppOptionalBuilder { + final LocalInAppBuilder builder; - private Builder10(Builder1 builder) { + private LocalInAppOptionalBuilder(LocalInAppBuilder builder) { this.builder = builder; } - public Builder10 btnBorderColor(String btnBorderColor){ + public LocalInAppOptionalBuilder image(String image){ + this.builder.image = image; + return this; + } + public LocalInAppOptionalBuilder btnBorderColor(String btnBorderColor){ this.builder.btnBorderColor = btnBorderColor; return this; } - public Builder10 btnBorderRadius(String btnBorderRadius){ + public LocalInAppOptionalBuilder btnBorderRadius(String btnBorderRadius){ this.builder.btnBorderRadius = btnBorderRadius; return this; } @@ -203,6 +209,9 @@ public String btnTextColor() { public String btnBackgroundColor() { return this.btnBackgroundColor; } + public String image() { + return this.image; + } public String btnBorderColor() { return this.btnBorderColor; } @@ -219,7 +228,8 @@ public String toString() { this.followDeviceOrientation + ", positiveBtnText=" + this.positiveBtnText + ", negativeBtnText=" + this.negativeBtnText + ", btnTextColor=" + this.btnTextColor + ", btnBackgroundColor=" + this.btnBackgroundColor + - ", btnBorderColor=" + this.btnBorderColor + ", btnBorderRadius=" + this.btnBorderRadius + ")"; + ", image=" + this.image + ", btnBorderColor=" + this.btnBorderColor + + ", btnBorderRadius=" + this.btnBorderRadius + ")"; } @Override @@ -235,6 +245,7 @@ public boolean equals(Object o) { Objects.equals(negativeBtnText, that.negativeBtnText) && Objects.equals(btnTextColor, that.btnTextColor) && Objects.equals(btnBackgroundColor, that.btnBackgroundColor) && + Objects.equals(image, that.image) && Objects.equals(btnBorderColor, that.btnBorderColor) && Objects.equals(btnBorderRadius, that.btnBorderRadius); } @@ -243,6 +254,6 @@ public boolean equals(Object o) { public int hashCode() { return Objects.hash(titleText, titleTextColor, bodyText, bodyTextColor, backgroundColor, followDeviceOrientation, positiveBtnText, negativeBtnText, btnTextColor, - btnBackgroundColor, btnBorderColor, btnBorderRadius); + btnBackgroundColor, image, btnBorderColor, btnBorderRadius); } } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index dbc02b704..0c8e67ed7 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -606,9 +606,6 @@ public CTInAppNotification configureAlertLocalInApp(CTAlertLocalInAppBuilder ale public CTInAppNotification configureHalfInterstitialLocalInApp (CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder, int deviceInfo){ - //check how many times have they called via local builder. -// boolean,count TODO - this.id = ""; this.campaignId = ""; this.type = HALF_INTERSTITIAL_LOCAL_IN_APP; @@ -644,10 +641,9 @@ public CTInAppNotification configureHalfInterstitialLocalInApp (CTHalfInterstiti this.hideCloseButton = true; - - //CTINAPPNOTIFMedia obj//1.local image in case of offline//TODO - //2.support for URI - //3. In case of failure in loading img should we load a placeholder img in layout. + if (halfInterstitialLocalInAppBuilder.image() != null){ + setupInAppMediaImage(halfInterstitialLocalInAppBuilder.image()); + } setupInAppActionButtons(halfInterstitialLocalInAppBuilder.positiveBtnText(), halfInterstitialLocalInAppBuilder.negativeBtnText(), @@ -659,6 +655,20 @@ public CTInAppNotification configureHalfInterstitialLocalInApp (CTHalfInterstiti return this; } + private void setupInAppMediaImage(String imageUrl) { + CTInAppNotificationMedia portraitMedia = new CTInAppNotificationMedia() + .initWithLocalData(imageUrl, Configuration.ORIENTATION_PORTRAIT); + if (portraitMedia != null) { + mediaList.add(portraitMedia); + } + + CTInAppNotificationMedia landscapeMedia = new CTInAppNotificationMedia() + .initWithLocalData(imageUrl, Configuration.ORIENTATION_LANDSCAPE); + if (landscapeMedia != null) { + mediaList.add(landscapeMedia); + } + } + private void setupInAppActionButtons(String positiveBtnText, String negativeBtnText, String btnBackgroundColor, String btnTextColor, String btnBorderColor, diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java index aa354f5ea..f8c1f99fa 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java @@ -102,6 +102,20 @@ CTInAppNotificationMedia initWithJSON(JSONObject mediaObject, int orientation) { } } + CTInAppNotificationMedia initWithLocalData(String imgURI, int orientation) { + this.orientation = orientation; + this.contentType = "image"; + if (!imgURI.isEmpty()) { + this.mediaUrl = imgURI; + this.cacheKey = UUID.randomUUID().toString(); + } + if (contentType.isEmpty()) { + return null; + } else { + return this; + } + } + boolean isAudio() { String contentType = this.getContentType(); return contentType != null && this.mediaUrl != null && contentType.startsWith("audio"); diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index abc491fee..70d03ff23 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -327,15 +327,16 @@ class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() "100"-> { val builder = CTHalfInterstitialLocalInAppBuilder.builder() .titleText("Get Notified") - .titleTextColor(Constants.WHITE) + .titleTextColor(Constants.BLACK) .bodyText("Please enable notifications on your device to use Push Notifications.") - .bodyTextColor(Constants.WHITE) - .backgroundColor(Constants.BLACK) - .followDeviceOrientation(false) + .bodyTextColor(Constants.BLACK) + .backgroundColor(Constants.WHITE) + .followDeviceOrientation(true) .positiveBtnText("Allow") .negativeBtnText("Cancel") .btnTextColor(Constants.WHITE) .btnBackgroundColor(Constants.LIGHT_BLUE) + .image("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png") .build() cleverTapAPI?.promptHalfInterstitialPushPrimer(builder) } @@ -343,7 +344,7 @@ class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() "101"->{ val builder = CTAlertLocalInAppBuilder.builder().titleText("Get Notified") .bodyText("Please enable notifications on your device to use Push Notifications.") - .followDeviceOrientation(true) + .followDeviceOrientation(false) .positiveBtnText("Allow") .negativeBtnText("Cancel") .build() From b29fb47d04624bdcc20f3a0d55e4bce1a54cac59 Mon Sep 17 00:00:00 2001 From: William John Date: Thu, 29 Sep 2022 13:41:07 +0530 Subject: [PATCH 12/58] task(SDK-1970)-Add public method to check notification permission status --- .../clevertap/android/sdk/CleverTapAPI.java | 38 ++++++++------ .../sdk/InAppNotificationActivity.java | 9 ++++ .../android/sdk/inapp/InAppController.java | 10 ++++ .../demo/ui/main/HomeScreenViewModel.kt | 50 +++++++++++-------- 4 files changed, 71 insertions(+), 36 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index d7d65ba8a..a31efaf60 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -2,6 +2,7 @@ import static android.content.Context.NOTIFICATION_SERVICE; import static com.clevertap.android.sdk.Utils.getDCDomain; +import static com.clevertap.android.sdk.Utils.isAndroid13; import static com.clevertap.android.sdk.pushnotification.PushConstants.FCM_LOG_TAG; import static com.clevertap.android.sdk.pushnotification.PushConstants.LOG_TAG; import static com.clevertap.android.sdk.pushnotification.PushConstants.PushType.FCM; @@ -1034,29 +1035,36 @@ public static void tokenRefresh(Context context, String token, PushType pushType } } + public boolean isNotificationPermissionGranted(){ + if (isAndroid13(context)) { + return coreState.getInAppController().isNotificationPermissionGranted(); + }else{ + return false; + } + } + public void promptHalfInterstitialPushPrimer(CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder){ - coreState.getInAppController().promptPushPrimer(halfInterstitialLocalInAppBuilder); + if (isAndroid13(context)) { + coreState.getInAppController().promptPushPrimer(halfInterstitialLocalInAppBuilder); + }else{ + Logger.v("Ensure your app support Android 13 to verify permission access for notifications."); + } } public void promptAlertPushPrimer(CTAlertLocalInAppBuilder alertLocalInAppBuilder){ - coreState.getInAppController().promptPushPrimer(alertLocalInAppBuilder); + if (isAndroid13(context)) { + coreState.getInAppController().promptPushPrimer(alertLocalInAppBuilder); + }else{ + Logger.v("Ensure your app support Android 13 to verify permission access for notifications."); + } } public void promptForNotificationPermission(){ - if (instances == null) { - return; - } - - for (String accountId : CleverTapAPI.instances.keySet()) { - CleverTapAPI instance = CleverTapAPI.instances.get(accountId); - try { - if (instance != null) { - instance.coreState.getInAppController().promptPermission(); - } - } catch (Throwable t) { - // Ignore - } + if (isAndroid13(context)){//TODO check for multi instance support + coreState.getInAppController().promptPermission(); + }else{ + Logger.v("Ensure your app support Android 13 to verify permission access for notifications."); } } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index 1a6f8c402..ba96572d9 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -2,6 +2,7 @@ import static com.clevertap.android.sdk.Utils.isAndroid13; +import android.Manifest; import android.app.Activity; import android.app.AlertDialog; import android.content.Context; @@ -14,7 +15,9 @@ import android.view.WindowManager; import androidx.annotation.NonNull; +import androidx.annotation.RequiresApi; import androidx.core.app.ActivityCompat; +import androidx.core.content.ContextCompat; import androidx.fragment.app.FragmentActivity; import com.clevertap.android.sdk.inapp.AlertDialogPromptForSettings; @@ -235,6 +238,12 @@ public static void startPrompt(Activity activity, CleverTapInstanceConfig config } } + @RequiresApi(api = 33) + public static int isNotificationPermissionGranted(Activity activity){ + return ContextCompat.checkSelfPermission( + activity, Manifest.permission.POST_NOTIFICATIONS); + } + void didDismiss(Bundle data) { if (isAlertVisible) { isAlertVisible = false; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 3c7e0dad2..2e166395e 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -4,8 +4,11 @@ import android.content.Context; import android.content.Intent; import android.content.SharedPreferences; +import android.content.pm.PackageManager; import android.os.Bundle; import android.os.Looper; + +import androidx.annotation.RequiresApi; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentTransaction; @@ -210,6 +213,13 @@ public void promptPermission(){ config); } + @RequiresApi(api = 33) + public boolean isNotificationPermissionGranted(){ + int permissionStatus = InAppNotificationActivity.isNotificationPermissionGranted( + Objects.requireNonNull(CoreMetaData.getCurrentActivity())); + return permissionStatus == PackageManager.PERMISSION_GRANTED; + } + public void discardInApps() { this.inAppState = InAppState.DISCARDED; logger.verbose(config.getAccountId(), "InAppState is DISCARDED"); diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index 70d03ff23..4f8e43a89 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -325,30 +325,38 @@ class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() "918"-> cleverTapAPI?.pushEvent("Send Input Box Reminder DOC false") "919"-> cleverTapAPI?.pushEvent("Send Three CTA Notification") "100"-> { - val builder = CTHalfInterstitialLocalInAppBuilder.builder() - .titleText("Get Notified") - .titleTextColor(Constants.BLACK) - .bodyText("Please enable notifications on your device to use Push Notifications.") - .bodyTextColor(Constants.BLACK) - .backgroundColor(Constants.WHITE) - .followDeviceOrientation(true) - .positiveBtnText("Allow") - .negativeBtnText("Cancel") - .btnTextColor(Constants.WHITE) - .btnBackgroundColor(Constants.LIGHT_BLUE) - .image("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png") - .build() - cleverTapAPI?.promptHalfInterstitialPushPrimer(builder) + if (cleverTapAPI?.isNotificationPermissionGranted == false){ + val builder = CTHalfInterstitialLocalInAppBuilder.builder() + .titleText("Get Notified") + .titleTextColor(Constants.BLACK) + .bodyText("Please enable notifications on your device to use Push Notifications.") + .bodyTextColor(Constants.BLACK) + .backgroundColor(Constants.WHITE) + .followDeviceOrientation(true) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .btnTextColor(Constants.WHITE) + .btnBackgroundColor(Constants.LIGHT_BLUE) + /*.image("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png")*/ + .build() + cleverTapAPI.promptHalfInterstitialPushPrimer(builder) + }else{ + Log.v("HomeScreenViewModel","Notification permission is already granted.") + } } "101"->{ - val builder = CTAlertLocalInAppBuilder.builder().titleText("Get Notified") - .bodyText("Please enable notifications on your device to use Push Notifications.") - .followDeviceOrientation(false) - .positiveBtnText("Allow") - .negativeBtnText("Cancel") - .build() - cleverTapAPI?.promptAlertPushPrimer(builder) + if (cleverTapAPI?.isNotificationPermissionGranted == false) { + val builder = CTAlertLocalInAppBuilder.builder().titleText("Get Notified") + .bodyText("Please enable notifications on your device to use Push Notifications.") + .followDeviceOrientation(false) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .build() + cleverTapAPI.promptAlertPushPrimer(builder) + }else{ + Log.v("HomeScreenViewModel","Notification permission is already granted.") + } } "102"->{ From 884ddb8330b2149e4cc5c47e48813f0d62e95156 Mon Sep 17 00:00:00 2001 From: William John Date: Thu, 29 Sep 2022 18:47:55 +0530 Subject: [PATCH 13/58] task(SDK-1970)- Add public listener for push primer CTA's click --- .../android/sdk/BaseCallbackManager.java | 4 ++++ .../clevertap/android/sdk/CallbackManager.java | 14 ++++++++++++++ .../clevertap/android/sdk/CleverTapAPI.java | 5 +++++ .../android/sdk/InAppNotificationActivity.java | 18 +++++++++--------- .../android/sdk/PushPrimerButtonListener.java | 10 ++++++++++ .../android/sdk/inapp/CTInAppBaseFragment.java | 12 ++++++------ .../sdk/inapp/CTInAppBaseFullHtmlFragment.java | 2 +- .../inapp/CTInAppBasePartialHtmlFragment.java | 2 +- .../android/sdk/inapp/InAppController.java | 14 +++++++++++++- .../android/sdk/inapp/InAppListener.java | 2 +- .../com/clevertap/demo/HomeScreenActivity.kt | 18 +++++++++++++++++- 11 files changed, 81 insertions(+), 20 deletions(-) create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/PushPrimerButtonListener.java diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java index 8b7c5abf3..5a76475bb 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java @@ -26,6 +26,8 @@ public abstract class BaseCallbackManager { public abstract InAppNotificationButtonListener getInAppNotificationButtonListener(); + public abstract PushPrimerButtonListener getPushPrimerButtonListener(); + public abstract InAppNotificationListener getInAppNotificationListener(); public abstract PushPermissionNotificationResponseListener getPushPermissionNotificationResponseListener(); @@ -60,6 +62,8 @@ public abstract class BaseCallbackManager { public abstract void setInAppNotificationButtonListener( InAppNotificationButtonListener inAppNotificationButtonListener); + public abstract void setPushPrimerButtonListener(PushPrimerButtonListener pushPrimerButtonListener); + public abstract void setInAppNotificationListener(InAppNotificationListener inAppNotificationListener); public abstract void setPushPermissionNotificationResponseListener(PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java index b3ecedf52..7bc3eafc7 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java @@ -25,6 +25,7 @@ public class CallbackManager extends BaseCallbackManager { private DCDomainCallback dcDomainCallback; private WeakReference inAppNotificationButtonListener; + private WeakReference pushPrimerButtonListener; private InAppNotificationListener inAppNotificationListener; @@ -122,12 +123,25 @@ public InAppNotificationButtonListener getInAppNotificationButtonListener() { return null; } + @Override + public PushPrimerButtonListener getPushPrimerButtonListener() { + if (pushPrimerButtonListener != null && pushPrimerButtonListener.get() != null){ + return pushPrimerButtonListener.get(); + } + return null; + } + @Override public void setInAppNotificationButtonListener( InAppNotificationButtonListener inAppNotificationButtonListener) { this.inAppNotificationButtonListener = new WeakReference<>(inAppNotificationButtonListener); } + @Override + public void setPushPrimerButtonListener(PushPrimerButtonListener pushPrimerButtonListener) { + this.pushPrimerButtonListener = new WeakReference<>(pushPrimerButtonListener); + } + @Override public InAppNotificationListener getInAppNotificationListener() { return inAppNotificationListener; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index a31efaf60..bcf8ae08e 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -2459,6 +2459,11 @@ public void setInAppNotificationButtonListener(InAppNotificationButtonListener l coreState.getCallbackManager().setInAppNotificationButtonListener(listener); } + @SuppressWarnings("unused") + public void setPushPrimerButtonListener(PushPrimerButtonListener listener) { + coreState.getCallbackManager().setPushPrimerButtonListener(listener); + } + @SuppressWarnings("unused") public void setInboxMessageButtonListener(InboxMessageButtonListener listener) { this.inboxMessageButtonListener = new WeakReference<>(listener); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index ba96572d9..799c88926 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -143,8 +143,8 @@ public void finish() { @Override public void inAppNotificationDidClick(CTInAppNotification inAppNotification, Bundle formData, - HashMap keyValueMap) { - didClick(formData, keyValueMap); + HashMap keyValueMap, int btnClickIndex) { + didClick(formData, keyValueMap, btnClickIndex); } @Override @@ -171,10 +171,10 @@ public void setTheme(int resid) { super.setTheme(android.R.style.Theme_Translucent_NoTitleBar); } - void didClick(Bundle data, HashMap keyValueMap) { + void didClick(Bundle data, HashMap keyValueMap, int btnClickIndex) { InAppListener listener = getListener(); if (listener != null) { - listener.inAppNotificationDidClick(inAppNotification, data, keyValueMap); + listener.inAppNotificationDidClick(inAppNotification, data, keyValueMap,btnClickIndex); } } @@ -352,7 +352,7 @@ public void onClick(DialogInterface dialogInterface, int i) { inAppNotification.getCampaignId()); data.putString("wzrk_c2a", inAppNotification.getButtons().get(0).getText()); - didClick(data, null); + didClick(data, null,0); String actionUrl = inAppNotification.getButtons().get(0) .getActionUrl(); if (actionUrl != null) { @@ -378,7 +378,7 @@ public void onClick(DialogInterface dialog, int which) { inAppNotification.getCampaignId()); data.putString("wzrk_c2a", inAppNotification.getButtons().get(1).getText()); - didClick(data, null); + didClick(data, null,1); String actionUrl = inAppNotification.getButtons().get(1).getActionUrl(); if (actionUrl != null) { fireUrlThroughIntent(actionUrl, data); @@ -402,7 +402,7 @@ public void onClick(DialogInterface dialogInterface, int i) { inAppNotification.getCampaignId()); data.putString("wzrk_c2a", inAppNotification.getButtons().get(0).getText()); - didClick(data, null); + didClick(data, null,0); String actionUrl = inAppNotification.getButtons().get(0) .getActionUrl(); if (actionUrl != null) { @@ -424,7 +424,7 @@ public void onClick(DialogInterface dialog, int which) { inAppNotification.getCampaignId()); data.putString("wzrk_c2a", inAppNotification.getButtons().get(1).getText()); - didClick(data, null); + didClick(data, null,1); String actionUrl = inAppNotification.getButtons().get(1).getActionUrl(); if (actionUrl != null) { fireUrlThroughIntent(actionUrl, data); @@ -446,7 +446,7 @@ public void onClick(DialogInterface dialogInterface, int i) { data.putString(Constants.NOTIFICATION_ID_TAG, inAppNotification.getCampaignId()); data.putString("wzrk_c2a", inAppNotification.getButtons().get(2).getText()); - didClick(data, null); + didClick(data, null,2); String actionUrl = inAppNotification.getButtons().get(2).getActionUrl(); if (actionUrl != null) { fireUrlThroughIntent(actionUrl, data); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPrimerButtonListener.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPrimerButtonListener.java new file mode 100644 index 000000000..63acdfe6a --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPrimerButtonListener.java @@ -0,0 +1,10 @@ +package com.clevertap.android.sdk; + +import com.clevertap.android.sdk.inapp.CTInAppNotification; + +public interface PushPrimerButtonListener { + + void onPositiveButtonClick(CTInAppNotification ctInAppNotification); + + void onNegativeButtonClick(CTInAppNotification ctInAppNotification); +} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java index fbe0b91ef..f89d10110 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java @@ -61,10 +61,10 @@ public void onViewCreated(View view, @Nullable Bundle savedInstanceState) { abstract void cleanup(); - void didClick(Bundle data, HashMap keyValueMap) { + void didClick(int index, Bundle data, HashMap keyValueMap) { InAppListener listener = getListener(); if (listener != null) { - listener.inAppNotificationDidClick(inAppNotification, data, keyValueMap); + listener.inAppNotificationDidClick(inAppNotification, data, keyValueMap,index); } } @@ -139,13 +139,12 @@ void handleButtonClickAtIndex(int index) { data.putString(Constants.NOTIFICATION_ID_TAG, inAppNotification.getCampaignId()); data.putString(Constants.KEY_C2A, button.getText()); - didClick(data, button.getKeyValues()); - -// check API and toolsSDK version, inapp type, whether the btn was meant for PN. -// requestPermissions() + didClick(index,data, button.getKeyValues()); if (index == 0 && inAppNotification.isLocalInApp()) { ((InAppNotificationActivity) context).prompt(); + }else if (index == 1 && inAppNotification.isLocalInApp()){ + didDismiss(null); }else { String actionUrl = button.getActionUrl(); if (actionUrl != null) { @@ -154,6 +153,7 @@ void handleButtonClickAtIndex(int index) { } didDismiss(data); } + } catch (Throwable t) { config.getLogger().debug("Error handling notification button click: " + t.getCause()); didDismiss(null); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFullHtmlFragment.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFullHtmlFragment.java index 565774384..7a67cad23 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFullHtmlFragment.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFullHtmlFragment.java @@ -50,7 +50,7 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { } } - didClick(formData, null); + didClick(-1, formData, null); Logger.d("Executing call to action for in-app: " + url); fireUrlThroughIntent(url, formData); } catch (Throwable t) { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBasePartialHtmlFragment.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBasePartialHtmlFragment.java index 4a4f7ca8c..3d85be794 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBasePartialHtmlFragment.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBasePartialHtmlFragment.java @@ -48,7 +48,7 @@ public boolean shouldOverrideUrlLoading(WebView view, String url) { } } - didClick(formData, null); + didClick(-1, formData, null); Logger.d("Executing call to action for in-app: " + url); fireUrlThroughIntent(url, formData); } catch (Throwable t) { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 2e166395e..23e196ebe 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -227,8 +227,20 @@ public void discardInApps() { @Override public void inAppNotificationDidClick(CTInAppNotification inAppNotification, Bundle formData, - HashMap keyValueMap) { + HashMap keyValueMap, int btnClickIndex) { analyticsManager.pushInAppNotificationStateEvent(true, inAppNotification, formData); + if (inAppNotification.isLocalInApp()){ + if (btnClickIndex == 0){ + if (callbackManager.getPushPrimerButtonListener() != null) { + callbackManager.getPushPrimerButtonListener().onPositiveButtonClick(inAppNotification); + } + }else if (btnClickIndex == 1){ + if (callbackManager.getPushPrimerButtonListener() != null) { + callbackManager.getPushPrimerButtonListener().onNegativeButtonClick(inAppNotification); + } + } + } + if (keyValueMap != null && !keyValueMap.isEmpty()) { if (callbackManager.getInAppNotificationButtonListener() != null) { callbackManager.getInAppNotificationButtonListener().onInAppButtonClick(keyValueMap); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppListener.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppListener.java index 432099e8b..7de25453e 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppListener.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppListener.java @@ -7,7 +7,7 @@ public interface InAppListener { void inAppNotificationDidClick(CTInAppNotification inAppNotification, Bundle formData, - HashMap keyValueMap); + HashMap keyValueMap, int btnClickIndex); void inAppNotificationDidDismiss(Context context, CTInAppNotification inAppNotification, Bundle formData); diff --git a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt index 4e80a002a..590f76e21 100644 --- a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt +++ b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt @@ -25,11 +25,13 @@ import net.khirr.android.privacypolicy.PrivacyPolicyDialog.OnClickListener import com.clevertap.demo.ui.main.NotificationUtils import org.json.JSONObject +import java.util.HashMap private const val TAG = "HomeScreenActivity" class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitListener, CTProductConfigListener, - CTFeatureFlagsListener, SyncListener, InAppNotificationListener, PushPermissionNotificationResponseListener { + CTFeatureFlagsListener, SyncListener, InAppNotificationListener, PushPermissionNotificationResponseListener, + InAppNotificationButtonListener, PushPrimerButtonListener { var cleverTapDefaultInstance: CleverTapAPI? = null @@ -145,6 +147,8 @@ class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitList pushPermissionNotificationResponseListener = this@HomeScreenActivity + setPushPrimerButtonListener(this@HomeScreenActivity) + } //With CleverTap Android SDK v3.2.0 you can create additional instances to send data to multiple CleverTap accounts @@ -257,4 +261,16 @@ class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitList override fun response(accepted: Boolean) { Log.i(TAG, "InApp---> response() called $accepted") } + + override fun onInAppButtonClick(payload: HashMap?) { + TODO("Not yet implemented") + } + + override fun onPositiveButtonClick(ctInAppNotification: CTInAppNotification?) { + Log.v(TAG, "onPositiveButtonClick() called") + } + + override fun onNegativeButtonClick(ctInAppNotification: CTInAppNotification?) { + Log.v(TAG, "onNegativeButtonClick() called") + } } \ No newline at end of file From fb314a728a9ad8c5e424fdb870a634871d67d334 Mon Sep 17 00:00:00 2001 From: William John Date: Mon, 3 Oct 2022 13:52:42 +0530 Subject: [PATCH 14/58] task(SDK-1970)- Create single builder for both local IAM, refactor InAppController to accept only jsonObj for creating local IAM --- .../clevertap/android/sdk/CleverTapAPI.java | 19 +- .../sdk/inapp/CTAlertLocalInAppBuilder.java | 129 --------- .../CTHalfInterstitialLocalInAppBuilder.java | 259 ------------------ .../sdk/inapp/CTInAppNotification.java | 111 +------- .../sdk/inapp/CTLocalInAppBuilder.java | 237 ++++++++++++++++ .../android/sdk/inapp/InAppController.java | 59 +--- .../com/clevertap/demo/ViewModelFactory.kt | 8 +- .../demo/ui/main/HomeScreenFragment.kt | 2 +- .../demo/ui/main/HomeScreenViewModel.kt | 45 +-- 9 files changed, 278 insertions(+), 591 deletions(-) delete mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java delete mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index bcf8ae08e..bf06d3e47 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -33,8 +33,6 @@ import com.clevertap.android.sdk.events.EventDetail; import com.clevertap.android.sdk.events.EventGroup; import com.clevertap.android.sdk.featureFlags.CTFeatureFlagsController; -import com.clevertap.android.sdk.inapp.CTAlertLocalInAppBuilder; -import com.clevertap.android.sdk.inapp.CTHalfInterstitialLocalInAppBuilder; import com.clevertap.android.sdk.inbox.CTInboxActivity; import com.clevertap.android.sdk.inbox.CTInboxMessage; import com.clevertap.android.sdk.inbox.CTMessageDAO; @@ -1043,20 +1041,11 @@ public boolean isNotificationPermissionGranted(){ } } - public void promptHalfInterstitialPushPrimer(CTHalfInterstitialLocalInAppBuilder - halfInterstitialLocalInAppBuilder){ + public void promptPushPrimer(JSONObject jsonObject) { if (isAndroid13(context)) { - coreState.getInAppController().promptPushPrimer(halfInterstitialLocalInAppBuilder); + coreState.getInAppController().promptPushPrimer(jsonObject); }else{ - Logger.v("Ensure your app support Android 13 to verify permission access for notifications."); - } - } - - public void promptAlertPushPrimer(CTAlertLocalInAppBuilder alertLocalInAppBuilder){ - if (isAndroid13(context)) { - coreState.getInAppController().promptPushPrimer(alertLocalInAppBuilder); - }else{ - Logger.v("Ensure your app support Android 13 to verify permission access for notifications."); + Logger.v("Ensure your app supports Android 13 to verify permission access for notifications."); } } @@ -1064,7 +1053,7 @@ public void promptForNotificationPermission(){ if (isAndroid13(context)){//TODO check for multi instance support coreState.getInAppController().promptPermission(); }else{ - Logger.v("Ensure your app support Android 13 to verify permission access for notifications."); + Logger.v("Ensure your app supports Android 13 to verify permission access for notifications."); } } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java deleted file mode 100644 index b97237add..000000000 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTAlertLocalInAppBuilder.java +++ /dev/null @@ -1,129 +0,0 @@ -package com.clevertap.android.sdk.inapp; - -import androidx.annotation.NonNull; - -import java.util.Objects; - -public class CTAlertLocalInAppBuilder { - - private final String titleText; - private final String bodyText; - private final boolean followDeviceOrientation; - private final String positiveBtnText; - private final String negativeBtnText; - - CTAlertLocalInAppBuilder(Builder.Builder1 builder) { - this.titleText = builder.titleText; - this.bodyText = builder.bodyText; - this.followDeviceOrientation = builder.followDeviceOrientation; - this.positiveBtnText = builder.positiveBtnText; - this.negativeBtnText = builder.negativeBtnText; - } - public static Builder builder() { - return new Builder(); - } - - public static final class Builder { - public Builder1 titleText(String titleText) { - return new Builder1(titleText); - } - public static final class Builder1 { - final String titleText; - String bodyText; - boolean followDeviceOrientation; - String positiveBtnText; - String negativeBtnText; - - private Builder1(String titleText) { - this.titleText = titleText; - } - public Builder2 bodyText(String bodyText) { - this.bodyText = bodyText; - return new Builder2(Builder1.this); - } - } - public static final class Builder2 { - final Builder1 builder; - - private Builder2(Builder1 builder) { - this.builder = builder; - } - public Builder3 followDeviceOrientation(boolean followDeviceOrientation) { - this.builder.followDeviceOrientation = followDeviceOrientation; - return new Builder3(this.builder); - } - } - public static final class Builder3 { - final Builder1 builder; - - private Builder3(Builder1 builder) { - this.builder = builder; - } - public Builder4 positiveBtnText(String positiveBtnText) { - this.builder.positiveBtnText = positiveBtnText; - return new Builder4(this.builder); - } - } - public static final class Builder4 { - final Builder1 builder; - - private Builder4(Builder1 builder) { - this.builder = builder; - } - public Builder5 negativeBtnText(String negativeBtnText) { - this.builder.negativeBtnText = negativeBtnText; - return new Builder5(this.builder); - } - } - public static final class Builder5 { - final Builder1 builder; - - private Builder5(Builder1 builder) { - this.builder = builder; - } - public CTAlertLocalInAppBuilder build() { - return new CTAlertLocalInAppBuilder(this.builder); - } - } - } - - public String titleText() { - return this.titleText; - } - public String bodyText() { - return this.bodyText; - } - public boolean followDeviceOrientation() { - return this.followDeviceOrientation; - } - public String positiveBtnText() { - return this.positiveBtnText; - } - public String negativeBtnText() { - return this.negativeBtnText; - } - - @NonNull - @Override - public String toString() { - return "CTAlertLocalInAppBuilder(titleText=" + this.titleText + ", bodyText=" + this.bodyText + - ", followDeviceOrientation=" + this.followDeviceOrientation + ", positiveBtnText=" + - this.positiveBtnText + ", negativeBtnText=" + this.negativeBtnText + ")"; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CTAlertLocalInAppBuilder that = (CTAlertLocalInAppBuilder) o; - return followDeviceOrientation == that.followDeviceOrientation && - Objects.equals(titleText, that.titleText) && Objects.equals(bodyText, that.bodyText) && - Objects.equals(positiveBtnText, that.positiveBtnText) && - Objects.equals(negativeBtnText, that.negativeBtnText); - } - - @Override - public int hashCode() { - return Objects.hash(titleText, bodyText, followDeviceOrientation, positiveBtnText, negativeBtnText); - } -} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java deleted file mode 100644 index 717f5603a..000000000 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTHalfInterstitialLocalInAppBuilder.java +++ /dev/null @@ -1,259 +0,0 @@ -package com.clevertap.android.sdk.inapp; - - -import androidx.annotation.NonNull; - -import java.util.Objects; - -public class CTHalfInterstitialLocalInAppBuilder { - - private final String titleText; - private final String titleTextColor; - private final String bodyText; - private final String bodyTextColor; - private final String backgroundColor; - private final boolean followDeviceOrientation; - private final String positiveBtnText; - private final String negativeBtnText; - private final String btnTextColor; - private final String btnBackgroundColor; - private final String btnBorderColor;// Optional - private final String btnBorderRadius;// Optional - private final String image;// Optional - - CTHalfInterstitialLocalInAppBuilder(Builder.LocalInAppBuilder localInAppBuilder) { - this.titleText = localInAppBuilder.titleText; - this.titleTextColor = localInAppBuilder.titleTextColor; - this.bodyText = localInAppBuilder.bodyText; - this.bodyTextColor = localInAppBuilder.bodyTextColor; - this.backgroundColor = localInAppBuilder.backgroundColor; - this.followDeviceOrientation = localInAppBuilder.followDeviceOrientation; - this.positiveBtnText = localInAppBuilder.positiveBtnText; - this.negativeBtnText = localInAppBuilder.negativeBtnText; - this.btnTextColor = localInAppBuilder.btnTextColor; - this.btnBackgroundColor = localInAppBuilder.btnBackgroundColor; - this.btnBorderColor = localInAppBuilder.btnBorderColor; - this.btnBorderRadius = localInAppBuilder.btnBorderRadius; - this.image = localInAppBuilder.image; - } - public static Builder builder() { - return new Builder(); - } - - public static final class Builder { - public LocalInAppBuilder titleText(String titleText) { - return new LocalInAppBuilder(titleText); - } - public static final class LocalInAppBuilder { - final String titleText; - String titleTextColor; - String bodyText; - String bodyTextColor; - String backgroundColor; - boolean followDeviceOrientation; - String positiveBtnText; - String negativeBtnText; - String btnTextColor; - String btnBackgroundColor; - String btnBorderColor; - String btnBorderRadius; - String image; - - private LocalInAppBuilder(String titleText) { - this.titleText = titleText; - } - public TitleTextColorBuilder titleTextColor(String titleTextColor) { - this.titleTextColor = titleTextColor; - return new TitleTextColorBuilder(LocalInAppBuilder.this); - } - } - public static final class TitleTextColorBuilder { - final LocalInAppBuilder builder; - - private TitleTextColorBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public BodyTextBuilder bodyText(String bodyText) { - this.builder.bodyText = bodyText; - return new BodyTextBuilder(this.builder); - } - } - public static final class BodyTextBuilder { - final LocalInAppBuilder builder; - - private BodyTextBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public BodyTextColorBuilder bodyTextColor(String bodyTextColor) { - this.builder.bodyTextColor = bodyTextColor; - return new BodyTextColorBuilder(this.builder); - } - } - public static final class BodyTextColorBuilder { - final LocalInAppBuilder builder; - - private BodyTextColorBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public BackgroundColorBuilder backgroundColor(String backgroundColor) { - this.builder.backgroundColor = backgroundColor; - return new BackgroundColorBuilder(this.builder); - } - } - public static final class BackgroundColorBuilder { - final LocalInAppBuilder builder; - - private BackgroundColorBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public FollowDeviceOrientationBuilder followDeviceOrientation(boolean followDeviceOrientation) { - this.builder.followDeviceOrientation = followDeviceOrientation; - return new FollowDeviceOrientationBuilder(this.builder); - } - } - public static final class FollowDeviceOrientationBuilder { - final LocalInAppBuilder builder; - - private FollowDeviceOrientationBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public PositiveBtnTextBuilder positiveBtnText(String positiveBtnText) { - this.builder.positiveBtnText = positiveBtnText; - return new PositiveBtnTextBuilder(this.builder); - } - } - public static final class PositiveBtnTextBuilder { - final LocalInAppBuilder builder; - - private PositiveBtnTextBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public NegativeBtnTextBuilder negativeBtnText(String negativeBtnText) { - this.builder.negativeBtnText = negativeBtnText; - return new NegativeBtnTextBuilder(this.builder); - } - } - public static final class NegativeBtnTextBuilder { - final LocalInAppBuilder builder; - - private NegativeBtnTextBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public BtnTextColorBuilder btnTextColor(String btnTextColor) { - this.builder.btnTextColor = btnTextColor; - return new BtnTextColorBuilder(this.builder); - } - } - public static final class BtnTextColorBuilder { - final LocalInAppBuilder builder; - - private BtnTextColorBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public LocalInAppOptionalBuilder btnBackgroundColor(String btnBackgroundColor) { - this.builder.btnBackgroundColor = btnBackgroundColor; - return new LocalInAppOptionalBuilder(this.builder); - } - } - public static final class LocalInAppOptionalBuilder { - final LocalInAppBuilder builder; - - private LocalInAppOptionalBuilder(LocalInAppBuilder builder) { - this.builder = builder; - } - public LocalInAppOptionalBuilder image(String image){ - this.builder.image = image; - return this; - } - public LocalInAppOptionalBuilder btnBorderColor(String btnBorderColor){ - this.builder.btnBorderColor = btnBorderColor; - return this; - } - public LocalInAppOptionalBuilder btnBorderRadius(String btnBorderRadius){ - this.builder.btnBorderRadius = btnBorderRadius; - return this; - } - public CTHalfInterstitialLocalInAppBuilder build() { - return new CTHalfInterstitialLocalInAppBuilder(this.builder); - } - } - } - - public String titleText() { - return this.titleText; - } - public String titleTextColor() { - return this.titleTextColor; - } - public String bodyText() { - return this.bodyText; - } - public String bodyTextColor() { - return this.bodyTextColor; - } - public String backgroundColor() { - return this.backgroundColor; - } - public boolean followDeviceOrientation() { - return this.followDeviceOrientation; - } - public String positiveBtnText() { - return this.positiveBtnText; - } - public String negativeBtnText() { - return this.negativeBtnText; - } - public String btnTextColor() { - return this.btnTextColor; - } - public String btnBackgroundColor() { - return this.btnBackgroundColor; - } - public String image() { - return this.image; - } - public String btnBorderColor() { - return this.btnBorderColor; - } - public String btnBorderRadius() { - return this.btnBorderRadius; - } - - @NonNull - @Override - public String toString() { - return "CTHalfInterstitialLocalInAppBuilder(titleText=" + this.titleText + ", titleTextColor=" + - this.titleTextColor + ", bodyText=" + this.bodyText + ", bodyTextColor=" + this.bodyTextColor + - ", backgroundColor=" + this.backgroundColor + ", followDeviceOrientation=" + - this.followDeviceOrientation + ", positiveBtnText=" + this.positiveBtnText + - ", negativeBtnText=" + this.negativeBtnText + ", btnTextColor=" + - this.btnTextColor + ", btnBackgroundColor=" + this.btnBackgroundColor + - ", image=" + this.image + ", btnBorderColor=" + this.btnBorderColor + - ", btnBorderRadius=" + this.btnBorderRadius + ")"; - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (o == null || getClass() != o.getClass()) return false; - CTHalfInterstitialLocalInAppBuilder that = (CTHalfInterstitialLocalInAppBuilder) o; - return followDeviceOrientation == that.followDeviceOrientation && - Objects.equals(titleText, that.titleText) && Objects.equals(titleTextColor, that.titleTextColor) - && Objects.equals(bodyText, that.bodyText) && Objects.equals(bodyTextColor, that.bodyTextColor) - && Objects.equals(backgroundColor, that.backgroundColor) && - Objects.equals(positiveBtnText, that.positiveBtnText) && - Objects.equals(negativeBtnText, that.negativeBtnText) && - Objects.equals(btnTextColor, that.btnTextColor) && - Objects.equals(btnBackgroundColor, that.btnBackgroundColor) && - Objects.equals(image, that.image) && - Objects.equals(btnBorderColor, that.btnBorderColor) && - Objects.equals(btnBorderRadius, that.btnBorderRadius); - } - - @Override - public int hashCode() { - return Objects.hash(titleText, titleTextColor, bodyText, bodyTextColor, backgroundColor, - followDeviceOrientation, positiveBtnText, negativeBtnText, btnTextColor, - btnBackgroundColor, image, btnBorderColor, btnBorderRadius); - } -} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index 0c8e67ed7..d72f7b6ba 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -9,7 +9,6 @@ import androidx.annotation.RestrictTo; import androidx.annotation.RestrictTo.Scope; import com.clevertap.android.sdk.Constants; -import com.clevertap.android.sdk.DeviceInfo; import com.clevertap.android.sdk.Logger; import com.clevertap.android.sdk.Utils; import com.clevertap.android.sdk.utils.ImageCache; @@ -583,115 +582,6 @@ void prepareForDisplay() { } listener.notificationReady(this); } - public CTInAppNotification configureAlertLocalInApp(CTAlertLocalInAppBuilder alertLocalInAppBuilder, - int deviceInfo){ - this.id = ""; - this.campaignId = ""; - this.type = ALERT_LOCAL_IN_APP; - this.inAppType = CTInAppType.fromString(this.type); - this.isTablet = deviceInfo == DeviceInfo.TABLET; - this.isPortrait = true; - this.isLandscape = alertLocalInAppBuilder.followDeviceOrientation(); - this.isLocalInApp = true; - this.timeToLive = System.currentTimeMillis() + 2 * Constants.ONE_DAY_IN_MILLIS; - this.title = alertLocalInAppBuilder.titleText() != null ? alertLocalInAppBuilder.titleText() : ""; - this.message = alertLocalInAppBuilder.bodyText() != null ? alertLocalInAppBuilder.bodyText() : ""; - - setupInAppActionButtons(alertLocalInAppBuilder.positiveBtnText(), - alertLocalInAppBuilder.negativeBtnText(), - null,null,null,null); - - return this; - } - - public CTInAppNotification configureHalfInterstitialLocalInApp (CTHalfInterstitialLocalInAppBuilder - halfInterstitialLocalInAppBuilder, int deviceInfo){ - this.id = ""; - this.campaignId = ""; - this.type = HALF_INTERSTITIAL_LOCAL_IN_APP; - - - this.excludeFromCaps = false;//Check this withInAppFC Manager - this.totalLifetimeCount = -1;// - this.totalDailyCount = -1;// - - this.inAppType = CTInAppType.fromString(this.type); - this.isTablet = deviceInfo == DeviceInfo.TABLET; - - this.backgroundColor = halfInterstitialLocalInAppBuilder.backgroundColor() != null ? - halfInterstitialLocalInAppBuilder.backgroundColor() : Constants.WHITE; - - this.isPortrait = true; - this.isLandscape = halfInterstitialLocalInAppBuilder.followDeviceOrientation(); - - this.isLocalInApp = true; - this.timeToLive = System.currentTimeMillis() + 2 * Constants.ONE_DAY_IN_MILLIS; - - this.title = halfInterstitialLocalInAppBuilder.titleText() != null ? - halfInterstitialLocalInAppBuilder.titleText() : ""; - this.titleColor = halfInterstitialLocalInAppBuilder.titleTextColor() !=null ? - halfInterstitialLocalInAppBuilder.titleTextColor() - : Constants.BLACK; - - this.message = halfInterstitialLocalInAppBuilder.bodyText() != null ? - halfInterstitialLocalInAppBuilder.bodyText() : ""; - this.messageColor = halfInterstitialLocalInAppBuilder.bodyTextColor() != null ? - halfInterstitialLocalInAppBuilder.bodyTextColor() - : Constants.BLACK; - - this.hideCloseButton = true; - - if (halfInterstitialLocalInAppBuilder.image() != null){ - setupInAppMediaImage(halfInterstitialLocalInAppBuilder.image()); - } - - setupInAppActionButtons(halfInterstitialLocalInAppBuilder.positiveBtnText(), - halfInterstitialLocalInAppBuilder.negativeBtnText(), - halfInterstitialLocalInAppBuilder.btnBackgroundColor(), - halfInterstitialLocalInAppBuilder.btnTextColor(), - halfInterstitialLocalInAppBuilder.btnBorderColor(), - halfInterstitialLocalInAppBuilder.btnBorderRadius()); - - return this; - } - - private void setupInAppMediaImage(String imageUrl) { - CTInAppNotificationMedia portraitMedia = new CTInAppNotificationMedia() - .initWithLocalData(imageUrl, Configuration.ORIENTATION_PORTRAIT); - if (portraitMedia != null) { - mediaList.add(portraitMedia); - } - - CTInAppNotificationMedia landscapeMedia = new CTInAppNotificationMedia() - .initWithLocalData(imageUrl, Configuration.ORIENTATION_LANDSCAPE); - if (landscapeMedia != null) { - mediaList.add(landscapeMedia); - } - } - - private void setupInAppActionButtons(String positiveBtnText, String negativeBtnText, - String btnBackgroundColor, - String btnTextColor, String btnBorderColor, - String btnBorderRadius){ - //Positive Button - CTInAppNotificationButton inAppNotificationPositiveButton = new CTInAppNotificationButton() - .initWithLocalData(positiveBtnText, - btnBackgroundColor,btnTextColor,btnBorderColor,btnBorderRadius); - - if (inAppNotificationPositiveButton != null) { - this.buttons.add(inAppNotificationPositiveButton); - } - - //Negative Button - CTInAppNotificationButton inAppNotificationNegativeButton = new CTInAppNotificationButton() - .initWithLocalData(negativeBtnText, - btnBackgroundColor,btnTextColor, - btnBorderColor,btnBorderRadius); - - if (inAppNotificationNegativeButton != null) { - this.buttons.add(inAppNotificationNegativeButton); - } - } private void configureWithJson(JSONObject jsonObject) { try { @@ -700,6 +590,7 @@ private void configureWithJson(JSONObject jsonObject) { this.campaignId = jsonObject.has(Constants.NOTIFICATION_ID_TAG) ? jsonObject .getString(Constants.NOTIFICATION_ID_TAG) : ""; this.type = jsonObject.getString(Constants.KEY_TYPE); + this.isLocalInApp = jsonObject.has("isLocalInApp") && jsonObject.getBoolean("isLocalInApp"); this.excludeFromCaps = jsonObject.has(Constants.KEY_EFC) && jsonObject.getInt(Constants.KEY_EFC) == 1; this.totalLifetimeCount = jsonObject.has(Constants.KEY_TLC) ? jsonObject.getInt(Constants.KEY_TLC) : -1; this.totalDailyCount = jsonObject.has(Constants.KEY_TDC) ? jsonObject.getInt(Constants.KEY_TDC) : -1; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java new file mode 100644 index 000000000..ab3c92267 --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java @@ -0,0 +1,237 @@ +package com.clevertap.android.sdk.inapp; + + +import android.content.Context; +import com.clevertap.android.sdk.Constants; +import com.clevertap.android.sdk.DeviceInfo; +import org.json.JSONArray; +import org.json.JSONException; +import org.json.JSONObject; + +import java.util.Objects; + +public class CTLocalInAppBuilder { + + private final String localInAppType;//Required + private final JSONObject titleObj;// Required + private final JSONObject messageObj;// Required + private final boolean followDeviceOrientation;// Required + private final String positiveBtnText;// Required + private final String negativeBtnText;// Required + + CTLocalInAppBuilder(Builder.Builder1 builder) throws JSONException { + this.localInAppType = builder.jsonObject.getString(Constants.KEY_TYPE); + this.titleObj = builder.titleObject; + this.messageObj = builder.msgObject; + this.followDeviceOrientation = builder.jsonObject.getBoolean(Constants.KEY_LANDSCAPE); + this.positiveBtnText = builder.buttonArray.get(0).toString(); + this.negativeBtnText = builder.buttonArray.get(1).toString(); + } + + public static Builder builder() { + return new Builder(); + } + + public static final class Builder { + + public Builder1 inAppType(String inAppType, Context context) throws JSONException { + return new Builder1(inAppType, context); + } + + public static final class Builder1 { + + JSONObject jsonObject = new JSONObject(); + JSONObject titleObject = new JSONObject(); + JSONObject msgObject = new JSONObject(); + JSONObject media = new JSONObject(); + JSONArray buttonArray = new JSONArray(); + JSONObject positiveButtonObject = new JSONObject(); + JSONObject negativeButtonObject = new JSONObject(); + + String btnBorderRadius; + + private Builder1(String inAppType, Context context) throws JSONException { + this.jsonObject.put(Constants.KEY_TYPE, inAppType); + this.jsonObject.put("isLocalInApp",true); + this.jsonObject.put(Constants.KEY_HIDE_CLOSE,true); + this.jsonObject.put(Constants.KEY_IS_TABLET, + DeviceInfo.getDeviceType(context) == DeviceInfo.TABLET); + + } + + public Builder2 titleText(String titleText) throws JSONException { + this.titleObject.put(Constants.KEY_TEXT, titleText); + this.jsonObject.put(Constants.KEY_TITLE, titleObject); + return new Builder2(Builder1.this); + } + } + + public static final class Builder2 { + final Builder1 builder; + + private Builder2(Builder1 builder) { + this.builder = builder; + } + + public Builder3 messageText(String messageText) throws JSONException { + this.builder.msgObject.put(Constants.KEY_TEXT, messageText); + this.builder.jsonObject.put(Constants.KEY_MESSAGE, this.builder.msgObject); + return new Builder3(this.builder); + } + } + + public static final class Builder3 { + final Builder1 builder; + + private Builder3(Builder1 builder) { + this.builder = builder; + } + + public Builder4 followDeviceOrientation(boolean followDeviceOrientation) throws JSONException { + this.builder.jsonObject.put(Constants.KEY_PORTRAIT, true); + this.builder.jsonObject.put(Constants.KEY_LANDSCAPE, followDeviceOrientation); + return new Builder4(this.builder); + } + } + + public static final class Builder4 { + final Builder1 builder; + + private Builder4(Builder1 builder) { + this.builder = builder; + } + + public Builder5 positiveBtnText(String positiveBtnText) throws JSONException { + this.builder.positiveButtonObject.put(Constants.KEY_TEXT, positiveBtnText); + if (this.builder.btnBorderRadius == null || this.builder.btnBorderRadius.isEmpty()){ + this.builder.positiveButtonObject.put(Constants.KEY_RADIUS, "2"); + } + this.builder.buttonArray.put(0, this.builder.positiveButtonObject); + this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + return new Builder5(this.builder); + } + } + + public static final class Builder5 { + final Builder1 builder; + + private Builder5(Builder1 builder) { + this.builder = builder; + } + + public Builder6 negativeBtnText(String negativeBtnText) throws JSONException { + this.builder.negativeButtonObject.put(Constants.KEY_TEXT, negativeBtnText); + if (this.builder.btnBorderRadius == null || this.builder.btnBorderRadius.isEmpty()){ + this.builder.negativeButtonObject.put(Constants.KEY_RADIUS, "2"); + } + this.builder.buttonArray.put(1, this.builder.negativeButtonObject); + this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + return new Builder6(this.builder); + } + } + + public static final class Builder6 { + final Builder1 builder; + + private Builder6(Builder1 builder) { + this.builder = builder; + } + + public Builder6 backgroundColor(String backgroundColor) throws JSONException { + this.builder.jsonObject.put(Constants.KEY_BG, backgroundColor); + return this; + } + + public Builder6 imageUrl(String imageUrl) throws JSONException { + this.builder.media.put(Constants.KEY_URL, imageUrl); + this.builder.media.put(Constants.KEY_CONTENT_TYPE, "image"); + this.builder.jsonObject.put(Constants.KEY_MEDIA, this.builder.media); + + if (builder.jsonObject.getBoolean(Constants.KEY_LANDSCAPE)) { + this.builder.media.put(Constants.KEY_URL, imageUrl); + this.builder.media.put(Constants.KEY_CONTENT_TYPE, "image"); + this.builder.jsonObject.put(Constants.KEY_MEDIA_LANDSCAPE, this.builder.media); + } + return this; + } + + public Builder6 titleTextColor(String titleTextColor) throws JSONException { + this.builder.titleObject.put(Constants.KEY_COLOR, titleTextColor); + this.builder.jsonObject.put(Constants.KEY_TITLE, this.builder.titleObject); + return this; + } + + public Builder6 messageTextColor(String messageTextColor) throws JSONException { + this.builder.msgObject.put(Constants.KEY_COLOR, messageTextColor); + this.builder.jsonObject.put(Constants.KEY_MESSAGE, this.builder.msgObject); + return this; + } + + public Builder6 btnTextColor(String btnTextColor) throws JSONException { + this.builder.positiveButtonObject.put(Constants.KEY_COLOR, btnTextColor); + this.builder.negativeButtonObject.put(Constants.KEY_COLOR, btnTextColor); + + this.builder.buttonArray.put(0, this.builder.positiveButtonObject); + this.builder.buttonArray.put(1, this.builder.negativeButtonObject); + + this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + return this; + } + + public Builder6 btnBackgroundColor(String btnBackgroundColor) throws JSONException { + this.builder.positiveButtonObject.put(Constants.KEY_BG, btnBackgroundColor); + this.builder.negativeButtonObject.put(Constants.KEY_BG, btnBackgroundColor); + + this.builder.buttonArray.put(0, this.builder.positiveButtonObject); + this.builder.buttonArray.put(1, this.builder.negativeButtonObject); + + this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + return this; + } + + public Builder6 btnBorderColor(String btnBorderColor) throws JSONException { + this.builder.positiveButtonObject.put(Constants.KEY_BORDER, btnBorderColor); + this.builder.negativeButtonObject.put(Constants.KEY_BORDER, btnBorderColor); + + this.builder.buttonArray.put(0, this.builder.positiveButtonObject); + this.builder.buttonArray.put(1, this.builder.negativeButtonObject); + + this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + return this; + } + + public Builder6 btnBorderRadius(String btnBorderRadius) throws JSONException { + this.builder.btnBorderRadius = btnBorderRadius; + this.builder.positiveButtonObject.put(Constants.KEY_RADIUS, btnBorderRadius); + this.builder.negativeButtonObject.put(Constants.KEY_RADIUS, btnBorderRadius); + + this.builder.buttonArray.put(0, this.builder.positiveButtonObject); + this.builder.buttonArray.put(1, this.builder.negativeButtonObject); + + this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + return this; + } + public JSONObject build() throws JSONException { + return this.builder.jsonObject; + } + } + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (o == null || getClass() != o.getClass()) return false; + CTLocalInAppBuilder that = (CTLocalInAppBuilder) o; + return followDeviceOrientation == that.followDeviceOrientation && + Objects.equals(localInAppType, that.localInAppType) && + Objects.equals(titleObj, that.titleObj) && Objects.equals(messageObj, that.messageObj) + && Objects.equals(positiveBtnText, that.positiveBtnText) + && Objects.equals(negativeBtnText, that.negativeBtnText); + } + + @Override + public int hashCode() { + return Objects.hash(localInAppType, titleObj, messageObj, followDeviceOrientation, + positiveBtnText, negativeBtnText); + } +} diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 23e196ebe..6fa2ad4cc 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -18,7 +18,6 @@ import com.clevertap.android.sdk.Constants; import com.clevertap.android.sdk.ControllerManager; import com.clevertap.android.sdk.CoreMetaData; -import com.clevertap.android.sdk.DeviceInfo; import com.clevertap.android.sdk.InAppNotificationActivity; import com.clevertap.android.sdk.InAppNotificationListener; import com.clevertap.android.sdk.Logger; @@ -51,9 +50,6 @@ private final class NotificationPrepareRunnable implements Runnable { private JSONObject jsonObject; - private CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder; - private CTAlertLocalInAppBuilder alertLocalInAppBuilder; - private final boolean videoSupport = Utils.haveVideoPlayerSupport; NotificationPrepareRunnable(InAppController inAppController, JSONObject jsonObject) { @@ -61,33 +57,10 @@ private final class NotificationPrepareRunnable implements Runnable { this.jsonObject = jsonObject; } - NotificationPrepareRunnable(InAppController inAppController, - CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder) { - this.inAppControllerWeakReference = new WeakReference<>(inAppController); - this.halfInterstitialLocalInAppBuilder = halfInterstitialLocalInAppBuilder; - } - - NotificationPrepareRunnable(InAppController inAppController, - CTAlertLocalInAppBuilder alertLocalInAppBuilder) { - this.inAppControllerWeakReference = new WeakReference<>(inAppController); - this.alertLocalInAppBuilder = alertLocalInAppBuilder; - } - @Override public void run() { - final CTInAppNotification inAppNotification; - if (jsonObject != null) {//If jsonObj is available then render in-app via JSON - inAppNotification = new CTInAppNotification() - .initWithJSON(jsonObject, videoSupport); - }else {//render in-app via local in-app builder - inAppNotification = halfInterstitialLocalInAppBuilder != null ? new CTInAppNotification() - .configureHalfInterstitialLocalInApp(halfInterstitialLocalInAppBuilder, - DeviceInfo.getDeviceType(context)) : - new CTInAppNotification() - .configureAlertLocalInApp(alertLocalInAppBuilder, - DeviceInfo.getDeviceType(context)); - } - + final CTInAppNotification inAppNotification = new CTInAppNotification() + .initWithJSON(jsonObject, videoSupport); if (inAppNotification.getError() != null) { logger .debug(config.getAccountId(), @@ -200,12 +173,8 @@ public void checkPendingInAppNotifications(Activity activity) { } } - public void promptPushPrimer(CTHalfInterstitialLocalInAppBuilder halfInterstitialLocalInAppBuilder){ - prepareNotificationForDisplay(halfInterstitialLocalInAppBuilder,null); - } - - public void promptPushPrimer(CTAlertLocalInAppBuilder alertLocalInAppBuilder){ - prepareNotificationForDisplay(null,alertLocalInAppBuilder); + public void promptPushPrimer(JSONObject jsonObject){ + prepareNotificationForDisplay(jsonObject); } public void promptPermission(){ @@ -508,26 +477,6 @@ public Void call() { } }); } - - private void prepareNotificationForDisplay(CTHalfInterstitialLocalInAppBuilder - halfInterstitialLocalInAppBuilder, CTAlertLocalInAppBuilder alertLocalInAppBuilder){ - logger.debug(config.getAccountId(), "Preparing local In-App for display"); - Task task = CTExecutorFactory.executors(config).postAsyncSafelyTask(Constants.TAG_FEATURE_IN_APPS); - task.execute("InappController#prepareLocalNotificationForDisplay", new Callable() { - @Override - public Void call() { - if (halfInterstitialLocalInAppBuilder != null) { - new NotificationPrepareRunnable(InAppController.this, - halfInterstitialLocalInAppBuilder).run(); - }else if (alertLocalInAppBuilder != null){ - new NotificationPrepareRunnable(InAppController.this, - alertLocalInAppBuilder).run(); - } - return null; - } - }); - } - private void showInAppNotificationIfAny() { if (!config.isAnalyticsOnly()) { Task task = CTExecutorFactory.executors(config).postAsyncSafelyTask(Constants.TAG_FEATURE_IN_APPS); diff --git a/sample/src/main/java/com/clevertap/demo/ViewModelFactory.kt b/sample/src/main/java/com/clevertap/demo/ViewModelFactory.kt index 2d9c46053..c71a563c1 100644 --- a/sample/src/main/java/com/clevertap/demo/ViewModelFactory.kt +++ b/sample/src/main/java/com/clevertap/demo/ViewModelFactory.kt @@ -1,19 +1,21 @@ package com.clevertap.demo +import androidx.fragment.app.FragmentActivity import androidx.lifecycle.ViewModel import androidx.lifecycle.ViewModelProvider import com.clevertap.android.sdk.CleverTapAPI import com.clevertap.demo.ui.main.HomeScreenViewModel -class ViewModelFactory constructor( - private val cleverTapAPI: CleverTapAPI? +class ViewModelFactory( + private val cleverTapAPI: CleverTapAPI?, + private val activity: FragmentActivity? ) : ViewModelProvider.NewInstanceFactory() { override fun create(modelClass: Class) = with(modelClass) { when { isAssignableFrom(HomeScreenViewModel::class.java) -> - HomeScreenViewModel(cleverTapAPI) + HomeScreenViewModel(cleverTapAPI,activity) else -> throw IllegalArgumentException("Unknown ViewModel class: ${modelClass.name}") } diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt index 19000bcaf..c88270708 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenFragment.kt @@ -40,7 +40,7 @@ private const val PERMISSIONS_REQUEST_CODE = 34 class HomeScreenFragment : Fragment() { private val viewModel by viewModels { - ViewModelFactory((activity as? HomeScreenActivity)?.cleverTapDefaultInstance) + ViewModelFactory((activity as? HomeScreenActivity)?.cleverTapDefaultInstance, activity) } companion object { diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index 4f8e43a89..f478650a6 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -1,17 +1,19 @@ package com.clevertap.demo.ui.main +import android.annotation.SuppressLint import android.os.Looper import android.util.Log +import androidx.fragment.app.FragmentActivity import androidx.lifecycle.MutableLiveData import androidx.lifecycle.ViewModel import com.clevertap.android.sdk.CTInboxStyleConfig import com.clevertap.android.sdk.CleverTapAPI import com.clevertap.android.sdk.Constants -import com.clevertap.android.sdk.inapp.CTAlertLocalInAppBuilder -import com.clevertap.android.sdk.inapp.CTHalfInterstitialLocalInAppBuilder +import com.clevertap.android.sdk.inapp.CTLocalInAppBuilder import java.util.* -class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() { +class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?, @SuppressLint("StaticFieldLeak") +private val activity:FragmentActivity?) : ViewModel() { val clickCommand: MutableLiveData by lazy { MutableLiveData() @@ -326,34 +328,39 @@ class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?) : ViewModel() "919"-> cleverTapAPI?.pushEvent("Send Three CTA Notification") "100"-> { if (cleverTapAPI?.isNotificationPermissionGranted == false){ - val builder = CTHalfInterstitialLocalInAppBuilder.builder() + val builder = CTLocalInAppBuilder.builder() + .inAppType("half-interstitial",activity) .titleText("Get Notified") - .titleTextColor(Constants.BLACK) - .bodyText("Please enable notifications on your device to use Push Notifications.") - .bodyTextColor(Constants.BLACK) - .backgroundColor(Constants.WHITE) + .messageText("Please enable notifications on your device to use Push Notifications.") .followDeviceOrientation(true) .positiveBtnText("Allow") .negativeBtnText("Cancel") + .backgroundColor(Constants.WHITE) + .btnBorderColor(Constants.BLUE) + .titleTextColor(Constants.BLUE) + .messageTextColor(Constants.BLACK) .btnTextColor(Constants.WHITE) - .btnBackgroundColor(Constants.LIGHT_BLUE) - /*.image("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png")*/ + .btnBackgroundColor(Constants.BLUE) + .imageUrl("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png") .build() - cleverTapAPI.promptHalfInterstitialPushPrimer(builder) + cleverTapAPI.promptPushPrimer(builder) + }else{ Log.v("HomeScreenViewModel","Notification permission is already granted.") } } "101"->{ - if (cleverTapAPI?.isNotificationPermissionGranted == false) { - val builder = CTAlertLocalInAppBuilder.builder().titleText("Get Notified") - .bodyText("Please enable notifications on your device to use Push Notifications.") - .followDeviceOrientation(false) - .positiveBtnText("Allow") - .negativeBtnText("Cancel") - .build() - cleverTapAPI.promptAlertPushPrimer(builder) + if (cleverTapAPI?.isNotificationPermissionGranted == false) { + val builder = CTLocalInAppBuilder.builder() + .inAppType("alert-template",activity) + .titleText("Get Notified") + .messageText("Enable Notification permission") + .followDeviceOrientation(true) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .build() + cleverTapAPI.promptPushPrimer(builder) }else{ Log.v("HomeScreenViewModel","Notification permission is already granted.") } From d5ef9a6571213c9886c507d590cc3389dfd14fb2 Mon Sep 17 00:00:00 2001 From: William John Date: Mon, 3 Oct 2022 14:01:50 +0530 Subject: [PATCH 15/58] chore(SDK-1970)- Refactor CTLocalInAppBuilder and CTInAppNotification --- .../clevertap/android/sdk/inapp/CTInAppNotification.java | 3 ++- .../clevertap/android/sdk/inapp/CTLocalInAppBuilder.java | 6 +++++- .../java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt | 6 ++++-- 3 files changed, 11 insertions(+), 4 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index d72f7b6ba..d37ea2720 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -1,5 +1,6 @@ package com.clevertap.android.sdk.inapp; +import static com.clevertap.android.sdk.inapp.CTLocalInAppBuilder.IS_LOCAL_INAPP; import android.content.res.Configuration; import android.graphics.Bitmap; import android.os.Bundle; @@ -590,7 +591,7 @@ private void configureWithJson(JSONObject jsonObject) { this.campaignId = jsonObject.has(Constants.NOTIFICATION_ID_TAG) ? jsonObject .getString(Constants.NOTIFICATION_ID_TAG) : ""; this.type = jsonObject.getString(Constants.KEY_TYPE); - this.isLocalInApp = jsonObject.has("isLocalInApp") && jsonObject.getBoolean("isLocalInApp"); + this.isLocalInApp = jsonObject.has(IS_LOCAL_INAPP) && jsonObject.getBoolean(IS_LOCAL_INAPP); this.excludeFromCaps = jsonObject.has(Constants.KEY_EFC) && jsonObject.getInt(Constants.KEY_EFC) == 1; this.totalLifetimeCount = jsonObject.has(Constants.KEY_TLC) ? jsonObject.getInt(Constants.KEY_TLC) : -1; this.totalDailyCount = jsonObject.has(Constants.KEY_TDC) ? jsonObject.getInt(Constants.KEY_TDC) : -1; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java index ab3c92267..14c322f79 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java @@ -12,6 +12,10 @@ public class CTLocalInAppBuilder { + public static final String HALF_INTERSTITIAL_INAPP = "half-interstitial"; + public static final String ALERT_INAPP = "alert-template"; + protected static final String IS_LOCAL_INAPP = "isLocalInApp"; + private final String localInAppType;//Required private final JSONObject titleObj;// Required private final JSONObject messageObj;// Required @@ -52,7 +56,7 @@ public static final class Builder1 { private Builder1(String inAppType, Context context) throws JSONException { this.jsonObject.put(Constants.KEY_TYPE, inAppType); - this.jsonObject.put("isLocalInApp",true); + this.jsonObject.put(IS_LOCAL_INAPP,true); this.jsonObject.put(Constants.KEY_HIDE_CLOSE,true); this.jsonObject.put(Constants.KEY_IS_TABLET, DeviceInfo.getDeviceType(context) == DeviceInfo.TABLET); diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index f478650a6..ed6aa9186 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -10,6 +10,8 @@ import com.clevertap.android.sdk.CTInboxStyleConfig import com.clevertap.android.sdk.CleverTapAPI import com.clevertap.android.sdk.Constants import com.clevertap.android.sdk.inapp.CTLocalInAppBuilder +import com.clevertap.android.sdk.inapp.CTLocalInAppBuilder.ALERT_INAPP +import com.clevertap.android.sdk.inapp.CTLocalInAppBuilder.HALF_INTERSTITIAL_INAPP import java.util.* class HomeScreenViewModel(private val cleverTapAPI: CleverTapAPI?, @SuppressLint("StaticFieldLeak") @@ -329,7 +331,7 @@ private val activity:FragmentActivity?) : ViewModel() { "100"-> { if (cleverTapAPI?.isNotificationPermissionGranted == false){ val builder = CTLocalInAppBuilder.builder() - .inAppType("half-interstitial",activity) + .inAppType(HALF_INTERSTITIAL_INAPP,activity) .titleText("Get Notified") .messageText("Please enable notifications on your device to use Push Notifications.") .followDeviceOrientation(true) @@ -353,7 +355,7 @@ private val activity:FragmentActivity?) : ViewModel() { "101"->{ if (cleverTapAPI?.isNotificationPermissionGranted == false) { val builder = CTLocalInAppBuilder.builder() - .inAppType("alert-template",activity) + .inAppType(ALERT_INAPP,activity) .titleText("Get Notified") .messageText("Enable Notification permission") .followDeviceOrientation(true) From dd2fa5abe3a4e28cffc851d3c4ca8f8434819d69 Mon Sep 17 00:00:00 2001 From: William John Date: Tue, 4 Oct 2022 14:15:08 +0530 Subject: [PATCH 16/58] chore(SDK-1970)- Refactor hard permission dialog listener,`CTLocalInAppBuilder`,navigation to settings dialog flow, Remove unused code in `CTInAppNotificationButton` and `CTInAppNotificationMedia` --- .../android/sdk/BaseCallbackManager.java | 4 +- .../android/sdk/CallbackManager.java | 6 +-- .../clevertap/android/sdk/CleverTapAPI.java | 12 +++-- .../sdk/InAppNotificationActivity.java | 14 +----- ...va => PushPermissionResponseListener.java} | 4 +- .../java/com/clevertap/android/sdk/Utils.java | 20 ++++++++ .../sdk/inapp/CTInAppNotificationButton.java | 28 +++++------ .../sdk/inapp/CTInAppNotificationMedia.java | 26 +++++----- .../sdk/inapp/CTLocalInAppBuilder.java | 47 ++++++++----------- .../android/sdk/inapp/InAppController.java | 23 ++++++--- ...vigateToAndroidSettingsForNotifications.kt | 20 -------- .../com/clevertap/demo/HomeScreenActivity.kt | 5 +- .../demo/ui/main/HomeScreenViewModel.kt | 6 ++- 13 files changed, 106 insertions(+), 109 deletions(-) rename clevertap-core/src/main/java/com/clevertap/android/sdk/{PushPermissionNotificationResponseListener.java => PushPermissionResponseListener.java} (72%) delete mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java index 5a76475bb..d710aa794 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/BaseCallbackManager.java @@ -30,7 +30,7 @@ public abstract class BaseCallbackManager { public abstract InAppNotificationListener getInAppNotificationListener(); - public abstract PushPermissionNotificationResponseListener getPushPermissionNotificationResponseListener(); + public abstract PushPermissionResponseListener getPushPermissionNotificationResponseListener(); public abstract CTInboxListener getInboxListener(); @@ -66,7 +66,7 @@ public abstract void setInAppNotificationButtonListener( public abstract void setInAppNotificationListener(InAppNotificationListener inAppNotificationListener); - public abstract void setPushPermissionNotificationResponseListener(PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener); + public abstract void setPushPermissionNotificationResponseListener(PushPermissionResponseListener pushPermissionNotificationResponseListener); public abstract void setInboxListener(CTInboxListener inboxListener); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java index 7bc3eafc7..8546b98c0 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CallbackManager.java @@ -29,7 +29,7 @@ public class CallbackManager extends BaseCallbackManager { private InAppNotificationListener inAppNotificationListener; - private PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener; + private PushPermissionResponseListener pushPermissionNotificationResponseListener; private CTInboxListener inboxListener; @@ -148,7 +148,7 @@ public InAppNotificationListener getInAppNotificationListener() { } @Override - public PushPermissionNotificationResponseListener getPushPermissionNotificationResponseListener() { + public PushPermissionResponseListener getPushPermissionNotificationResponseListener() { return pushPermissionNotificationResponseListener; } @@ -158,7 +158,7 @@ public void setInAppNotificationListener(final InAppNotificationListener inAppNo } @Override - public void setPushPermissionNotificationResponseListener(PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener) { + public void setPushPermissionNotificationResponseListener(PushPermissionResponseListener pushPermissionNotificationResponseListener) { this.pushPermissionNotificationResponseListener = pushPermissionNotificationResponseListener; } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index bf06d3e47..5a62e90bb 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -1631,21 +1631,23 @@ public void setInAppNotificationListener(InAppNotificationListener inAppNotifica /** * Returns the PushPermissionNotificationResponseListener object * - * @return An {@link PushPermissionNotificationResponseListener} object + * @return An {@link PushPermissionResponseListener} object */ @SuppressWarnings({"unused", "WeakerAccess"}) - public PushPermissionNotificationResponseListener getPushPermissionNotificationResponseListener() { + public PushPermissionResponseListener getPushPermissionNotificationResponseListener() { return coreState.getCallbackManager().getPushPermissionNotificationResponseListener(); } /** * This method sets the PushPermissionNotificationResponseListener * - * @param pushPermissionNotificationResponseListener An {@link PushPermissionNotificationResponseListener} object + * @param pushPermissionResponseListener An {@link PushPermissionResponseListener} object */ @SuppressWarnings({"unused"}) - public void setPushPermissionNotificationResponseListener(PushPermissionNotificationResponseListener pushPermissionNotificationResponseListener) { - coreState.getCallbackManager().setPushPermissionNotificationResponseListener(pushPermissionNotificationResponseListener); + public void setPushPermissionNotificationResponseListener(PushPermissionResponseListener + pushPermissionResponseListener) { + coreState.getCallbackManager(). + setPushPermissionNotificationResponseListener(pushPermissionResponseListener); } /** diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index 799c88926..c829f818f 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -34,7 +34,6 @@ import com.clevertap.android.sdk.inapp.CTInAppNotification; import com.clevertap.android.sdk.inapp.CTInAppType; import com.clevertap.android.sdk.inapp.InAppListener; -import com.clevertap.android.sdk.inapp.NavigateToAndroidSettingsForNotifications; import java.lang.ref.WeakReference; import java.util.HashMap; @@ -216,7 +215,7 @@ public void showFallbackAlertDialog() { AlertDialogPromptForSettings.INSTANCE.show(this, new AlertDialogPromptForSettings.Callback() { @Override public void onAccept() { - NavigateToAndroidSettingsForNotifications.INSTANCE.show(getBaseContext()); + Utils.navigateToAndroidSettingsForNotifications(InAppNotificationActivity.this); didDismiss(null); } @@ -227,17 +226,6 @@ public void onDecline() { }); } - public static void startPrompt(Activity activity, CleverTapInstanceConfig config){ - if (!activity.getClass().equals(InAppNotificationActivity.class)) { - Intent intent = new Intent(activity, InAppNotificationActivity.class); - Bundle configBundle = new Bundle(); - configBundle.putParcelable("config", config); - intent.putExtra("configBundle", configBundle); - intent.putExtra("displayHardPermissionDialog", true); - activity.startActivity(intent); - } - } - @RequiresApi(api = 33) public static int isNotificationPermissionGranted(Activity activity){ return ContextCompat.checkSelfPermission( diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionNotificationResponseListener.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionResponseListener.java similarity index 72% rename from clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionNotificationResponseListener.java rename to clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionResponseListener.java index fe5340546..549e7da55 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionNotificationResponseListener.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/PushPermissionResponseListener.java @@ -3,7 +3,7 @@ /** * A listener for notification permission. */ -public interface PushPermissionNotificationResponseListener { +public interface PushPermissionResponseListener { /** * This is called when user either grants allow/dismiss permission for notifications for Android 13+ @@ -11,5 +11,5 @@ public interface PushPermissionNotificationResponseListener { * @param accepted This boolean will return true if notification permission is granted and will retrun * false if permission is denied. */ - void response(boolean accepted);//Change method name here, sounds ambiguous + void onPushPermissionResponse(boolean accepted);//Change method name here, sounds ambiguous } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java index 4c0f36173..2dc2d0a39 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/Utils.java @@ -21,12 +21,14 @@ import android.graphics.drawable.Drawable; import android.net.ConnectivityManager; import android.net.NetworkInfo; +import android.net.Uri; import android.os.Build; import android.os.Bundle; import android.os.Handler; import android.os.Looper; import android.os.Process; import android.os.SystemClock; +import android.provider.Settings; import android.telephony.TelephonyManager; import android.text.TextUtils; import androidx.annotation.NonNull; @@ -668,6 +670,24 @@ public static boolean isAndroid13(Context context){ return Build.VERSION.SDK_INT > 32 && getTargetSdkVersion(context) > 32; } + public static void navigateToAndroidSettingsForNotifications(Context context){ + Intent intent = new Intent(); + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { + intent.setAction(Settings.ACTION_APP_NOTIFICATION_SETTINGS); + intent.putExtra(Settings.EXTRA_APP_PACKAGE, context.getPackageName()); + intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); + } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP){ + intent.setAction("android.settings.APP_NOTIFICATION_SETTINGS"); + intent.putExtra("app_package", context.getPackageName()); + intent.putExtra("app_uid", context.getApplicationInfo().uid); + } else { + intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS); + intent.addCategory(Intent.CATEGORY_DEFAULT); + intent.setData(Uri.parse("package:" + context.getPackageName())); + } + context.startActivity(intent); + } + public static int getTargetSdkVersion(Context context) { String packageName = context.getPackageName(); PackageManager packageManager = context.getPackageManager(); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java index 546cfe1c6..9965afdc6 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationButton.java @@ -215,20 +215,20 @@ CTInAppNotificationButton initWithJSON(JSONObject jsonObject) { return this; } - CTInAppNotificationButton initWithLocalData(String btnText, String btnBackgroundColor, - String btnTextColor, String btnBorderColor, - String btnBorderRadius) { - - this.text = btnText != null ? btnText : ""; - this.backgroundColor = btnBackgroundColor != null ? btnBackgroundColor - : Constants.BLUE; - - this.textColor = btnTextColor != null ? btnTextColor : Constants.BLUE; - this.borderColor = btnBorderColor !=null ? btnBorderColor : Constants.WHITE; - this.borderRadius = btnBorderRadius != null ? btnBorderRadius : "2";//Adding default value as 2 instead of an empty value. - // If the value is empty then action btn defaults to standard btn without any customizations - return this; - } +// CTInAppNotificationButton initWithLocalData(String btnText, String btnBackgroundColor, +// String btnTextColor, String btnBorderColor, +// String btnBorderRadius) { +// +// this.text = btnText != null ? btnText : ""; +// this.backgroundColor = btnBackgroundColor != null ? btnBackgroundColor +// : Constants.BLUE; +// +// this.textColor = btnTextColor != null ? btnTextColor : Constants.BLUE; +// this.borderColor = btnBorderColor !=null ? btnBorderColor : Constants.WHITE; +// this.borderRadius = btnBorderRadius != null ? btnBorderRadius : "2";//Adding default value as 2 instead of an empty value. +// // If the value is empty then action btn defaults to standard btn without any customizations +// return this; +// } /** * Checks if custom Key Value pair is present or not diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java index f8c1f99fa..5ac5f2f02 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotificationMedia.java @@ -102,19 +102,19 @@ CTInAppNotificationMedia initWithJSON(JSONObject mediaObject, int orientation) { } } - CTInAppNotificationMedia initWithLocalData(String imgURI, int orientation) { - this.orientation = orientation; - this.contentType = "image"; - if (!imgURI.isEmpty()) { - this.mediaUrl = imgURI; - this.cacheKey = UUID.randomUUID().toString(); - } - if (contentType.isEmpty()) { - return null; - } else { - return this; - } - } +// CTInAppNotificationMedia initWithLocalData(String imgURI, int orientation) { +// this.orientation = orientation; +// this.contentType = "image"; +// if (!imgURI.isEmpty()) { +// this.mediaUrl = imgURI; +// this.cacheKey = UUID.randomUUID().toString(); +// } +// if (contentType.isEmpty()) { +// return null; +// } else { +// return this; +// } +// } boolean isAudio() { String contentType = this.getContentType(); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java index 14c322f79..d3b1132fa 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java @@ -172,51 +172,42 @@ public Builder6 messageTextColor(String messageTextColor) throws JSONException { } public Builder6 btnTextColor(String btnTextColor) throws JSONException { - this.builder.positiveButtonObject.put(Constants.KEY_COLOR, btnTextColor); - this.builder.negativeButtonObject.put(Constants.KEY_COLOR, btnTextColor); - - this.builder.buttonArray.put(0, this.builder.positiveButtonObject); - this.builder.buttonArray.put(1, this.builder.negativeButtonObject); - - this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + this.builder.jsonObject.put(Constants.KEY_BUTTONS, + getActionButtonJSONArray(Constants.KEY_COLOR, btnTextColor)); return this; } public Builder6 btnBackgroundColor(String btnBackgroundColor) throws JSONException { - this.builder.positiveButtonObject.put(Constants.KEY_BG, btnBackgroundColor); - this.builder.negativeButtonObject.put(Constants.KEY_BG, btnBackgroundColor); - - this.builder.buttonArray.put(0, this.builder.positiveButtonObject); - this.builder.buttonArray.put(1, this.builder.negativeButtonObject); - - this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + this.builder.jsonObject.put(Constants.KEY_BUTTONS, + getActionButtonJSONArray(Constants.KEY_BG, btnBackgroundColor)); return this; } public Builder6 btnBorderColor(String btnBorderColor) throws JSONException { - this.builder.positiveButtonObject.put(Constants.KEY_BORDER, btnBorderColor); - this.builder.negativeButtonObject.put(Constants.KEY_BORDER, btnBorderColor); - - this.builder.buttonArray.put(0, this.builder.positiveButtonObject); - this.builder.buttonArray.put(1, this.builder.negativeButtonObject); - - this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); + this.builder.jsonObject.put(Constants.KEY_BUTTONS, + getActionButtonJSONArray(Constants.KEY_BORDER, btnBorderColor)); return this; } public Builder6 btnBorderRadius(String btnBorderRadius) throws JSONException { this.builder.btnBorderRadius = btnBorderRadius; - this.builder.positiveButtonObject.put(Constants.KEY_RADIUS, btnBorderRadius); - this.builder.negativeButtonObject.put(Constants.KEY_RADIUS, btnBorderRadius); + this.builder.jsonObject.put(Constants.KEY_BUTTONS, + getActionButtonJSONArray(Constants.KEY_RADIUS, btnBorderRadius)); + return this; + } + public JSONObject build() { + return this.builder.jsonObject; + } + + + private JSONArray getActionButtonJSONArray(String key, String value) throws JSONException{ + this.builder.positiveButtonObject.put(key, value); + this.builder.negativeButtonObject.put(key, value); this.builder.buttonArray.put(0, this.builder.positiveButtonObject); this.builder.buttonArray.put(1, this.builder.negativeButtonObject); - this.builder.jsonObject.put(Constants.KEY_BUTTONS, this.builder.buttonArray); - return this; - } - public JSONObject build() throws JSONException { - return this.builder.jsonObject; + return this.builder.buttonArray; } } } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 6fa2ad4cc..f04f45eb9 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -22,7 +22,7 @@ import com.clevertap.android.sdk.InAppNotificationListener; import com.clevertap.android.sdk.Logger; import com.clevertap.android.sdk.ManifestInfo; -import com.clevertap.android.sdk.PushPermissionNotificationResponseListener; +import com.clevertap.android.sdk.PushPermissionResponseListener; import com.clevertap.android.sdk.StorageHelper; import com.clevertap.android.sdk.Utils; import com.clevertap.android.sdk.task.CTExecutorFactory; @@ -178,10 +178,21 @@ public void promptPushPrimer(JSONObject jsonObject){ } public void promptPermission(){ - InAppNotificationActivity.startPrompt(Objects.requireNonNull(CoreMetaData.getCurrentActivity()), + startPrompt(Objects.requireNonNull(CoreMetaData.getCurrentActivity()), config); } + public void startPrompt(Activity activity, CleverTapInstanceConfig config){ + if (!activity.getClass().equals(InAppNotificationActivity.class)) { + Intent intent = new Intent(activity, InAppNotificationActivity.class); + Bundle configBundle = new Bundle(); + configBundle.putParcelable("config", config); + intent.putExtra("configBundle", configBundle); + intent.putExtra("displayHardPermissionDialog", true); + activity.startActivity(intent); + } + } + @RequiresApi(api = 33) public boolean isNotificationPermissionGranted(){ int permissionStatus = InAppNotificationActivity.isNotificationPermissionGranted( @@ -304,17 +315,17 @@ public void run() { @Override public void onAccept() { - final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); + final PushPermissionResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); if (listener != null){ - listener.response(true); + listener.onPushPermissionResponse(true); } } @Override public void onReject() { - final PushPermissionNotificationResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); + final PushPermissionResponseListener listener = callbackManager.getPushPermissionNotificationResponseListener(); if (listener != null){ - listener.response(false); + listener.onPushPermissionResponse(false); } } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt deleted file mode 100644 index 8d3ee4e94..000000000 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/NavigateToAndroidSettingsForNotifications.kt +++ /dev/null @@ -1,20 +0,0 @@ -package com.clevertap.android.sdk.inapp - -import android.content.Context -import android.content.Intent - -object NavigateToAndroidSettingsForNotifications { - fun show(context: Context) { - val intent = Intent() - intent.action = "android.settings.APP_NOTIFICATION_SETTINGS" - intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) - - //for Android 5-7 - intent.putExtra("app_package", context.getPackageName()) - intent.putExtra("app_uid", context.getApplicationInfo().uid) - - // for Android 8 and above - intent.putExtra("android.provider.extra.APP_PACKAGE", context.getPackageName()) - context.startActivity(intent) - } -} \ No newline at end of file diff --git a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt index 590f76e21..ccf996880 100644 --- a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt +++ b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt @@ -30,7 +30,8 @@ import java.util.HashMap private const val TAG = "HomeScreenActivity" class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitListener, CTProductConfigListener, - CTFeatureFlagsListener, SyncListener, InAppNotificationListener, PushPermissionNotificationResponseListener, + CTFeatureFlagsListener, SyncListener, InAppNotificationListener, + PushPermissionResponseListener, InAppNotificationButtonListener, PushPrimerButtonListener { var cleverTapDefaultInstance: CleverTapAPI? = null @@ -258,7 +259,7 @@ class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitList Log.i(TAG, "InApp---> onDismissed() called") } - override fun response(accepted: Boolean) { + override fun onPushPermissionResponse(accepted: Boolean) { Log.i(TAG, "InApp---> response() called $accepted") } diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index a4b7e253f..1a92820c1 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -386,7 +386,11 @@ private val activity:FragmentActivity?) : ViewModel() { } "102"->{ - cleverTapAPI?.promptForNotificationPermission() + if (cleverTapAPI?.isNotificationPermissionGranted == false) { + cleverTapAPI.promptForNotificationPermission() + }else{ + Log.v("HomeScreenViewModel","Notification permission is already granted.") + } } //"60" -> webViewClickListener?.onWebViewClick() From 098fca8ebb926bd69f39f1c58826fc965b6e9cf6 Mon Sep 17 00:00:00 2001 From: William John Date: Thu, 6 Oct 2022 16:20:36 +0530 Subject: [PATCH 17/58] task(SDK-2169)- Maintain count when local IAM is called --- .../java/com/clevertap/android/sdk/DeviceInfo.java | 5 +++++ .../android/sdk/inapp/CTInAppNotification.java | 3 --- .../clevertap/android/sdk/inapp/InAppController.java | 12 +++++++++++- .../clevertap/android/sdk/utils/CTJsonConverter.java | 2 ++ 4 files changed, 18 insertions(+), 4 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java index 4bfe83fa6..407529345 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/DeviceInfo.java @@ -40,6 +40,7 @@ import org.json.JSONObject; import static android.content.Context.USAGE_STATS_SERVICE; +import static com.clevertap.android.sdk.inapp.InAppController.LOCAL_INAPP_COUNT; @RestrictTo(Scope.LIBRARY) public class DeviceInfo { @@ -725,6 +726,10 @@ int getWidthPixels() { return getDeviceCachedInfo().widthPixels; } + public int getLocalInAppCount(){ + return StorageHelper.getInt(context,LOCAL_INAPP_COUNT,0); + } + void onInitDeviceInfo(final String cleverTapID) { Task taskDeviceCachedInfo = CTExecutorFactory.executors(config).ioTask(); taskDeviceCachedInfo.execute("getDeviceCachedInfo", new Callable() { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index d37ea2720..07a22b837 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -223,9 +223,6 @@ public CTInAppNotification[] newArray(int size) { private boolean isLocalInApp = false; - private static final String HALF_INTERSTITIAL_LOCAL_IN_APP = "half-interstitial"; - private static final String ALERT_LOCAL_IN_APP = "alert-template"; - CTInAppNotification() { } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index f04f45eb9..24161daa0 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -113,6 +113,8 @@ int intValue() { private final MainLooperHandler mainLooperHandler; + public final static String LOCAL_INAPP_COUNT = "local_in_app_count"; + public InAppController(Context context, CleverTapInstanceConfig config, MainLooperHandler mainLooperHandler, @@ -473,7 +475,7 @@ public void run() { return; } showInApp(context, inAppNotification, config, this); - + incrementLocalInAppCountInPersistentStore(context, inAppNotification); } //InApp @@ -551,6 +553,14 @@ private static void inAppDidDismiss(Context context, CleverTapInstanceConfig con } } + private void incrementLocalInAppCountInPersistentStore(Context context, CTInAppNotification inAppNotification) { + if (inAppNotification.isLocalInApp()){ + int localInAppCount = StorageHelper.getInt(context,LOCAL_INAPP_COUNT,0); + ++localInAppCount; + StorageHelper.putInt(context,LOCAL_INAPP_COUNT,localInAppCount); + } + } + //InApp private static void showInApp(Context context, final CTInAppNotification inAppNotification, CleverTapInstanceConfig config, InAppController inAppController) { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/utils/CTJsonConverter.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/utils/CTJsonConverter.java index 0dd4a7ab6..b25677903 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/utils/CTJsonConverter.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/utils/CTJsonConverter.java @@ -127,6 +127,8 @@ public static JSONObject from(DeviceInfo deviceInfo, Location locationFromUser, evtData.put("Radio", radio); } } + //Adds an extra field to send local inApp count in queueData. + evtData.put("LIAMC",deviceInfo.getLocalInAppCount()); } catch (Throwable t) { // Ignore From d48a63ce92db590369694e570f3a8269471d0645 Mon Sep 17 00:00:00 2001 From: William John Date: Fri, 7 Oct 2022 17:28:48 +0530 Subject: [PATCH 18/58] task(SDK-1970)- Allow `fallBackToNotificationSettings` in local inApp, refactor CleverTapAPI.java, AlertDialogPromptForSettings.kt and InAppController.java, Update sample, --- .../clevertap/android/sdk/CTWebInterface.java | 2 +- .../clevertap/android/sdk/CleverTapAPI.java | 8 +- .../sdk/InAppNotificationActivity.java | 30 +++-- .../sdk/inapp/AlertDialogPromptForSettings.kt | 33 +++-- .../sdk/inapp/CTInAppBaseFragment.java | 2 +- .../sdk/inapp/CTInAppNotification.java | 11 ++ .../sdk/inapp/CTLocalInAppBuilder.java | 6 + .../android/sdk/inapp/InAppController.java | 9 +- .../com/clevertap/demo/HomeScreenActivity.kt | 10 +- .../clevertap/demo/ui/main/HomeScreenModel.kt | 4 + .../demo/ui/main/HomeScreenViewModel.kt | 127 +++++++++++++----- 11 files changed, 172 insertions(+), 70 deletions(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java index ee6c7b1bf..51f06ad8a 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CTWebInterface.java @@ -30,7 +30,7 @@ public void promptForNotificationPermission() { if (cleverTapAPI == null) { Logger.d("CleverTap Instance is null."); } else { - cleverTapAPI.promptForNotificationPermission(); + cleverTapAPI.promptForPushPermission(); } } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java index 5a62e90bb..edfc8de23 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/CleverTapAPI.java @@ -1033,9 +1033,9 @@ public static void tokenRefresh(Context context, String token, PushType pushType } } - public boolean isNotificationPermissionGranted(){ + public boolean isPushPermissionGranted(){ if (isAndroid13(context)) { - return coreState.getInAppController().isNotificationPermissionGranted(); + return coreState.getInAppController().isPushPermissionGranted(); }else{ return false; } @@ -1049,8 +1049,8 @@ public void promptPushPrimer(JSONObject jsonObject) { } } - public void promptForNotificationPermission(){ - if (isAndroid13(context)){//TODO check for multi instance support + public void promptForPushPermission(){ + if (isAndroid13(context)){ coreState.getInAppController().promptPermission(); }else{ Logger.v("Ensure your app supports Android 13 to verify permission access for notifications."); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index c829f818f..b0f17effc 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -183,16 +183,26 @@ public void prompt(){ } } + @RequiresApi(api = 33) public void requestPermission() { - boolean neverAskAgainClicked = !ActivityCompat.shouldShowRequestPermissionRationale( - InAppNotificationActivity.this, ANDROID_PERMISSION_STRING); + int permissionStatus = ContextCompat.checkSelfPermission(this, + Manifest.permission.POST_NOTIFICATIONS); + + if (permissionStatus == PackageManager.PERMISSION_DENIED){ + boolean neverAskAgainClicked = !ActivityCompat.shouldShowRequestPermissionRationale( + InAppNotificationActivity.this, ANDROID_PERMISSION_STRING); + + if (neverAskAgainClicked && inAppNotification.fallBackToNotificationSettings()) { + showFallbackAlertDialog(); + return; + } - if (neverAskAgainClicked) { ActivityCompat.requestPermissions(this, - new String[]{ANDROID_PERMISSION_STRING}, PERMISSION_REQUEST_CODE); - }else{ - permissionCallbackWeakReference.get().onReject(); - showFallbackAlertDialog(); + new String[]{ANDROID_PERMISSION_STRING}, PERMISSION_REQUEST_CODE); + + }else if (permissionStatus == PackageManager.PERMISSION_GRANTED){ + permissionCallbackWeakReference.get().onAccept(); + didDismiss(null); } } @@ -226,12 +236,6 @@ public void onDecline() { }); } - @RequiresApi(api = 33) - public static int isNotificationPermissionGranted(Activity activity){ - return ContextCompat.checkSelfPermission( - activity, Manifest.permission.POST_NOTIFICATIONS); - } - void didDismiss(Bundle data) { if (isAlertVisible) { isAlertVisible = false; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt index 12f8d452f..dbbbf21e9 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/AlertDialogPromptForSettings.kt @@ -19,15 +19,28 @@ object AlertDialogPromptForSettings { val message = activity.getString(R.string.permission_not_available_message) - AlertDialog.Builder(activity) - .setTitle(title) - .setMessage(message) - .setPositiveButton(R.string.permission_not_available_open_settings_option) { dialog, which -> - callback.onAccept() - } - .setNegativeButton(android.R.string.no) { dialog, which -> - callback.onDecline() - } - .show() + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.LOLLIPOP) { + AlertDialog.Builder(activity, android.R.style.Theme_Material_Light_Dialog_Alert) + .setTitle(title) + .setMessage(message) + .setPositiveButton(R.string.permission_not_available_open_settings_option) { dialog, which -> + callback.onAccept() + } + .setNegativeButton(android.R.string.no) { dialog, which -> + callback.onDecline() + } + .show() + }else{ + AlertDialog.Builder(activity) + .setTitle(title) + .setMessage(message) + .setPositiveButton(R.string.permission_not_available_open_settings_option) { dialog, which -> + callback.onAccept() + } + .setNegativeButton(android.R.string.no) { dialog, which -> + callback.onDecline() + } + .show() + } } } \ No newline at end of file diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java index f89d10110..4751f8141 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppBaseFragment.java @@ -144,7 +144,7 @@ void handleButtonClickAtIndex(int index) { if (index == 0 && inAppNotification.isLocalInApp()) { ((InAppNotificationActivity) context).prompt(); }else if (index == 1 && inAppNotification.isLocalInApp()){ - didDismiss(null); + didDismiss(data); }else { String actionUrl = button.getActionUrl(); if (actionUrl != null) { diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java index 07a22b837..56a708204 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNotification.java @@ -1,5 +1,6 @@ package com.clevertap.android.sdk.inapp; +import static com.clevertap.android.sdk.inapp.CTLocalInAppBuilder.FALLBACK_TO_NOTIFICATION_SETTINGS; import static com.clevertap.android.sdk.inapp.CTLocalInAppBuilder.IS_LOCAL_INAPP; import android.content.res.Configuration; import android.graphics.Bitmap; @@ -223,6 +224,8 @@ public CTInAppNotification[] newArray(int size) { private boolean isLocalInApp = false; + private boolean fallBackToNotificationSettings = false; + CTInAppNotification() { } @@ -271,6 +274,7 @@ private CTInAppNotification(Parcel in) { isPortrait = in.readByte() != 0x00; isLandscape = in.readByte() != 0x00; isLocalInApp = in.readByte() != 0x00; + fallBackToNotificationSettings = in.readByte() != 0x00; landscapeImageUrl = in.readString(); _landscapeImageCacheKey = in.readString(); timeToLive = in.readLong(); @@ -359,6 +363,7 @@ public void writeToParcel(Parcel dest, int flags) { dest.writeByte((byte) (isPortrait ? 0x01 : 0x00)); dest.writeByte((byte) (isLandscape ? 0x01 : 0x00)); dest.writeByte((byte) (isLocalInApp ? 0x01 : 0x00)); + dest.writeByte((byte) (fallBackToNotificationSettings ? 0x01 : 0x00)); dest.writeString(landscapeImageUrl); dest.writeString(_landscapeImageCacheKey); dest.writeLong(timeToLive); @@ -400,6 +405,10 @@ public boolean isLocalInApp() { return isLocalInApp; } + public boolean fallBackToNotificationSettings() { + return fallBackToNotificationSettings; + } + byte[] getGifByteArray(CTInAppNotificationMedia inAppMedia) { return GifCache.getByteArray(inAppMedia.getCacheKey()); } @@ -589,6 +598,8 @@ private void configureWithJson(JSONObject jsonObject) { .getString(Constants.NOTIFICATION_ID_TAG) : ""; this.type = jsonObject.getString(Constants.KEY_TYPE); this.isLocalInApp = jsonObject.has(IS_LOCAL_INAPP) && jsonObject.getBoolean(IS_LOCAL_INAPP); + this.fallBackToNotificationSettings = jsonObject.has(FALLBACK_TO_NOTIFICATION_SETTINGS) && + jsonObject.getBoolean(FALLBACK_TO_NOTIFICATION_SETTINGS); this.excludeFromCaps = jsonObject.has(Constants.KEY_EFC) && jsonObject.getInt(Constants.KEY_EFC) == 1; this.totalLifetimeCount = jsonObject.has(Constants.KEY_TLC) ? jsonObject.getInt(Constants.KEY_TLC) : -1; this.totalDailyCount = jsonObject.has(Constants.KEY_TDC) ? jsonObject.getInt(Constants.KEY_TDC) : -1; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java index d3b1132fa..7e5a34db4 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java @@ -15,6 +15,7 @@ public class CTLocalInAppBuilder { public static final String HALF_INTERSTITIAL_INAPP = "half-interstitial"; public static final String ALERT_INAPP = "alert-template"; protected static final String IS_LOCAL_INAPP = "isLocalInApp"; + protected static final String FALLBACK_TO_NOTIFICATION_SETTINGS = "fallbackToNotificationSettings"; private final String localInAppType;//Required private final JSONObject titleObj;// Required @@ -141,6 +142,11 @@ private Builder6(Builder1 builder) { this.builder = builder; } + public Builder6 fallbackToSettings(boolean fallbackToSettings) throws JSONException { + this.builder.jsonObject.put(FALLBACK_TO_NOTIFICATION_SETTINGS, fallbackToSettings); + return this; + } + public Builder6 backgroundColor(String backgroundColor) throws JSONException { this.builder.jsonObject.put(Constants.KEY_BG, backgroundColor); return this; diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java index 24161daa0..f183bae75 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/InAppController.java @@ -1,5 +1,6 @@ package com.clevertap.android.sdk.inapp; +import android.Manifest; import android.app.Activity; import android.content.Context; import android.content.Intent; @@ -9,6 +10,7 @@ import android.os.Looper; import androidx.annotation.RequiresApi; +import androidx.core.content.ContextCompat; import androidx.fragment.app.Fragment; import androidx.fragment.app.FragmentActivity; import androidx.fragment.app.FragmentTransaction; @@ -196,9 +198,10 @@ public void startPrompt(Activity activity, CleverTapInstanceConfig config){ } @RequiresApi(api = 33) - public boolean isNotificationPermissionGranted(){ - int permissionStatus = InAppNotificationActivity.isNotificationPermissionGranted( - Objects.requireNonNull(CoreMetaData.getCurrentActivity())); + public boolean isPushPermissionGranted(){ + int permissionStatus = ContextCompat.checkSelfPermission( + Objects.requireNonNull(CoreMetaData.getCurrentActivity()), + Manifest.permission.POST_NOTIFICATIONS); return permissionStatus == PackageManager.PERMISSION_GRANTED; } diff --git a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt index ccf996880..f6b331ea8 100644 --- a/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt +++ b/sample/src/main/java/com/clevertap/demo/HomeScreenActivity.kt @@ -8,6 +8,7 @@ import android.os.Build import android.os.Bundle import android.util.Log +import android.widget.Toast import androidx.appcompat.app.AppCompatActivity import androidx.fragment.app.commitNow import com.clevertap.android.sdk.* @@ -261,6 +262,11 @@ class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitList override fun onPushPermissionResponse(accepted: Boolean) { Log.i(TAG, "InApp---> response() called $accepted") + if(accepted){ + Toast.makeText(this, "Permission granted!", Toast.LENGTH_SHORT).show() + }else{ + Toast.makeText(this, "Permission denied!", Toast.LENGTH_SHORT).show() + } } override fun onInAppButtonClick(payload: HashMap?) { @@ -268,10 +274,10 @@ class HomeScreenActivity : AppCompatActivity(), CTInboxListener, DisplayUnitList } override fun onPositiveButtonClick(ctInAppNotification: CTInAppNotification?) { - Log.v(TAG, "onPositiveButtonClick() called") + Log.i(TAG, "onPositiveButtonClick() called") } override fun onNegativeButtonClick(ctInAppNotification: CTInAppNotification?) { - Log.v(TAG, "onNegativeButtonClick() called") + Log.i(TAG, "onNegativeButtonClick() called") } } \ No newline at end of file diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt index d3a9d62b8..366b7a77b 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenModel.kt @@ -66,7 +66,11 @@ object HomeScreenModel { ), "PROMPT LOCAL IN-APP" to listOf( "Generate Half-Interstitial Local InApp", + "Generate Half-Interstitial Local InApp with image URL", + "Generate Half-Interstitial Local InApp with fallbackToSettings - true", "Generate Alert Local InApp", + "Generate Alert Local InApp with followDeviceOrientation - false", + "Generate Alert Local InApp with fallbackToSettings - true", "Generate hard permission dialog" ) ) diff --git a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt index 1a92820c1..45d0caaac 100644 --- a/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt +++ b/sample/src/main/java/com/clevertap/demo/ui/main/HomeScreenViewModel.kt @@ -346,48 +346,103 @@ private val activity:FragmentActivity?) : ViewModel() { "918"-> cleverTapAPI?.pushEvent("Send Input Box Reminder DOC false") "919"-> cleverTapAPI?.pushEvent("Send Three CTA Notification") "100"-> { - if (cleverTapAPI?.isNotificationPermissionGranted == false){ - val builder = CTLocalInAppBuilder.builder() - .inAppType(HALF_INTERSTITIAL_INAPP,activity) - .titleText("Get Notified") - .messageText("Please enable notifications on your device to use Push Notifications.") - .followDeviceOrientation(true) - .positiveBtnText("Allow") - .negativeBtnText("Cancel") - .backgroundColor(Constants.WHITE) - .btnBorderColor(Constants.BLUE) - .titleTextColor(Constants.BLUE) - .messageTextColor(Constants.BLACK) - .btnTextColor(Constants.WHITE) - .btnBackgroundColor(Constants.BLUE) - .imageUrl("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png") - .build() - cleverTapAPI.promptPushPrimer(builder) - - }else{ - Log.v("HomeScreenViewModel","Notification permission is already granted.") - } + val builder = CTLocalInAppBuilder.builder() + .inAppType(HALF_INTERSTITIAL_INAPP,activity) + .titleText("Get Notified") + .messageText("Please enable notifications on your device to use Push Notifications.") + .followDeviceOrientation(true) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .backgroundColor(Constants.WHITE) + .btnBorderColor(Constants.BLUE) + .titleTextColor(Constants.BLUE) + .messageTextColor(Constants.BLACK) + .btnTextColor(Constants.WHITE) + .btnBackgroundColor(Constants.BLUE) + .build() + cleverTapAPI?.promptPushPrimer(builder) } "101"->{ - if (cleverTapAPI?.isNotificationPermissionGranted == false) { - val builder = CTLocalInAppBuilder.builder() - .inAppType(ALERT_INAPP,activity) - .titleText("Get Notified") - .messageText("Enable Notification permission") - .followDeviceOrientation(true) - .positiveBtnText("Allow") - .negativeBtnText("Cancel") - .build() - cleverTapAPI.promptPushPrimer(builder) - }else{ - Log.v("HomeScreenViewModel","Notification permission is already granted.") - } + val builder = CTLocalInAppBuilder.builder() + .inAppType(HALF_INTERSTITIAL_INAPP,activity) + .titleText("Get Notified") + .messageText("Please enable notifications on your device to use Push Notifications.") + .followDeviceOrientation(true) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .backgroundColor(Constants.WHITE) + .btnBorderColor(Constants.BLUE) + .titleTextColor(Constants.BLUE) + .messageTextColor(Constants.BLACK) + .btnTextColor(Constants.WHITE) + .btnBackgroundColor(Constants.BLUE) + .imageUrl("https://icons.iconarchive.com/icons/treetog/junior/64/camera-icon.png") + .build() + cleverTapAPI?.promptPushPrimer(builder) } "102"->{ - if (cleverTapAPI?.isNotificationPermissionGranted == false) { - cleverTapAPI.promptForNotificationPermission() + val builder = CTLocalInAppBuilder.builder() + .inAppType(HALF_INTERSTITIAL_INAPP,activity) + .titleText("Get Notified") + .messageText("Please enable notifications on your device to use Push Notifications.") + .followDeviceOrientation(true) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .backgroundColor(Constants.WHITE) + .btnBorderColor(Constants.BLUE) + .titleTextColor(Constants.BLUE) + .messageTextColor(Constants.BLACK) + .btnTextColor(Constants.WHITE) + .btnBackgroundColor(Constants.BLUE) + .fallbackToSettings(true) + .build() + cleverTapAPI?.promptPushPrimer(builder) + + } + + "103"->{ + val builder = CTLocalInAppBuilder.builder() + .inAppType(ALERT_INAPP,activity) + .titleText("Get Notified") + .messageText("Enable Notification permission") + .followDeviceOrientation(true) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .build() + cleverTapAPI?.promptPushPrimer(builder) + } + + "104"->{ + val builder = CTLocalInAppBuilder.builder() + .inAppType(ALERT_INAPP,activity) + .titleText("Get Notified") + .messageText("Enable Notification permission") + .followDeviceOrientation(false) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .fallbackToSettings(true) + .build() + cleverTapAPI?.promptPushPrimer(builder) + } + + "105"->{ + val builder = CTLocalInAppBuilder.builder() + .inAppType(ALERT_INAPP,activity) + .titleText("Get Notified") + .messageText("Enable Notification permission") + .followDeviceOrientation(false) + .positiveBtnText("Allow") + .negativeBtnText("Cancel") + .fallbackToSettings(true) + .build() + cleverTapAPI?.promptPushPrimer(builder) + } + + "106"->{ + if (cleverTapAPI?.isPushPermissionGranted == false) { + cleverTapAPI.promptForPushPermission() }else{ Log.v("HomeScreenViewModel","Notification permission is already granted.") } From bf9e56c34e07469932bbfb38d7ca583be4884f6d Mon Sep 17 00:00:00 2001 From: Piyush Kukadiya Date: Mon, 10 Oct 2022 17:28:34 +0530 Subject: [PATCH 19/58] task(SDK-1970) : Add LocalInApp builder written in kotlin --- .../android/sdk/inapp/CTLocalInApp.kt | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt new file mode 100644 index 000000000..4eed539fc --- /dev/null +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt @@ -0,0 +1,139 @@ +package com.clevertap.android.sdk.inapp + +import android.content.Context +import com.clevertap.android.sdk.Constants +import com.clevertap.android.sdk.DeviceInfo +import org.json.JSONArray +import org.json.JSONObject + +class CTLocalInApp private constructor() { + + enum class InAppType(val type: String) { + ALERT(CTInAppType.CTInAppTypeAlert.toString()), + HALF_INTERSTITIAL(CTInAppType.CTInAppTypeHalfInterstitial.toString()) + } + + companion object { + + @JvmStatic + fun builder(context: Context): Builder = Builder(context) + const val IS_LOCAL_INAPP = " isLocalInApp" + } + + class Builder internal constructor(private val context: Context) { + + private var jsonObject = JSONObject() + + fun setInAppType(inAppType: InAppType) = + jsonObject.run { + put(Constants.KEY_TYPE, inAppType.type) + put(IS_LOCAL_INAPP, true) + put(Constants.KEY_HIDE_CLOSE, true) + put( + Constants.KEY_IS_TABLET, + DeviceInfo.getDeviceType(this@Builder.context) == DeviceInfo.TABLET + ) + Builder1(this) + } + + class Builder1(private var jsonObject: JSONObject) { + + fun setTitleText(titleText: String) = + jsonObject.run { + put(Constants.KEY_TITLE, JSONObject().put(Constants.KEY_TEXT, titleText)) + Builder2(this) + } + } + + class Builder2(private var jsonObject: JSONObject) { + + fun setMessageText(messageText: String) = + jsonObject.run { + put(Constants.KEY_MESSAGE, JSONObject().put(Constants.KEY_TEXT, messageText)) + Builder3(this) + } + } + + class Builder3(private var jsonObject: JSONObject) { + + fun followDeviceOrientation(deviceOrientation: Boolean) = + jsonObject.run { + put(Constants.KEY_PORTRAIT, true) + put(Constants.KEY_LANDSCAPE, deviceOrientation) + Builder4(this) + } + } + + class Builder4(private var jsonObject: JSONObject) { + + fun setPositiveBtnText(positiveBtnText: String) = + jsonObject.run { + val positiveButtonObject = JSONObject().apply { + put(Constants.KEY_TEXT, positiveBtnText) + put(Constants.KEY_RADIUS, "2") + } + put(Constants.KEY_BUTTONS, JSONArray().put(0, positiveButtonObject)) + Builder5(this) + } + } + + class Builder5(private var jsonObject: JSONObject) { + + fun setNegativeBtnText(negativeBtnText: String) = + jsonObject.run { + val negativeButtonObject = JSONObject().apply { + put(Constants.KEY_TEXT, negativeBtnText) + put(Constants.KEY_RADIUS, "2") + } + getJSONArray(Constants.KEY_BUTTONS).put(1, negativeButtonObject) + Builder6(this) + } + } + + class Builder6(private var jsonObject: JSONObject) { + + fun setBackgroundColor(backgroundColor: String) = + apply { jsonObject.put(Constants.KEY_BG, backgroundColor) } + + fun setImageUrl(imageUrl: String) = + apply { + val mediaObject = JSONObject().apply { + put(Constants.KEY_URL, imageUrl) + put(Constants.KEY_CONTENT_TYPE, "image") + } + jsonObject.apply { + put(Constants.KEY_MEDIA, mediaObject) + if (getBoolean(Constants.KEY_LANDSCAPE)) { + put(Constants.KEY_MEDIA_LANDSCAPE, mediaObject) + } + } + } + + fun setTitleTextColor(titleTextColor: String) = + apply { jsonObject.getJSONObject(Constants.KEY_TITLE).put(Constants.KEY_COLOR, titleTextColor) } + + fun setMessageTextColor(messageTextColor: String) = + apply { jsonObject.getJSONObject(Constants.KEY_MESSAGE).put(Constants.KEY_COLOR, messageTextColor) } + + fun setBtnTextColor(btnTextColor: String) = + apply { updateActionButtonArray(Constants.KEY_COLOR, btnTextColor) } + + fun setBtnBackgroundColor(btnBackgroundColor: String) = + apply { updateActionButtonArray(Constants.KEY_BG, btnBackgroundColor) } + + fun setBtnBorderColor(btnBorderColor: String) = + apply { updateActionButtonArray(Constants.KEY_BORDER, btnBorderColor) } + + fun setBtnBorderRadius(btnBorderRadius: String) = + apply { updateActionButtonArray(Constants.KEY_RADIUS, btnBorderRadius) } + + private val updateActionButtonArray: (String, String) -> Unit = { key, value -> + arrayOf(0, 1).forEach { + jsonObject.getJSONArray(Constants.KEY_BUTTONS).getJSONObject(it).put(key, value) + } + } + + fun build() = jsonObject + } + } +} From a7b61f9affd23b9fa3cefdf925fd7c2d5a42fcc0 Mon Sep 17 00:00:00 2001 From: Piyush Kukadiya Date: Tue, 11 Oct 2022 18:25:28 +0530 Subject: [PATCH 20/58] task(SDK-1970) : remove typo from IS_LOCAL_INAPP key --- .../main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt index 4eed539fc..636936044 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInApp.kt @@ -17,7 +17,7 @@ class CTLocalInApp private constructor() { @JvmStatic fun builder(context: Context): Builder = Builder(context) - const val IS_LOCAL_INAPP = " isLocalInApp" + const val IS_LOCAL_INAPP = "isLocalInApp" } class Builder internal constructor(private val context: Context) { From 8e653c3994ff87e3598fbfcd7cc55ff562ff468f Mon Sep 17 00:00:00 2001 From: William John Date: Wed, 12 Oct 2022 16:57:15 +0530 Subject: [PATCH 21/58] task(SDK-1970) - Add `fallbackToNotificationSettings` in CTLocalInApp.kt, refactor hard permission flow if permission is denied --- .../sdk/InAppNotificationActivity.java | 34 +-- .../clevertap/android/sdk/StorageHelper.java | 2 +- ...CTInAppNativeHalfInterstitialFragment.java | 14 +- .../sdk/inapp/CTInAppNotification.java | 4 +- .../sdk/inapp/CTInAppNotificationButton.java | 15 -- .../android/sdk/inapp/CTLocalInApp.kt | 12 +- .../sdk/inapp/CTLocalInAppBuilder.java | 238 ------------------ .../android/sdk/inapp/InAppController.java | 49 +++- .../com/clevertap/demo/ViewModelFactory.kt | 4 +- .../demo/ui/main/HomeScreenFragment.kt | 2 +- .../demo/ui/main/HomeScreenViewModel.kt | 126 +++++----- 11 files changed, 146 insertions(+), 354 deletions(-) delete mode 100644 clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTLocalInAppBuilder.java diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java index b0f17effc..758300982 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/InAppNotificationActivity.java @@ -1,6 +1,7 @@ package com.clevertap.android.sdk; import static com.clevertap.android.sdk.Utils.isAndroid13; +import static com.clevertap.android.sdk.inapp.InAppController.IS_FIRST_TIME_PERMISSION_REQUEST; import android.Manifest; import android.app.Activity; @@ -52,7 +53,7 @@ public final class InAppNotificationActivity extends FragmentActivity implements private static final int PERMISSION_REQUEST_CODE = 2; - private static final String ANDROID_PERMISSION_STRING = "android.permission.POST_NOTIFICATIONS"; + public static final String ANDROID_PERMISSION_STRING = "android.permission.POST_NOTIFICATIONS"; public interface PermissionCallback { void onAccept(); @@ -71,7 +72,8 @@ public void onCreate(Bundle savedInstanceState) { throw new IllegalArgumentException(); } inAppNotification = notif.getParcelable("inApp"); - boolean displayHardNotificationDialog = notif.getBoolean("displayHardPermissionDialog",false); + boolean displayHardNotificationDialog = notif.getBoolean("displayHardPermissionDialog", + false); // Using this boolean for a directly showing hard permission dialog flow Bundle configBundle = notif.getBundle("configBundle"); if (configBundle != null) { config = configBundle.getParcelable("config"); @@ -185,30 +187,28 @@ public void prompt(){ @RequiresApi(api = 33) public void requestPermission() { - int permissionStatus = ContextCompat.checkSelfPermission(this, + int permissionStatus = ContextCompat.checkSelfPermission(InAppNotificationActivity.this, Manifest.permission.POST_NOTIFICATIONS); if (permissionStatus == PackageManager.PERMISSION_DENIED){ - boolean neverAskAgainClicked = !ActivityCompat.shouldShowRequestPermissionRationale( - InAppNotificationActivity.this, ANDROID_PERMISSION_STRING); - - if (neverAskAgainClicked && inAppNotification.fallBackToNotificationSettings()) { - showFallbackAlertDialog(); - return; - } - - ActivityCompat.requestPermissions(this, + if (!StorageHelper.getBoolean(InAppNotificationActivity.this, + IS_FIRST_TIME_PERMISSION_REQUEST,true)) { + boolean neverAskAgainClicked = ActivityCompat.shouldShowRequestPermissionRationale( + InAppNotificationActivity.this, ANDROID_PERMISSION_STRING); + if (neverAskAgainClicked && inAppNotification.fallBackToNotificationSettings()) { + showFallbackAlertDialog(); + } + }else{ + ActivityCompat.requestPermissions(InAppNotificationActivity.this, new String[]{ANDROID_PERMISSION_STRING}, PERMISSION_REQUEST_CODE); - - }else if (permissionStatus == PackageManager.PERMISSION_GRANTED){ - permissionCallbackWeakReference.get().onAccept(); - didDismiss(null); + } } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); + StorageHelper.putBoolean(InAppNotificationActivity.this,IS_FIRST_TIME_PERMISSION_REQUEST,false); if (requestCode == PERMISSION_REQUEST_CODE) { boolean granted = grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED; @@ -222,7 +222,7 @@ public void onRequestPermissionsResult(int requestCode, @NonNull String[] permis } public void showFallbackAlertDialog() { - AlertDialogPromptForSettings.INSTANCE.show(this, new AlertDialogPromptForSettings.Callback() { + AlertDialogPromptForSettings.INSTANCE.show(InAppNotificationActivity.this, new AlertDialogPromptForSettings.Callback() { @Override public void onAccept() { Utils.navigateToAndroidSettingsForNotifications(InAppNotificationActivity.this); diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/StorageHelper.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/StorageHelper.java index a97e55b22..d87c7752e 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/StorageHelper.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/StorageHelper.java @@ -95,7 +95,7 @@ public static String storageKeyWithSuffix(@NonNull CleverTapInstanceConfig confi } @SuppressWarnings("SameParameterValue") - static boolean getBoolean(Context context, String key, boolean defaultValue) { + public static boolean getBoolean(Context context, String key, boolean defaultValue) { return getPreferences(context).getBoolean(key, defaultValue); } diff --git a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNativeHalfInterstitialFragment.java b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNativeHalfInterstitialFragment.java index 81b341ddd..6483ee4ab 100644 --- a/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNativeHalfInterstitialFragment.java +++ b/clevertap-core/src/main/java/com/clevertap/android/sdk/inapp/CTInAppNativeHalfInterstitialFragment.java @@ -1,6 +1,7 @@ package com.clevertap.android.sdk.inapp; import android.annotation.SuppressLint; +import android.content.Context; import android.content.res.Configuration; import android.graphics.Color; import android.graphics.drawable.ColorDrawable; @@ -19,6 +20,8 @@ import android.widget.TextView; import androidx.annotation.NonNull; import androidx.annotation.Nullable; + +import com.clevertap.android.sdk.DeviceInfo; import com.clevertap.android.sdk.R; import com.clevertap.android.sdk.customviews.CloseImageView; import java.util.ArrayList; @@ -34,7 +37,8 @@ public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup c ArrayList