Skip to content

Commit 0d53bfe

Browse files
committed
Release v1.1.3
1 parent 7458aaa commit 0d53bfe

34 files changed

+1800
-106
lines changed

CHANGELOG.md

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,19 @@
22

33
All notable changes to this project will be documented in this file.
44

5+
## 1.1.3
6+
7+
### Changed
8+
- Enhanced the session analytics feature to work better across different environments.
9+
10+
### Fixed
11+
- Fix the bugs related to on-demand sessions providing a more stable experience.
12+
13+
## 1.1.2
14+
15+
### Fixed
16+
- Fix the session recording experience in the SDK.
17+
518
## 1.1.1
619

720
### Added

MIGRATION.md

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
# Migration Guide
2+
This guide and chart should help facilitate the transition from the legacy UserExperior SDK to the new DevRev SDK in your Android application, providing insights into feature equivalents and method changes.
3+
4+
## Feature Equivalence Chart
5+
6+
| Feature | UserExperior SDK | DevRev SDK (Kotlin) | DevRev SDK (Java) |
7+
|-|-|-|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
8+
| Installation | `implementation 'com.userexperior:userexperior-android::<version>’` | `implementation("ai.devrev.sdk:devrev-sdk:<version>") ` | `implementation("ai.devrev.sdk:devrev-sdk:<version>") ` |
9+
| Initialization | `UserExperior.startRecording(Context context, String ueSdkAppVersionKey)` | `DevRev.configure(context: Context, appId: String, prefersDialogMode: Boolean)` | `DevRev.INSTANCE.configure(Context context, String appId, Boolean prefersDialogMode)` |
10+
| User Identification | `UserExperior.setUserIdentifier(String userIdentifier)` | `DevRev.identifyAnonymousUser(userId: String)`<br> `DevRev.identifyUnverifiedUser(identity: Identity)`<br> `DevRev.updateUser(identity: Identity)`<br> `DevRev.logout(deviceID: String)` | `DevRev.INSTANCE.identifyAnonymousUser(String userId)`<br> `DevRev.INSTANCE.identifyUnverifiedUser(Identity identity)`<br> `DevRev.INSTANCE.updateUser(Identity identity)`<br> `DevRev.INSTANCE.logout(String deviceID)` |
11+
| Event Tracking | `UserExperior.logEvent(String event, HashMap<String, Object> properties)` | `DevRev.trackEvent(name: String, properties: HashMap<String, String>)` | `DevRevAnalyticsExtKt.trackEvent(DevRev.INSTANCE, String name, HashMap<String, String> properties)` |
12+
| Session Recording | `UserExperior.stopRecording()`<br />`UserExperior.pauseRecording()`<br />`UserExperior.resumeRecording()` | `DevRev.startRecording()`<br />`DevRev.stopRecording()`<br />`DevRev.pauseRecording()`<br />`DevRev.resumeRecording()`<br />`DevRev.processAllOnDemandSessions()` | `DevRevObservabilityExtKt.startRecording(DevRev.INSTANCE, context)`<br />`DevRevObservabilityExtKt.stopRecording(DevRev.INSTANCE)`<br />`DevRevObservabilityExtKt.pauseRecording(DevRev.INSTANCE)`<br />`DevRevObservabilityExtKt.resumeRecording(DevRev.INSTANCE)`<br />`DevRevObservabilityExtKt.processAllOnDemandSessions(DevRev.INSTANCE)` |
13+
| Opting in/out | `UserExperior.consentOptOut()`<br />`UserExperior.consentOptIn()`<br>`UserExperior.getConsentStatus()`<br>`UserExperior.getOptOutStatus()` | `DevRev.stopAllMonitoring()`<br />`DevRev.resumeAllMonitoring()` | `DevRevObservabilityExtKt.stopAllMonitoring(DevRev.INSTANCE)`<br />`DevRevObservabilityExtKt.resumeAllMonitoring(DevRev.INSTANCE)` |
14+
| Session Properties | `UserExperior.setUserProperties(HashMap<String, Object> userProperties)` | `DevRev.addSessionProperties(properties: HashMap<String, Any>)`<br />`DevRev.clearSessionProperties()` | `DevRevObservabilityExtKt.addSessionProperties(DevRev.INSTANCE, HashMap<String, Object> properties)`<br />`DevRevObservabilityExtKt.clearSessionProperties(DevRev.INSTANCE)` |
15+
| Masking Sensitive Data | `UserExperior.markSensitiveView(View view)`<br />`UserExperior.unmarkSensitiveView(View view)` | `DevRev.markSensitiveViews(sensitiveViews: List<View>)`<br />`DevRev.unmarkSensitiveViews(sensitiveViews: List<View>)` | `DevRevObservabilityExtKt.markSensitiveViews(DevRev.INSTANCE, List<View> sensitiveViews)`<br />`DevRevObservabilityExtKt.unmarkSensitiveViews(DevRev.INSTANCE, List<View> sensitiveViews)` |
16+
| Timers | `UserExperior.startTimer(String timerName, HashMap<String, String> properties)`<br> `UserExperior.endTimer(String timerName, HashMap<String, String> properties)` | `DevRev.startTimer(name: String, properties: HashMap<String, String>)`<br> `DevRev.endTimer(name: String, properties: HashMap<String, String>)` | `DevRevObservabilityExtKt.startTimer(DevRev.INSTANCE, String name, HashMap<String, String> properties)`<br> `DevRevObservabilityExtKt.endTimer(DevRev.INSTANCE, String name, HashMap<String, String> properties)` |
17+
| PLuG support chat | Not supported. | `DevRev.showSupport(context: Context)`<br> `DevRev.createSupportConversation()`<br> `DevRev.setShouldDismissModalsOnOpenLink(value: Boolean)`<br> `DevRev.setInAppLinkHandler(handler: (String) -> Unit)` | `DevRevExtKt.showSupport(DevRev.INSTANCE, context)`<br> `DevRev.INSTANCE.createSupportConversation(Context context)`<br> `DevRev.INSTANCE.setShouldDismissModalsOnOpenLink(Boolean value)`<br> `DevRev.INSTANCE.setInAppLinkHandler(Function1<? super String, Unit> handler)` |
18+
| Push Notifications | Not supported. | `DevRev.registerDeviceToken(context: Context, deviceToken: String, deviceId: String,)`<br> `DevRev.processPushNotification(context: Context, userInfo: String)` | `DevRev.INSTANCE.registerDeviceToken(Context context, String deviceToken, String deviceId)`<br> `DevRev.INSTANCE.processPushNotification(Context context, String userInfo)` |

