Privacy

Due to the fact the screen is being recorded at all times, in some cases you might want to protect some sensitive data from showing up in the recording, depending on the nature of the app, in some cases even the beta testers might have something on their screen they don't want the developer to see.

Fortunately, this is an easily solvable problem. We have few options to tackle this problem:

Protected activity

You can protect any activity and prevent it from being recorded by adding it's class to the list of secure activities. Whenever your user navigates to such activity, we substitute the actual screen content with black frames and stop recording touch events.

    Bugsee.addSecureActivity(MySecretActivity.class.getName());

Activities with system flag FLAG_SECURE are protected from video and touches recording without necessity to call any Bugsee methods. This flag can be set to activity the following way.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    getWindow().setFlags(WindowManager.LayoutParams.FLAG_SECURE, WindowManager.LayoutParams.FLAG_SECURE);
    //...
}

Protected view

You can prevent any view from being recorded by adding it to the list of secure views. When such views are visible, we substitute actual view with black rectangle in video frame.

Marking view as protected in xml layout

Protected views can be marked in xml layout by adding "app:bugsee_secure" attribute to the protected view. This attribute can be set to boolean or reference to boolean value. In order to prevent showing Lint warning, related with the attribute, you can add "tools:ignore="MissingPrefix"" line to your protected view declaration. Protected view must have id attribute.

<!-- LinearLayout is used only for example -->
<LinearLayout 
    xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    xmlns:app="http://schemas.android.com/apk/res-auto" <!-- You can use arbitrary name instead of "app" -->
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <View android:id="@+id/my_secret_view1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:bugsee_secure="true" <!-- Boolean value -->
        tools:ignore="MissingPrefix"/>

    <View android:id="@+id/my_secret_view2"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        app:bugsee_secure="@bool/enable_bugsee_hide" <!-- Reference to boolean value -->
        tools:ignore="MissingPrefix"/>
</LinearLayout>

Then it is enough to call one method in code of your activity just after setContentView() method call.

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.your_layout_name);

    Bugsee.addSecureViews(R.layout.your_layout_name, this);
}

Marking view as protected in code

The alternative approach is to mark each protected view in code.

    Bugsee.addSecureView(mySecretView);

    // View is substituted by black rectangle in video.

    Bugsee.removeSecureView(mySecretView);

Protected web page elements

You can also prevent any web page element, shown in WebView, from being recorded by adding class="bugsee-hide" to it.

<input type="text" class="bugsee-hide">

Elements with type="password" are not recorded by default. If you want such web page element to be recorded, add class="bugsee-show" to it.

<input type="password" class="bugsee-show">

Bugsee detects WebViews automatically, but if you use WebView.setWebViewClient() method, it is necessary to call Bugsee.addSecureWebView() method in order to prevent recording protected web page elements in this WebView.

WebView webView;
// Initialize WebView
//...
webView.setWebViewClient(new WebViewClient());
Bugsee.addSecureWebView(webView);

There is one more case, when it is necessary to call Bugsee.addSecureWebView() method - if you add WebView to Activity dynamically and set ViewGroup.OnHierarchyChangeListener to the WebView parent.

public class WebViewActivity extends BaseActivity {
  @Override
    protected void onResume() {
        super.onResume();

        ViewGroup contentContainer = (ViewGroup)findViewById(R.id.content_container); // ViewGroup in Activity layout.
        contentContainer.setOnHierarchyChangeListener(mHierarchyChangeListener);
        WebView webView;
        // Initialize WebView
        //...
        contentContainer.addView(webView);
        Bugsee.addSecureWebView(webView);
    }

    private final ViewGroup.OnHierarchyChangeListener mHierarchyChangeListener = new ViewGroup.OnHierarchyChangeListener() {
        //...
    };
}

Manual Pause & Resume

The following API's will come in handy, no video or touch events are being gathered between the calls to pause() and resume() below:

    // To stop video recording use   
    Bugsee.pause();

    // No touches are recorded, black frame is being recorded instead of actual data in the video.

    // And to continue
    Bugsee.resume();

Network traffic

Bugsee captures network activity from the application and stores headers and in some cases body of the request and response. In order to allow you to hide user identifiable and other sensetive data from these network logs, we provide a way to register a filter and process each event before it is being recorded into Bugsee logs.

The principle is simple, for every event to be recorded, Bugsee will call your method and provide you with BugseeNetworkEvent object. It is your method's responsibility to clean up all user identifiable data from that structure and call listener.onEvent(event) to pass it back to Bugsee. listener.onEvent(event) can be called in other thread than calling thread.

    Bugsee.setNetworkEventFilter(new NetworkEventFilter() {
        @Override
        public void filter(BugseeNetworkEvent event, NetworkEventListener listener) {
            String body = event.getBody();
            if (body != null) {
                // ..make changes
                event.setBody(body);
            }
            String errorDescription = event.getErrorDescription();
            if (errorDescription != null) {
                // ..make changes
                event.setErrorDescription(errorDescription);
            }
            String errorShortMessage = event.getErrorShortMessage();
            if (errorShortMessage != null) {
                // ..make changes
                event.setErrorShortMessage(errorShortMessage);
            }
            Map<String, Object> headers = event.getHeaders();
            if (headers != null) {
                // ..make changes
                event.setHeaders(headers);
            }
            String url = event.getUrl();
            if (url != null) {
                // ..make changes
                event.setUrl(url);
            }

            // Send the saninitized event back to Bugsee to record
            // Skip this in order to completely omit the event from Bugsee recording!
            listener.onEvent(event);
        }
    });