Skip to content

Commit

Permalink
Merge pull request #351 from CleverTap/task/SDK-1769/PushPrimer
Browse files Browse the repository at this point in the history
[SDK-1970] - Push primer for Android 13
  • Loading branch information
william-ct authored Nov 1, 2022
2 parents 5e0e7df + e5ba0bd commit 50bf3cc
Show file tree
Hide file tree
Showing 78 changed files with 2,236 additions and 461 deletions.
12 changes: 6 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,15 +26,15 @@ We publish the SDK to `mavenCentral` as an `AAR` file. Just declare it as depend

```groovy
dependencies {
implementation "com.clevertap.android:clevertap-android-sdk:4.6.6"
implementation "com.clevertap.android:clevertap-android-sdk:4.7.0"
}
```

Alternatively, you can download and add the AAR file included in this repo in your Module libs directory and tell gradle to install it like this:

```groovy
dependencies {
implementation (name: "clevertap-android-sdk-4.6.6", ext: 'aar')
implementation (name: "clevertap-android-sdk-4.7.0", ext: 'aar')
}
```

Expand All @@ -46,9 +46,9 @@ Add the Firebase Messaging library and Android Support Library v4 as dependencie

```groovy
dependencies {
implementation "com.clevertap.android:clevertap-android-sdk:4.6.6"
implementation "androidx.core:core:1.3.0"
implementation "com.google.firebase:firebase-messaging:21.0.0"
implementation "com.clevertap.android:clevertap-android-sdk:4.7.0"
implementation "androidx.core:core:1.9.0"
implementation "com.google.firebase:firebase-messaging:23.0.6"
implementation "com.google.android.gms:play-services-ads:19.4.0" // Required only if you enable Google ADID collection in the SDK (turned off by default).
implementation "com.android.installreferrer:installreferrer:2.2" // Mandatory for v3.6.4 and above
}
Expand All @@ -71,7 +71,7 @@ Also be sure to include the `google-services.json` classpath in your Project lev
}
dependencies {
classpath "com.android.tools.build:gradle:7.2.1"
classpath "com.android.tools.build:gradle:7.3.0"
classpath "com.google.gms:google-services:4.3.3"
// NOTE: Do not place your application dependencies here; they belong
Expand Down
9 changes: 9 additions & 0 deletions buildSrc/settings.gradle.kts
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,15 @@ pluginManagement {
//// # available:"0.21.0"
//// # available:"0.22.0"
//// # available:"0.23.0"
//// # available:"0.30.0"
//// # available:"0.30.1"
//// # available:"0.30.2"
//// # available:"0.40.0"
//// # available:"0.40.1"
//// # available:"0.40.2"
//// # available:"0.50.0"
//// # available:"0.50.1"
//// # available:"0.50.2"
}
}

Expand Down
8 changes: 4 additions & 4 deletions buildSrc/src/main/kotlin/Libs.kt
Original file line number Diff line number Diff line change
Expand Up @@ -177,10 +177,10 @@ object Libs {
object Android {

// Android SDK
const val compileSdkVersionVal = 31
const val targetSdkVersionVal = 31
const val buildToolsVersionVal = "30.0.3"
const val minSdkVersionVal = 16
const val compileSdkVersionVal = 33
const val targetSdkVersionVal = 33
const val buildToolsVersionVal = "33.0.0"
const val minSdkVersionVal = 19
}

object SDKTest {
Expand Down
3 changes: 3 additions & 0 deletions clevertap-core/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@
<manifest package="com.clevertap.android.sdk"
xmlns:android="http://schemas.android.com/apk/res/android">

<!-- Required runtime permission to display notifications on Android 13 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>

<application>

<activity
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public abstract class BaseCallbackManager {

public abstract InAppNotificationListener getInAppNotificationListener();

public abstract PushPermissionResponseListener getPushPermissionResponseListener();

public abstract CTInboxListener getInboxListener();

public abstract CTProductConfigListener getProductConfigListener();
Expand Down Expand Up @@ -60,6 +62,8 @@ public abstract void setInAppNotificationButtonListener(

public abstract void setInAppNotificationListener(InAppNotificationListener inAppNotificationListener);

public abstract void setPushPermissionResponseListener(PushPermissionResponseListener pushPermissionResponseListener);

public abstract void setInboxListener(CTInboxListener inboxListener);

public abstract void setProductConfigListener(
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.clevertap.android.sdk

import android.content.Context
import com.clevertap.android.sdk.inapp.InAppController
import com.clevertap.android.sdk.task.CTExecutorFactory

class CTPreferenceCache {

fun isFirstTimeRequest() = firstTimeRequest
fun setFirstTimeRequest(fTR : Boolean) {
firstTimeRequest = fTR
}

companion object {

@Volatile
private var INSTANCE: CTPreferenceCache? = null

@JvmField
var firstTimeRequest = true

@JvmStatic
fun getInstance(context: Context, config: CleverTapInstanceConfig): CTPreferenceCache =
INSTANCE ?: synchronized(this) {
INSTANCE ?: buildCache(context, config).also { INSTANCE = it }
}

private fun buildCache(context: Context, config: CleverTapInstanceConfig): CTPreferenceCache {
CTExecutorFactory.executors(config).ioTask<Void>().execute("buildCache") {
firstTimeRequest = StorageHelper.getBoolean(
context,
InAppController.IS_FIRST_TIME_PERMISSION_REQUEST, true
)
null
}
return CTPreferenceCache()
}

@JvmStatic
fun updateCacheToDisk(context: Context, config: CleverTapInstanceConfig) {
CTExecutorFactory.executors(config).ioTask<Void>().execute("updateCacheToDisk") {
StorageHelper.putBooleanImmediate(
context, InAppController.IS_FIRST_TIME_PERMISSION_REQUEST,
firstTimeRequest
)
null
}
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package com.clevertap.android.sdk

import android.content.Context
import androidx.annotation.RestrictTo
import androidx.annotation.RestrictTo.Scope.LIBRARY_GROUP

@RestrictTo(LIBRARY_GROUP)
class CTStringResources(private val context: Context, vararg sRID: Int) {

private var sArray: Array<String>

init {
sArray = Array(sRID.size) { context.getString(sRID[it]) }
}

operator fun component1(): String? = sArray.getOrNull(0)
operator fun component2(): String? = sArray.getOrNull(1)
operator fun component3(): String? = sArray.getOrNull(2)
operator fun component4(): String? = sArray.getOrNull(3)
operator fun component5(): String? = sArray.getOrNull(4)
}
Original file line number Diff line number Diff line change
@@ -1,6 +1,8 @@
package com.clevertap.android.sdk;

import android.webkit.JavascriptInterface;
import androidx.annotation.RestrictTo;
import com.clevertap.android.sdk.inapp.CTInAppBaseFullFragment;
import java.lang.ref.WeakReference;
import java.util.ArrayList;
import java.util.HashMap;
Expand All @@ -15,11 +17,47 @@
public class CTWebInterface {

private final WeakReference<CleverTapAPI> weakReference;
private CTInAppBaseFullFragment inAppBaseFullFragment;

public CTWebInterface(CleverTapAPI instance) {
this.weakReference = new WeakReference<>(instance);
}

@RestrictTo(RestrictTo.Scope.LIBRARY_GROUP)
public CTWebInterface(CleverTapAPI instance, CTInAppBaseFullFragment inAppBaseFullFragment){
this.weakReference = new WeakReference<>(instance);
this.inAppBaseFullFragment = inAppBaseFullFragment;
}

/**
* Method to be called from WebView Javascript to request permission for notification
* for Android 13 and above
*/
@JavascriptInterface
public void promptPushPermission(boolean shouldShowFallbackSettings) {
CleverTapAPI cleverTapAPI = weakReference.get();
if (cleverTapAPI == null) {
Logger.d("CleverTap Instance is null.");
} else {
//Dismisses current IAM and proceeds to call promptForPushPermission()
dismissInAppNotification();
cleverTapAPI.promptForPushPermission(shouldShowFallbackSettings);
}
}
/**
* Method to be called from WebView Javascript to dismiss the InApp notification
*/
@JavascriptInterface
public void dismissInAppNotification() {
CleverTapAPI cleverTapAPI = weakReference.get();
if (cleverTapAPI == null) {
Logger.d("CleverTap Instance is null.");
} else {
//Dismisses current IAM and proceeds to call promptForPushPermission()
inAppBaseFullFragment.didDismiss(null);
}
}

/**
* Method to be called from WebView Javascript to add profile properties in CleverTap
*
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
@file:JvmName("CTXtensions")

package com.clevertap.android.sdk

import android.content.Context
import android.os.Build.VERSION

fun Context.isPackageAndOsTargetsAbove(apiLevel: Int) =
VERSION.SDK_INT > apiLevel && targetSdkVersion > apiLevel

val Context.targetSdkVersion
get() = applicationContext.applicationInfo.targetSdkVersion
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,8 @@ public class CallbackManager extends BaseCallbackManager {

private InAppNotificationListener inAppNotificationListener;

private PushPermissionResponseListener pushPermissionResponseListener;

private CTInboxListener inboxListener;

private final CleverTapInstanceConfig config;
Expand Down Expand Up @@ -131,11 +133,21 @@ public InAppNotificationListener getInAppNotificationListener() {
return inAppNotificationListener;
}

@Override
public PushPermissionResponseListener getPushPermissionResponseListener() {
return pushPermissionResponseListener;
}

@Override
public void setInAppNotificationListener(final InAppNotificationListener inAppNotificationListener) {
this.inAppNotificationListener = inAppNotificationListener;
}

@Override
public void setPushPermissionResponseListener(PushPermissionResponseListener pushPermissionResponseListener) {
this.pushPermissionResponseListener = pushPermissionResponseListener;
}

@Override
public CTInboxListener getInboxListener() {
return inboxListener;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,11 +1,13 @@
package com.clevertap.android.sdk;

import static android.content.Context.NOTIFICATION_SERVICE;
import static com.clevertap.android.sdk.CTXtensions.isPackageAndOsTargetsAbove;
import static com.clevertap.android.sdk.Utils.getSCDomain;
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;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.NotificationChannel;
import android.app.NotificationChannelGroup;
Expand All @@ -20,7 +22,6 @@
import android.os.Build;
import android.os.Bundle;
import android.text.TextUtils;

import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
Expand All @@ -32,13 +33,14 @@
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.CTLocalInApp;
import com.clevertap.android.sdk.inbox.CTInboxActivity;
import com.clevertap.android.sdk.inbox.CTInboxMessage;
import com.clevertap.android.sdk.inbox.CTMessageDAO;
import com.clevertap.android.sdk.interfaces.SCDomainListener;
import com.clevertap.android.sdk.interfaces.NotificationHandler;
import com.clevertap.android.sdk.interfaces.NotificationRenderedListener;
import com.clevertap.android.sdk.interfaces.OnInitCleverTapIDListener;
import com.clevertap.android.sdk.interfaces.SCDomainListener;
import com.clevertap.android.sdk.network.NetworkManager;
import com.clevertap.android.sdk.product_config.CTProductConfigController;
import com.clevertap.android.sdk.product_config.CTProductConfigListener;
Expand Down Expand Up @@ -1032,6 +1034,46 @@ public static void tokenRefresh(Context context, String token, PushType pushType
}
}

/**
* Checks whether notification permission is granted or denied for Android 13 and above devices.
* @return boolean Returns true/false based on whether permission is granted or denied.
*/
@SuppressLint("NewApi")
public boolean isPushPermissionGranted(){
if (isPackageAndOsTargetsAbove(context, 32)) {
return coreState.getInAppController().isPushPermissionGranted();
} else {
return false;
}
}

/**
* Calls the push primer flow for Android 13 and above devices.
* @param jsonObject JSONObject - Accepts jsonObject created by {@link CTLocalInApp} object
*/
@SuppressLint("NewApi")
public void promptPushPrimer(JSONObject jsonObject) {
if (isPackageAndOsTargetsAbove(context, 32)) {
coreState.getInAppController().promptPushPrimer(jsonObject);
} else {
Logger.v("Ensure your app supports Android 13 to verify permission access for notifications.");
}
}

/**
* Calls directly hard permission dialog, if push primer is not required.
* @param showFallbackSettings - boolean - If `showFallbackSettings` is true then we show a alert
* dialog which routes to app's notification settings page.
*/
@SuppressLint("NewApi")
public void promptForPushPermission(boolean showFallbackSettings){
if (isPackageAndOsTargetsAbove(context, 32)) {
coreState.getInAppController().promptPermission(showFallbackSettings);
} else {
Logger.v("Ensure your app supports Android 13 to verify permission access for notifications.");
}
}

// Initialize
private CleverTapAPI(final Context context, final CleverTapInstanceConfig config, String cleverTapID) {
this.context = context;
Expand Down Expand Up @@ -1574,8 +1616,6 @@ public Map<String, EventDetail> getHistory() {
return coreState.getLocalDataStore().getEventHistory(context);
}

//DeepLink

/**
* Returns the InAppNotificationListener object
*
Expand All @@ -1596,6 +1636,28 @@ public void setInAppNotificationListener(InAppNotificationListener inAppNotifica
coreState.getCallbackManager().setInAppNotificationListener(inAppNotificationListener);
}

/**
* Returns the PushPermissionNotificationResponseListener object
*
* @return An {@link PushPermissionResponseListener} object
*/
@SuppressWarnings({"unused", "WeakerAccess"})
public PushPermissionResponseListener getPushPermissionNotificationResponseListener() {
return coreState.getCallbackManager().getPushPermissionResponseListener();
}

/**
* This method sets the PushPermissionNotificationResponseListener
*
* @param pushPermissionResponseListener An {@link PushPermissionResponseListener} object
*/
@SuppressWarnings({"unused"})
public void setPushPermissionNotificationResponseListener(PushPermissionResponseListener
pushPermissionResponseListener) {
coreState.getCallbackManager().
setPushPermissionResponseListener(pushPermissionResponseListener);
}

/**
* Returns the count of all inbox messages for the user
*
Expand Down
Loading

0 comments on commit 50bf3cc

Please sign in to comment.