README.md

Lines changed: 211 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
## Table of contents
2-
- [Table of contents](#table-of-contents)
32
- [Requirements](#requirements)
43
- [Integration](#integration)
5-
- [Step 1: App level dependencies](#step-1)
6-
- [Step 2: Project level dependencies](#step-2)
4+
- [Step 1](#step-1)
5+
- [Step 2](#step-2)
76
- [Setting up the DevRev SDK](#setting-up-the-devrev-sdk)
87
- [Step 1: Credentials](#step-1-credentials)
98
- [Step 2: Configuration](#step-2-configuration)
@@ -12,26 +11,49 @@
1211
- [Anonymous identification](#anonymous-identification)
1312
- [Unverified identification](#unverified-identification)
1413
- [Verified identification](#verified-identification)
14+
- [Examples](#examples)
1515
- [Updating the user](#updating-the-user)
1616
- [Logout](#logout)
17-
- [Examples](#examples)
1817
- [PLuG support chat](#plug-support-chat)
1918
- [Analytics](#analytics)
20-
- [Examples](#examples-1)
19+
- [Examples](#examples-1)
2120
- [Observability](#observability)
2221
- [Opting in/out](#opting-inout)
2322
- [Session recording](#session-recording)
2423
- [Session properties](#session-properties)
24+
- [Masking sensitive data](#masking-sensitive-data)
25+
- [Mask](#mask)
26+
- [Using tag](#using-tag)
27+
- [Example](#example)
28+
- [Using API](#using-api)
29+
- [Examples](#examples-2)
30+
- [Unmask](#unmask)
31+
- [Using tag](#using-tag-1)
32+
- [Example](#example-1)
33+
- [Using API](#using-api-1)
34+
- [Examples](#examples-3)
35+
- [Mask jetpack compose views](#mask-jetpack-compose-views)
36+
- [Example](#example-2)
37+
- [Mask webView elements](#mask-webview-elements)
38+
- [Example](#example-3)
39+
- [Unmask webView elements](#unmask-webview-elements)
40+
- [Example](#example-4)
2541
- [Timers](#timers)
26-
- [Examples](#examples-2)
42+
- [Examples](#examples-4)
2743
- [Screen tracking](#screen-tracking)
28-
- [Examples](#examples-3)
29-
- [Push notifications](#push-notifications)
30-
- [Registering for push notifications](#registering-for-push-notifications)
31-
- [Unregistering from push notifications](#unregistering-from-push-notifications)
32-
- [Handling push notifications](#handling-push-notifications)
33-
- [Examples](#examples-4)
44+
- [Examples](#examples-5)
45+
- [Screen Transition Management](#screen-transition-management)
46+
- [Check if the screen is transitioning](#check-if-the-screen-is-transitioning)
47+
- [Set screen transitioning state](#set-screen-transitioning-state)
48+
- [On-Demand Session Processing](#on-demand-session-processing)
49+
- [Process all on-demand sessions](#process-all-on-demand-sessions)
50+
- [Push notifications](#push-notifications)
51+
- [Registering for push notifications](#registering-for-push-notifications)
52+
- [Unregistering from push notifications](#unregistering-from-push-notifications)
53+
- [Handling push notifications](#handling-push-notifications)
54+
- [Examples](#examples-6)
3455
- [Sample app](#sample-app)
56+
- [Migration Guide](#migration-guide)
3557
- [FAQ](#faq)
3658

3759

@@ -458,6 +480,178 @@ DevRev.clearSessionProperties()
458480
DevRevObservabilityExtKt.clearSessionProperties(DevRev.INSTANCE);
459481
```
460482

483+
### Masking sensitive data
484+
To protect sensitive data, the DevRev SDK provides an auto-masking feature that masks data before sending to the server. Input views such as text fields, text views, and web views are automatically masked.
485+
486+
While the auto-masking feature may be sufficient for most situations, you can manually mark/unmark additional views as sensitive.
487+
488+
#### Mask
489+
490+
##### Using tag
491+
> [!NOTE]
492+
> Use Tag method only when you don't have any other tag already applied to your UI element.
493+
494+
```xml
495+
android:tag="devrev-mask"
496+
```
497+
498+
###### Example
499+
```xml
500+
<WebView
501+
android:id="@+id/webview2"
502+
android:layout_width="fill_parent"
503+
android:layout_height="200dp"
504+
android:background="@android:color/transparent"
505+
android:tag="devrev-mask"/>
506+
```
507+
508+
You can also set the tag programmatically:
509+
- Kotlin
510+
```kotlin
511+
val anyView: View = findViewById(R.id.anyView)
512+
anyView.tag = "devrev-mask"
513+
```
514+
515+
- Java
516+
```java
517+
View anyView = findViewById(R.id.anyView);
518+
anyView.setTag("devrev-mask");
519+
```
520+
521+
##### Using API
522+
- Kotlin
523+
```kotlin
524+
DevRev.markSensitiveViews(sensitiveViews: List<View>)
525+
```
526+
527+
- Java
528+
```java
529+
DevRevObservabilityExtKt.markSensitiveViews(DevRev.INSTANCE, List<View> sensitiveViews);
530+
```
531+
532+
###### Examples
533+
- Kotlin
534+
```kotlin
535+
val view1 = findViewById(R.id.view1)
536+
val view2 = findViewById(R.id.view2)
537+
538+
DevRev.markSensitiveViews(listOf(view1, view2))
539+
```
540+
541+
- Java
542+
```java
543+
View view1 = findViewById(R.id.view1);
544+
View view2 = findViewById(R.id.view2);
545+
546+
List<View> sensitiveViewsList = new ArrayList<>();
547+
sensitiveViewsList.add(view1);
548+
sensitiveViewsList.add(view2);
549+
550+
DevRevObservabilityExtKt.markSensitiveViews(DevRev.INSTANCE, sensitiveViewsList);
551+
```
552+
553+
#### Unmask
554+
555+
##### Using tag
556+
> [!NOTE]
557+
> Use Tag method only when you don't have any other tag already applied to your UI element.
558+
559+
```xml
560+
android:tag="devrev-unmask"
561+
```
562+
563+
###### Example
564+
```xml
565+
<WebView
566+
android:id="@+id/webview2"
567+
android:layout_width="fill_parent"
568+
android:layout_height="200dp"
569+
android:background="@android:color/transparent"
570+
android:tag="devrev-unmask"/>
571+
```
572+
573+
You can also set the tag programmatically:
574+
- Kotlin
575+
```kotlin
576+
val anyView: View = findViewById(R.id.anyView)
577+
anyView.tag = "devrev-unmask"
578+
```
579+
580+
- Java
581+
```java
582+
View anyView = findViewById(R.id.anyView);
583+
anyView.setTag("devrev-unmask");
584+
```
585+
586+
##### Using API
587+
- Kotlin
588+
```kotlin
589+
DevRev.unmarkSensitiveViews(sensitiveViews: List<View>)
590+
```
591+
592+
- Java
593+
```java
594+
DevRevObservabilityExtKt.unmarkSensitiveViews(DevRev.INSTANCE, List<View> sensitiveViews);
595+
```
596+
597+
###### Examples
598+
- Kotlin
599+
```kotlin
600+
val view1 = findViewById(R.id.view1)
601+
val view2 = findViewById(R.id.view2)
602+
603+
DevRev.unmarkSensitiveViews(listOf(view1, view2))
604+
```
605+
606+
- Java
607+
```java
608+
View view1 = findViewById(R.id.view1);
609+
View view2 = findViewById(R.id.view2);
610+
611+
List<View> sensitiveViewsList = new ArrayList<>();
612+
sensitiveViewsList.add(view1);
613+
sensitiveViewsList.add(view2);
614+
615+
DevRevObservabilityExtKt.unmarkSensitiveViews(DevRev.INSTANCE, sensitiveViewsList);
616+
```
617+
618+
#### Mask jetpack compose views
619+
If you want to mask any Jetpack Compose UI element(s) or view(s), you can apply a mask on it using a modifier.
620+
621+
```kotlin
622+
modifier = Modifier.markAsMaskedLocation("Name or ID of the Compose View")
623+
```
624+
625+
###### Example
626+
```kotlin
627+
TextField(
628+
modifier = Modifier
629+
.markAsMaskedLocation("myTextField")
630+
.padding(horizontal = 20.dp)
631+
.onGloballyPositioned { coordinates = it },
632+
value = input,
633+
onValueChange = { input = it }
634+
)
635+
```
636+
637+
#### Mask webView elements
638+
639+
If you wish to mask any WebView element on a Web page explicitly, you can mask it by using class 'devrev-mask'
640+
641+
###### Example
642+
```html
643+
<label class="ue-mask">OTP: 12345</label>
644+
```
645+
646+
#### Unmask webView elements
647+
648+
If you wish to explicitly un-mask any manually masked WebView element, you can un-mask it by using class 'devrev-unmask'
649+
650+
###### Example
651+
```html
652+
<input type="text" placeholder="Enter Username" name="username" required class="devrev-unmask">
653+
```
654+
461655
### Timers
462656
As part of the observability features, the DevRev SDK provides a timer mechanism to help you measure the time spent on a specific task. Events such as response time, loading time, or any other time-based event can be measured using the timer.
463657

@@ -577,8 +771,7 @@ You can configure your app to receive push notifications from the DevRev SDK. Th
577771
The DevRev backend sends push notifications to your app to notify users about new messages in the PLuG support chat. In the future, the push notification support will be expanded with additional features.
578772

579773
> [!CAUTION]
580-
> TBD @Ribhu has to provide the integration guide for push notifications.
581-
In order to receive push notifications, you need to configure your DevRev organization by following the [Push Notifications integration guide](#).
774+
> In order to receive push notifications, you need to configure your DevRev organization by following the [Push Notifications integration guide](#).
582775
583776
You need to make sure that your Android app is configured to receive push notifications. You can follow the [Firebase documentation](https://firebase.google.com/docs/cloud-messaging/android/client) to set up your app to receive push notifications.
584777

@@ -708,6 +901,10 @@ The sample app showcasing both the functionality and the XML implementation has
708901
> [!NOTE]
709902
> The sample is yet to be updated with the latest version of the SDK. Stay Tuned!
710903
904+
# Migration Guide
905+
906+
If you are migrating from the legacy UserExperior SDK to the new DevRev SDK, please refer to the [Migration Guide](./MIGRATION.md) for detailed instructions and feature equivalence.
907+
711908
# FAQ
712909
In case of any issues with the integration of the DevRev SDK, please verify that the dependency is correctly set in the project. In addition, please make sure that `mavenCentral` is reachable from the IDE and that the DevRev PluG SDK version of choice was correctly detected.
713910

build.gradle.kts

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,19 @@
11
buildscript {
22
repositories {
3-
gradlePluginPortal()
43
google()
54
mavenLocal()
65
mavenCentral()
6+
gradlePluginPortal()
77
maven { url = uri("https://jitpack.io") }
88
}
99
dependencies {
10-
classpath("org.jetbrains.kotlin:kotlin-gradle-plugin:1.7.20")
11-
classpath("com.android.tools.build:gradle:7.4.2")
10+
classpath(libs.kotlin.gradle.plugin)
11+
classpath(libs.android.gradlePlugin)
12+
classpath("com.google.gms:google-services:4.3.8")
1213
}
1314
}
15+
16+
plugins {
17+
id("com.google.gms.google-services") version "4.3.8" apply false
18+
}
19+

sample/build.gradle.kts

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
plugins {
22
id("com.android.application")
33
kotlin("android")
4+
alias(libs.plugins.google.gms.google.services)
45
}
56

67
apply(from = "$projectDir/dependencies.gradle.kts")
78
val versions: Map<String, String> by extra
89

910
android {
1011
namespace = "ai.devrev.sdk.sample"
11-
compileSdk = 33
12+
compileSdk = 35
1213

1314
defaultConfig {
1415
applicationId = "ai.devrev.sdk.sample"
@@ -30,7 +31,14 @@ android {
3031
targetCompatibility = JavaVersion.VERSION_11
3132
}
3233
kotlinOptions {
33-
jvmTarget = "1.8"
34+
jvmTarget = "11"
35+
}
36+
buildFeatures {
37+
viewBinding = true
38+
compose = true
39+
}
40+
composeOptions {
41+
kotlinCompilerExtensionVersion = "1.3.2"
3442
}
3543
}
3644

@@ -41,7 +49,26 @@ dependencies {
4149
implementation(versions["com.google.android.material"]!!)
4250
implementation(versions["androidx.constraintlayout"]!!)
4351
implementation(versions["ai.devrev.sdk"]!!)
52+
implementation(libs.android.material)
53+
implementation(libs.androidx.appcompat)
54+
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
55+
implementation(libs.androidx.navigation.fragment.ktx)
56+
implementation(libs.androidx.navigation.ui.ktx)
57+
implementation(libs.androidx.activity)
58+
implementation(libs.activity)
59+
implementation(libs.androidx.material3.android)
4460
testImplementation(versions["junit"]!!)
4561
androidTestImplementation(versions["androidx.test.ext"]!!)
4662
androidTestImplementation(versions["androidx.test.espresso"]!!)
63+
implementation(platform(libs.firebaseBom))
64+
implementation("com.google.firebase:firebase-messaging:23.0.0")
65+
implementation("com.google.firebase:firebase-analytics-ktx:21.0.0")
66+
implementation(libs.compose.ui)
67+
implementation(libs.compose.ui.tooling.preview)
68+
debugImplementation(libs.compose.ui.tooling)
69+
implementation(libs.compose.material)
70+
implementation(libs.androidx.activity.compose)
71+
implementation(libs.androidx.navigation.compose)
72+
implementation(libs.compose.runtime.livedata)
73+
implementation(libs.androidx.lifecycle.viewmodel.compose)
4774
}

sample/dependencies.gradle.kts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
val sdk_version = "1.0.2"
1+
val sdk_version = "1.1.3"
22

33
extra["versions"] = mapOf(
44
"androidx.core" to "androidx.core:core-ktx:1.9.0",

0 commit comments

Comments
 (0)