Skip to content

Commit 877f5d4

Browse files
committed
feat(android): Add custom masking options for session replay
1 parent 649b485 commit 877f5d4

File tree

1 file changed

+124
-0
lines changed

1 file changed

+124
-0
lines changed
Lines changed: 124 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,124 @@
1+
---
2+
title: Privacy
3+
sidebar_order: 5501
4+
notSupported:
5+
description: "Learn how to mask parts of your app's data in Session Replay."
6+
---
7+
8+
<Alert>
9+
10+
Before publising an App with Session Replay enabled, make sure to test it thoroughly to ensure that no sensitive data is exposed.
11+
12+
If you choose to use custom masking in your Session Replays, you may accidentally expose sensitive customer data. Be sure to double-check what you choose to expose.
13+
14+
</Alert>
15+
16+
By default, our Session Replay SDK masks all text content, images, webviews and user input. This helps ensure that no sensitive data will be exposed. You can also manually choose which parts of your app's data you want to mask by using the different options listed below.
17+
18+
To disable the default masking behavior (not to be used on applications with sensitive data):
19+
20+
```kotlin
21+
options.experimental.sessionReplay.maskAllText = false
22+
options.experimental.sessionReplay.maskAllImages = false
23+
```
24+
25+
## Mask by View Class
26+
27+
You can choose which type of view you want to mask or unmask by using the `addMaskViewClass` or `addUnmaskViewClass` options.
28+
29+
Let's say you have:
30+
- A custom view that you want to mask
31+
- A `TextView` subclass (which normally would be masked) that you don't want to mask.
32+
33+
You can set the options like this:
34+
35+
```kotlin
36+
options.experimental.sessionReplay.addMaskViewClass("com.example.MyCustomView")
37+
options.experimental.sessionReplay.addUnmaskViewClass("com.example.MyCustomTextView")
38+
```
39+
40+
<Note>
41+
42+
If you're using a code obfuscation tool (R8/ProGuard), adjust your proguard rules accordingly so your custom view class names are not minified.
43+
44+
</Note>
45+
46+
### Class Hierarchy
47+
48+
The masking behavior applies to classes and their subclasses. This means if you add a view via `addMaskViewClass` (for example, `TextView`, which is the default behavior), its respective subclasses (`RadioButton`, `CheckBox`, `EditText`, etc.) will also be masked. For example, you can do the following:
49+
50+
```kotlin
51+
options.experimental.sessionReplay.addMaskViewClass("android.widget.TextView") // mask TextView and all its subclasses
52+
options.experimental.sessionReplay.addUnmaskViewClass("android.widget.RadioButton") // but unmask RadioButton and all its subclasses
53+
```
54+
55+
## Mask by View Instance
56+
57+
You can also choose to mask or unmask a specific view instance by using tags like this:
58+
59+
```xml
60+
<View
61+
android:id="@+id/my_view"
62+
android:layout_width="wrap_content"
63+
android:layout_height="wrap_content"
64+
android:tag="sentry-mask|sentry-unmask"/>
65+
```
66+
67+
```kotlin
68+
view.tag = "sentry-mask|sentry-unmask"
69+
```
70+
71+
If your view already has a tag assigned, you can set the masking tag by a sentry-specific id:
72+
73+
```xml
74+
<View
75+
android:id="@+id/my_view"
76+
android:layout_width="wrap_content"
77+
android:layout_height="wrap_content">
78+
<tag android:id="@id/sentry_privacy" android:value="mask|unmask"/>
79+
</View>
80+
```
81+
82+
```kotlin
83+
view.setTag(io.sentry.android.replay.R.id.sentry_privacy, "mask|unmask")
84+
```
85+
86+
We also provide convenient extension functions for Kotlin:
87+
88+
```kotlin
89+
view.sentryReplayMask()
90+
// or
91+
view.sentryReplayUnmask()
92+
```
93+
94+
## Jetpack Compose
95+
96+
We only support masking specific composables in Jetpack Compose. Since composables don't have a concept of classes (they are all composable functions), masking by view class is not supported.
97+
98+
In this example, we want the "Hello" message to be captured in the replay (by default, all text composables are masked), but not the custom composable:
99+
100+
```kotlin
101+
import io.sentry.android.replay.sentryReplayMask
102+
import io.sentry.android.replay.sentryReplayUnmask
103+
104+
Column(
105+
verticalArrangement = Arrangement.Center,
106+
horizontalAlignment = Alignment.CenterHorizontally,
107+
modifier = Modifier.fillMaxSize()
108+
) {
109+
MyCustomComposable(
110+
modifier = Modifier.sentryReplayMask()
111+
...
112+
)
113+
Text("Hello", modifier = Modifier.sentryReplayUnmask())
114+
}
115+
```
116+
117+
Currently, we don't support masking anything within embedded android views (`AndroidView`), but you can still mask the entire view as follows:
118+
119+
```kotlin
120+
AndroidView(
121+
modifier = Modifier.sentryReplayMask(),
122+
factory = { context -> ... }
123+
)
124+
```

0 commit comments

Comments
 (0)