Manage sensitive data

As with any third-party service, it’s important for you to understand and have the ability to manage what data is sent to Shake servers. Shake SDK allows you to filter out sensitive data on the mobile device itself, so it never reaches the Shake servers.

Views

You can mark any view as private, and it'll automatically be deleted from the screenshot.

Let's suppose you're building a shopping cart app and you want to delete the name and the credit card number views from the screenshot:

App.kt
import com.shakebugs.shake.Shake
import kotlinx.android.synthetic.main.activity_payment.*
private fun maskSensitiveData() {
Shake.addPrivateView(textName)
Shake.addPrivateView(textCardNumber)
}

To remove a view from the list of private views, use the following method:

App.kt
Shake.removePrivateView(view)

If you want to delete the whole screen from the screenshot, simply mark the whole activity as private:

App.kt
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity
import com.shakebugs.shake.Shake
public class PaymentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_payment)
Shake.addPrivateView(this)
}
...
}

To remove an activity from the list of private views, use the following method:

App.kt
Shake.removePrivateView(activity)

If you want to clear all the private views, use the following method:

App.kt
Shake.clearPrivateViews()

Note that these methods won't delete sensitive views from screen recordings, only screenshots.

You can use Android system flag FLAG_SECURE on activity if you want to prevent sensitive data from being visible in the screen recording feature. FLAG_SECURE will make activity black in screen recordings.

App.kt
import android.os.Bundle
import android.view.WindowManager
import androidx.appcompat.app.AppCompatActivity
public class PaymentActivity : AppCompatActivity() {
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_payment)
window.setFlags(
WindowManager.LayoutParams.FLAG_SECURE,
WindowManager.LayoutParams.FLAG_SECURE)
}
...
}
App.kt
Shake.getReportConfiguration().isAutoVideoRecording = false

Touch events

Marking a view as private will automatically delete its touch events' text properties too. Consequently, you'll see them as data_redacted strings in your Activity history.

Bear in mind that the view's ID, accessiblity labels and tags remain visible.

Network requests

Certain network requests may contain sensitive data which you may not want to send to Shake servers. Use the Shake.setNetworkRequestsFilter() method to obfuscate only the sensitive parts of those requests, or to entirely prevent certain network requests from being logged.

For example, if you'd like to obfuscate the Authorization header in all network requests sent from your app, do this:

App.kt
import com.shakebugs.shake.Shake
private fun setupNetworkFilter() {
Shake.setNetworkRequestsFilter { networkRequest ->
val headers = networkRequest.requestHeaders
if (headers.containsKey("Authorization")) {
headers["Authorization"] = "***"
}
networkRequest
}
}

If you do not want to log specific network requests, return null from the NetworkRequestsFilter like below:

App.kt
import com.shakebugs.shake.Shake
private fun setupNetworkFilter() {
Shake.setNetworkRequestsFilter { networkRequest ->
if (networkRequest.url.startsWith("https://api.myapp.com/cards")) {
null
} else networkRequest
}
}

To clear the network requests filter, use Shake.setNetworkRequestsFilter(null).

Notification events

If your app notifications contain sensitive data, use the Shake.setNotificationEventsFilter() method to obfuscate only the sensitive parts of those notifications, or to entirely prevent certain notifications from being logged.

For example, if you'd like to obfuscate the title of the notification event with id 0, do this:

App.kt
import com.shakebugs.shake.Shake
import com.shakebugs.shake.privacy.NotificationEventEditor
import com.shakebugs.shake.privacy.NotificationEventsFilter
private fun setupNotificationsFilter() {
Shake.setNotificationEventsFilter { notificationEvent ->
if (notificationEvent.id == 0) {
notificationEvent.title = "***"
}
notificationEvent
}
}

If you do not want to track a specific notification event, return null from the NotificationEventsFilter like below:

App.kt
import com.shakebugs.shake.Shake
private fun setupNotificationsFilter() {
Shake.setNotificationEventsFilter { notificationEvent ->
if (notificationEvent.id == 0) {
null
} else notificationEvent
}
}

To clear the notification events filter, use Shake.setNotificationEventsFilter(null).