Instabug for Mobile in Java: Complete Implementation Guide

Introduction to Instabug

Instabug is a comprehensive mobile monitoring platform that provides bug reporting, crash reporting, in-app feedback, feature surveys, and performance monitoring for mobile applications. It helps developers quickly identify and resolve issues in their mobile apps.

Key Features

  • Bug Reporting: In-app screenshot and screen recording
  • Crash Reporting: Automatic crash detection with detailed context
  • Performance Monitoring: App launch time, network requests, UI responsiveness
  • Surveys & Feedback: In-app surveys and user feedback collection
  • Session Replay: User session recording for debugging
  • Real User Monitoring: Performance insights from real users

Android Implementation

Dependencies

Add to your app/build.gradle:

android {
compileSdk 33
defaultConfig {
applicationId "com.example.instabugdemo"
minSdk 21
targetSdk 33
versionCode 1
versionName "1.0.0"
}
}
dependencies {
// Instabug Core
implementation 'com.instabug.library:instabug:11.10.0'
// Instabug for APM (Application Performance Monitoring)
implementation 'com.instabug.library:instabug-apm:11.10.0'
// Instabug for Network Monitoring
implementation 'com.instabug.library:instabug-network-logging:11.10.0'
// Optional: Chat support
implementation 'com.instabug.library:instabug-chat:11.10.0'
// Optional: Surveys support
implementation 'com.instabug.library:instabug-surveys:11.10.0'
// AndroidX
implementation 'androidx.appcompat:appcompat:1.6.1'
implementation 'androidx.core:core-ktx:1.12.0'
implementation 'androidx.constraintlayout:constraintlayout:2.1.4'
// Networking (for demo)
implementation 'com.squareup.retrofit2:retrofit:2.9.0'
implementation 'com.squareup.retrofit2:converter-gson:2.9.0'
implementation 'com.squareup.okhttp3:logging-interceptor:4.11.0'
// Image loading (for demo)
implementation 'com.github.bumptech.glide:glide:4.15.1'
}
// Add this to your project-level build.gradle
allprojects {
repositories {
maven {
url "https://sdks.instabug.com/nexus/repository/instabug-cp"
}
}
}

Application Class Setup

package com.example.instabugdemo;
import android.app.Application;
import android.util.Log;
import com.instabug.bug.BugReporting;
import com.instabug.chat.Chats;
import com.instabug.crash.CrashReporting;
import com.instabug.apm.APM;
import com.instabug.library.Instabug;
import com.instabug.library.InstabugColorTheme;
import com.instabug.library.InstabugCustomTextPlaceHolder;
import com.instabug.library.OnSdkDismissedCallback;
import com.instabug.library.invocation.InstabugInvocationEvent;
import com.instabug.library.logging.InstabugLog;
import com.instabug.library.network.InstabugNetworkInterceptor;
import com.instabug.library.ui.onboarding.WelcomeMessage;
import com.instabug.library.InstabugCustomTextPlaceHolder.Key;
public class InstabugApplication extends Application {
private static final String TAG = "InstabugApplication";
private static final String INSTABUG_TOKEN = "YOUR_INSTABUG_TOKEN_HERE";
@Override
public void onCreate() {
super.onCreate();
// Initialize Instabug
initializeInstabug();
// Setup performance monitoring
setupPerformanceMonitoring();
// Setup network monitoring
setupNetworkMonitoring();
}
private void initializeInstabug() {
try {
new Instabug.Builder(this, INSTABUG_TOKEN)
.setInvocationEvents(
InstabugInvocationEvent.SHAKE,
InstabugInvocationEvent.SCREENSHOT,
InstabugInvocationEvent.FLOATING_BUTTON
)
.setTheme(InstabugColorTheme.Light)
.setWelcomeMessageState(WelcomeMessage.State.LIVE)
.setSdkDebugLogsLevel(Log.VERBOSE) // Use Log.ASSERT in production
.build();
// Configure Bug Reporting
BugReporting.setEnabled(true);
BugReporting.setInvocationEvents(
InstabugInvocationEvent.SHAKE,
InstabugInvocationEvent.SCREENSHOT
);
// Configure Crash Reporting
CrashReporting.setEnabled(true);
// Configure Chats
Chats.setState(Chats.State.ENABLED);
// Set custom placeholder texts
setCustomTextPlaceholders();
// Set user data
setUserData();
Log.d(TAG, "Instabug initialized successfully");
} catch (Exception e) {
Log.e(TAG, "Failed to initialize Instabug", e);
}
}
private void setCustomTextPlaceholders() {
InstabugCustomTextPlaceHolder placeHolder = new InstabugCustomTextPlaceHolder();
placeHolder.set(Key.REPORT_FEEDBACK, "Send Feedback");
placeHolder.set(Key.REPORT_BUG, "Report a Bug");
placeHolder.set(Key.REPORT_QUESTION, "Ask a Question");
placeHolder.set(Key.SHAKE_HINT, "Shake to report an issue");
placeHolder.set(Key.INVALID_EMAIL_MESSAGE, "Please enter a valid email");
placeHolder.set(Key.INVALID_COMMENT_MESSAGE, "Please add a description");
placeHolder.set(Key.REPORT_SUCCESSFULLY_SENT, "Thank you for your feedback!");
placeHolder.set(Key.REPORT_REPRODUCTION_STEPS, "What were you doing when the issue occurred?");
Instabug.setCustomTextPlaceHolders(placeHolder);
}
private void setUserData() {
// Set user data for better context in reports
Instabug.identifyUser("john_doe", "[email protected]");
Instabug.setUserAttribute("app_version", BuildConfig.VERSION_NAME);
Instabug.setUserAttribute("device_model", android.os.Build.MODEL);
Instabug.setUserAttribute("android_version", android.os.Build.VERSION.RELEASE);
// Add custom user attributes
Instabug.setUserAttribute("premium_user", "true");
Instabug.setUserAttribute("last_login", String.valueOf(System.currentTimeMillis()));
}
private void setupPerformanceMonitoring() {
// Enable APM (Application Performance Monitoring)
APM.setEnabled(true);
// Set performance monitoring callbacks
APM.setAPMListener(new APM.APMListener() {
@Override
public void onAppLaunchFinished(long duration) {
Log.d(TAG, "App launch duration: " + duration + "ms");
Instabug.setUserAttribute("app_launch_time", String.valueOf(duration));
}
@Override
public void onUIBlocked(long duration) {
Log.w(TAG, "UI blocked for: " + duration + "ms");
// You can set thresholds and take actions
if (duration > 1000) { // 1 second threshold
InstabugLog.w("UI blocked for " + duration + "ms");
}
}
});
// Start app launch tracking
APM.startAppLaunch();
}
private void setupNetworkMonitoring() {
// Network monitoring is automatically enabled
// You can configure it further if needed
}
public static void logDebug(String message) {
InstabugLog.d(message);
}
public static void logError(String message) {
InstabugLog.e(message);
}
public static void logWarning(String message) {
InstabugLog.w(message);
}
public static void logVerbose(String message) {
InstabugLog.v(message);
}
}

Main Activity with Instabug Integration

package com.example.instabugdemo;
import android.os.Bundle;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import com.instabug.bug.BugReporting;
import com.instabug.chat.Chats;
import com.instabug.library.Instabug;
import com.instabug.library.OnSdkDismissedCallback;
import com.instabug.library.invocation.InstabugInvocationEvent;
import com.instabug.survey.Surveys;
import com.instabug.survey.callbacks.OnSurveyShowCallback;
public class MainActivity extends AppCompatActivity {
private static final String TAG = "MainActivity";
private TextView performanceStatus;
private Button crashButton;
private Button networkTestButton;
private Button customSurveyButton;
private Button startSessionReplayButton;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initializeViews();
setupClickListeners();
setupPerformanceMonitoring();
checkForSurveys();
// Log app start
InstabugApplication.logDebug("MainActivity created");
}
private void initializeViews() {
performanceStatus = findViewById(R.id.performance_status);
crashButton = findViewById(R.id.crash_button);
networkTestButton = findViewById(R.id.network_test_button);
customSurveyButton = findViewById(R.id.custom_survey_button);
startSessionReplayButton = findViewById(R.id.start_session_replay_button);
}
private void setupClickListeners() {
crashButton.setOnClickListener(v -> simulateCrashScenario());
networkTestButton.setOnClickListener(v -> performNetworkOperations());
customSurveyButton.setOnClickListener(v -> showCustomSurvey());
startSessionReplayButton.setOnClickListener(v -> startSessionReplay());
// Manual bug report trigger
findViewById(R.id.manual_report_button).setOnClickListener(v -> {
showBugReporting();
});
// Chat trigger
findViewById(R.id.chat_button).setOnClickListener(v -> {
showChat();
});
}
private void setupPerformanceMonitoring() {
// Monitor cold start time
new Handler(Looper.getMainLooper()).postDelayed(() -> {
updatePerformanceStatus("App loaded successfully");
}, 1000);
}
private void updatePerformanceStatus(String status) {
runOnUiThread(() -> {
performanceStatus.setText(status);
performanceStatus.setVisibility(View.VISIBLE);
});
}
private void simulateCrashScenario() {
new Handler(Looper.getMainLooper()).postDelayed(() -> {
try {
// Simulate a potential crash scenario
String[] array = new String[5];
String element = array[10]; // This will cause ArrayIndexOutOfBoundsException
} catch (Exception e) {
// Log the exception to Instabug
InstabugApplication.logError("Simulated crash scenario: " + e.getMessage());
// Report non-fatal exception
Instabug.reportException(e);
updatePerformanceStatus("Crash scenario handled and reported");
}
}, 500);
}
private void performNetworkOperations() {
updatePerformanceStatus("Performing network operations...");
// Simulate network requests that will be monitored by Instabug
new Thread(() -> {
try {
// Simulate API calls
simulateApiCall("/api/users", 1000);
simulateApiCall("/api/products", 500);
simulateApiCall("/api/orders", 1500);
runOnUiThread(() -> 
updatePerformanceStatus("Network operations completed")
);
} catch (Exception e) {
InstabugApplication.logError("Network operation failed: " + e.getMessage());
runOnUiThread(() -> 
updatePerformanceStatus("Network operations failed")
);
}
}).start();
}
private void simulateApiCall(String endpoint, long delay) {
try {
Thread.sleep(delay);
// Log network request (this will be captured by Instabug)
InstabugApplication.logDebug("API call to " + endpoint + " completed in " + delay + "ms");
// Simulate random failures
if (Math.random() < 0.2) { // 20% failure rate for demo
throw new RuntimeException("Simulated API failure for " + endpoint);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
} catch (Exception e) {
Instabug.reportException(e);
}
}
private void showCustomSurvey() {
// Check if there are available surveys
Surveys.showSurveyIfAvailable();
// Alternatively, you can show a specific survey
// Surveys.showSurvey("your_survey_token");
}
private void startSessionReplay() {
// Note: Session replay might require additional setup
updatePerformanceStatus("Session replay started");
// Add custom log for session start
InstabugApplication.logDebug("User started session replay");
}
private void showBugReporting() {
BugReporting.setReportTypes(
BugReporting.ReportType.BUG,
BugReporting.ReportType.FEEDBACK
);
BugReporting.invoke();
}
private void showChat() {
Chats.show();
}
private void checkForSurveys() {
Surveys.setOnShowCallback(new OnSurveyShowCallback() {
@Override
public void onSurveyShow(String surveyId) {
Log.d(TAG, "Survey shown: " + surveyId);
}
});
// Check for available surveys
Surveys.getAvailableSurveys((surveys) -> {
if (surveys != null && !surveys.isEmpty()) {
Log.d(TAG, "Available surveys: " + surveys.size());
// You can show a notification or badge
}
});
}
@Override
protected void onResume() {
super.onResume();
InstabugApplication.logDebug("MainActivity resumed");
// Track screen view
Instabug.trackScreenView("MainActivity");
}
@Override
protected void onPause() {
super.onPause();
InstabugApplication.logDebug("MainActivity paused");
}
}

Network Monitoring with Retrofit

package com.example.instabugdemo.network;
import android.util.Log;
import com.example.instabugdemo.InstabugApplication;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
import okhttp3.logging.HttpLoggingInterceptor;
import retrofit2.Retrofit;
import retrofit2.converter.gson.GsonConverterFactory;
import java.io.IOException;
import java.util.concurrent.TimeUnit;
public class ApiClient {
private static final String TAG = "ApiClient";
private static final String BASE_URL = "https://api.example.com/";
private static Retrofit retrofit = null;
public static Retrofit getClient() {
if (retrofit == null) {
OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
// Add Instabug network interceptor
httpClient.addInterceptor(new InstabugNetworkInterceptor());
// Add logging interceptor
HttpLoggingInterceptor logging = new HttpLoggingInterceptor(message -> 
InstabugApplication.logDebug("HTTP: " + message)
);
logging.setLevel(HttpLoggingInterceptor.Level.BODY);
httpClient.addInterceptor(logging);
// Add custom headers
httpClient.addInterceptor(chain -> {
Request original = chain.request();
Request request = original.newBuilder()
.header("User-Agent", "InstabugDemo/1.0.0")
.header("Accept", "application/json")
.method(original.method(), original.body())
.build();
return chain.proceed(request);
});
// Timeout configurations
httpClient.connectTimeout(30, TimeUnit.SECONDS);
httpClient.readTimeout(30, TimeUnit.SECONDS);
httpClient.writeTimeout(30, TimeUnit.SECONDS);
// Add response monitoring
httpClient.addNetworkInterceptor(chain -> {
long startTime = System.nanoTime();
Request request = chain.request();
Response response = chain.proceed(request);
long endTime = System.nanoTime();
long duration = (endTime - startTime) / 1_000_000; // Convert to milliseconds
// Log network performance
InstabugApplication.logDebug(
String.format("Network: %s %s - %dms - %d bytes",
request.method(),
request.url(),
duration,
response.body().contentLength())
);
return response;
});
retrofit = new Retrofit.Builder()
.baseUrl(BASE_URL)
.client(httpClient.build())
.addConverterFactory(GsonConverterFactory.create())
.build();
}
return retrofit;
}
}
// API Service Interface
package com.example.instabugdemo.network;
import retrofit2.Call;
import retrofit2.http.GET;
import retrofit2.http.Path;
import java.util.List;
public interface ApiService {
@GET("users")
Call<List<User>> getUsers();
@GET("users/{id}")
Call<User> getUser(@Path("id") String userId);
@GET("products")
Call<List<Product>> getProducts();
@GET("orders")
Call<List<Order>> getOrders();
}
// Usage in Activity/Fragment
package com.example.instabugdemo;
import android.os.Bundle;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.example.instabugdemo.network.ApiClient;
import com.example.instabugdemo.network.ApiService;
import retrofit2.Call;
import retrofit2.Callback;
import retrofit2.Response;
import java.util.List;
public class NetworkActivity extends AppCompatActivity {
private ApiService apiService;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_network);
apiService = ApiClient.getClient().create(ApiService.class);
// Make sample API calls
fetchUsers();
fetchProducts();
}
private void fetchUsers() {
InstabugApplication.logDebug("Fetching users...");
Call<List<User>> call = apiService.getUsers();
call.enqueue(new Callback<List<User>>() {
@Override
public void onResponse(Call<List<User>> call, Response<List<User>> response) {
if (response.isSuccessful()) {
List<User> users = response.body();
InstabugApplication.logDebug("Fetched " + users.size() + " users");
Toast.makeText(NetworkActivity.this, 
"Users loaded: " + users.size(), Toast.LENGTH_SHORT).show();
} else {
InstabugApplication.logError("Failed to fetch users: " + response.code());
}
}
@Override
public void onFailure(Call<List<User>> call, Throwable t) {
InstabugApplication.logError("Network error fetching users: " + t.getMessage());
Toast.makeText(NetworkActivity.this, 
"Network error", Toast.LENGTH_SHORT).show();
// Report network failure to Instabug
Instabug.reportException(t);
}
});
}
private void fetchProducts() {
InstabugApplication.logDebug("Fetching products...");
Call<List<Product>> call = apiService.getProducts();
call.enqueue(new Callback<List<Product>>() {
@Override
public void onResponse(Call<List<Product>> call, Response<List<Product>> response) {
if (response.isSuccessful()) {
List<Product> products = response.body();
InstabugApplication.logDebug("Fetched " + products.size() + " products");
} else {
InstabugApplication.logError("Failed to fetch products: " + response.code());
}
}
@Override
public void onFailure(Call<List<Product>> call, Throwable t) {
InstabugApplication.logError("Network error fetching products: " + t.getMessage());
Instabug.reportException(t);
}
});
}
}

Custom Bug Reporting with Additional Context

package com.example.instabugdemo.bugreporting;
import android.content.Context;
import android.util.Log;
import com.instabug.bug.BugReporting;
import com.instabug.library.Instabug;
import com.instabug.library.OnSdkDismissedCallback;
import com.instabug.library.model.Report;
import org.json.JSONObject;
import java.util.HashMap;
import java.util.Map;
public class CustomBugReporter {
private static final String TAG = "CustomBugReporter";
public static void reportBugWithContext(Context context, String title, String description) {
reportBugWithContext(context, title, description, null);
}
public static void reportBugWithContext(Context context, String title, 
String description, Map<String, String> additionalData) {
try {
// Set report type
BugReporting.setReportTypes(BugReporting.ReportType.BUG);
// Add custom fields
if (additionalData != null) {
for (Map.Entry<String, String> entry : additionalData.entrySet()) {
Instabug.setUserAttribute(entry.getKey(), entry.getValue());
}
}
// Set custom invocation event callback
BugReporting.setOnInvokeCallback(() -> {
Log.d(TAG, "Bug reporting invoked");
// You can add pre-reporting logic here
});
BugReporting.setOnDismissCallback(new OnSdkDismissedCallback() {
@Override
public void onSdkDismissed(DismissType dismissType, Report.Type reportType) {
Log.d(TAG, "Bug reporting dismissed: " + dismissType);
switch (dismissType) {
case SUBMIT:
Log.d(TAG, "Bug report submitted");
// Perform any post-submission actions
break;
case CANCEL:
Log.d(TAG, "Bug report cancelled");
break;
case ADD_ATTACHMENT:
Log.d(TAG, "User added attachment");
break;
}
}
});
// Invoke bug reporting with pre-filled description
BugReporting.invoke(title, description);
} catch (Exception e) {
Log.e(TAG, "Error reporting bug", e);
}
}
public static void reportPerformanceIssue(Context context, String issueType, 
long duration, Map<String, Object> metrics) {
Map<String, String> additionalData = new HashMap<>();
additionalData.put("issue_type", issueType);
additionalData.put("duration_ms", String.valueOf(duration));
additionalData.put("timestamp", String.valueOf(System.currentTimeMillis()));
if (metrics != null) {
for (Map.Entry<String, Object> entry : metrics.entrySet()) {
additionalData.put("metric_" + entry.getKey(), 
entry.getValue() != null ? entry.getValue().toString() : "null");
}
}
String description = String.format(
"Performance Issue Detected\nType: %s\nDuration: %dms\nMetrics: %s",
issueType, duration, new JSONObject(metrics).toString()
);
reportBugWithContext(context, "Performance Issue: " + issueType, description, additionalData);
}
public static void reportNetworkIssue(Context context, String url, 
int statusCode, String errorMessage, long responseTime) {
Map<String, String> additionalData = new HashMap<>();
additionalData.put("network_url", url);
additionalData.put("status_code", String.valueOf(statusCode));
additionalData.put("response_time_ms", String.valueOf(responseTime));
additionalData.put("error_message", errorMessage);
String description = String.format(
"Network Issue\nURL: %s\nStatus: %d\nResponse Time: %dms\nError: %s",
url, statusCode, responseTime, errorMessage
);
reportBugWithContext(context, "Network Issue: " + statusCode, description, additionalData);
}
public static void setCustomUserData(String userId, String userRole, String appVersion) {
// Identify user
Instabug.identifyUser(userId, userId + "@example.com");
// Set user attributes
Instabug.setUserAttribute("user_role", userRole);
Instabug.setUserAttribute("app_version", appVersion);
Instabug.setUserAttribute("device_model", android.os.Build.MODEL);
Instabug.setUserAttribute("android_version", android.os.Build.VERSION.RELEASE);
// Add session-specific data
Instabug.setUserAttribute("session_start_time", String.valueOf(System.currentTimeMillis()));
}
}

Performance Monitoring Service

package com.example.instabugdemo.performance;
import android.app.Activity;
import android.os.Handler;
import android.os.Looper;
import android.util.Log;
import com.instabug.apm.APM;
import com.instabug.library.Instabug;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
public class PerformanceMonitor {
private static final String TAG = "PerformanceMonitor";
private static final Map<String, Long> traceStartTimes = new ConcurrentHashMap<>();
private static final Map<String, Map<String, Object>> traceMetadata = new ConcurrentHashMap<>();
private static final Handler mainHandler = new Handler(Looper.getMainLooper());
public static void startTrace(String traceName) {
startTrace(traceName, null);
}
public static void startTrace(String traceName, Map<String, Object> metadata) {
long startTime = System.currentTimeMillis();
traceStartTimes.put(traceName, startTime);
if (metadata != null) {
traceMetadata.put(traceName, metadata);
}
Log.d(TAG, "Started trace: " + traceName);
Instabug.logVerbose("Trace started: " + traceName);
}
public static void endTrace(String traceName) {
endTrace(traceName, null);
}
public static void endTrace(String traceName, Map<String, Object> additionalData) {
Long startTime = traceStartTimes.remove(traceName);
if (startTime == null) {
Log.w(TAG, "Trace not found: " + traceName);
return;
}
long endTime = System.currentTimeMillis();
long duration = endTime - startTime;
Map<String, Object> traceData = new HashMap<>();
traceData.put("duration", duration);
traceData.put("start_time", startTime);
traceData.put("end_time", endTime);
// Add original metadata
Map<String, Object> metadata = traceMetadata.remove(traceName);
if (metadata != null) {
traceData.putAll(metadata);
}
// Add additional data
if (additionalData != null) {
traceData.putAll(additionalData);
}
// Log performance data
Log.d(TAG, String.format("Trace %s completed in %dms", traceName, duration));
Instabug.logDebug(String.format("Performance: %s - %dms", traceName, duration));
// Report slow traces
if (duration > 1000) { // 1 second threshold
Instabug.logWarn(String.format("Slow trace detected: %s - %dms", traceName, duration));
// You can automatically report performance issues
if (duration > 5000) { // 5 seconds threshold
reportPerformanceIssue(traceName, duration, traceData);
}
}
// Update user attribute for monitoring
Instabug.setUserAttribute("last_trace_" + traceName, String.valueOf(duration));
}
private static void reportPerformanceIssue(String traceName, long duration, Map<String, Object> traceData) {
// This would integrate with your bug reporting
Map<String, String> bugData = new HashMap<>();
bugData.put("trace_name", traceName);
bugData.put("duration_ms", String.valueOf(duration));
bugData.put("issue_type", "performance_slow_trace");
// Convert trace data to string for bug report
StringBuilder traceInfo = new StringBuilder();
for (Map.Entry<String, Object> entry : traceData.entrySet()) {
traceInfo.append(entry.getKey()).append(": ").append(entry.getValue()).append("\n");
}
// You can invoke custom bug reporting here
Log.w(TAG, "Performance issue detected for trace: " + traceName);
}
public static void monitorActivityLaunch(Activity activity, String activityName) {
startTrace("activity_launch_" + activityName);
// Monitor when activity becomes fully visible
mainHandler.postDelayed(() -> {
endTrace("activity_launch_" + activityName);
}, 1000); // Adjust based on your needs
}
public static void monitorNetworkRequest(String requestId, String url, String method) {
Map<String, Object> metadata = new HashMap<>();
metadata.put("url", url);
metadata.put("method", method);
metadata.put("request_id", requestId);
startTrace("network_request_" + requestId, metadata);
}
public static void endNetworkRequest(String requestId, int statusCode, long contentLength) {
Map<String, Object> additionalData = new HashMap<>();
additionalData.put("status_code", statusCode);
additionalData.put("content_length", contentLength);
endTrace("network_request_" + requestId, additionalData);
}
public static void monitorDatabaseOperation(String operation, String table) {
Map<String, Object> metadata = new HashMap<>();
metadata.put("operation", operation);
metadata.put("table", table);
startTrace("database_" + operation + "_" + table, metadata);
}
public static void endDatabaseOperation(String operation, String table) {
endTrace("database_" + operation + "_" + table);
}
}

Layout Files

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<ScrollView xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
android:background="#f5f5f5">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<!-- Header -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Instabug Demo"
android:textSize="24sp"
android:textStyle="bold"
android:gravity="center"
android:layout_marginBottom="24dp"
android:textColor="#333333" />
<!-- Performance Status -->
<TextView
android:id="@+id/performance_status"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Performance monitoring active..."
android:textSize="14sp"
android:padding="12dp"
android:background="#e8f5e8"
android:textColor="#2e7d32"
android:visibility="gone"
android:layout_marginBottom="16dp" />
<!-- Crash Simulation -->
<Button
android:id="@+id/crash_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Simulate Crash Scenario"
android:textColor="#ffffff"
android:background="#ff4444"
android:layout_marginBottom="8dp" />
<!-- Network Test -->
<Button
android:id="@+id/network_test_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Test Network Operations"
android:textColor="#ffffff"
android:background="#2196F3"
android:layout_marginBottom="8dp" />
<!-- Manual Bug Report -->
<Button
android:id="@+id/manual_report_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Report Bug Manually"
android:textColor="#ffffff"
android:background="#FF9800"
android:layout_marginBottom="8dp" />
<!-- Chat -->
<Button
android:id="@+id/chat_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Chat"
android:textColor="#ffffff"
android:background="#4CAF50"
android:layout_marginBottom="8dp" />
<!-- Surveys -->
<Button
android:id="@+id/custom_survey_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Show Survey"
android:textColor="#ffffff"
android:background="#9C27B0"
android:layout_marginBottom="8dp" />
<!-- Session Replay -->
<Button
android:id="@+id/start_session_replay_button"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Start Session Replay"
android:textColor="#ffffff"
android:background="#607D8B"
android:layout_marginBottom="16dp" />
<!-- Instructions -->
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="Try these gestures to trigger Instabug:\n• Shake device\n• Take screenshot\n• Tap floating button (if enabled)"
android:textSize="12sp"
android:textColor="#666666"
android:lineSpacingExtra="4dp"
android:padding="8dp" />
</LinearLayout>
</ScrollView>

Advanced Configuration

ProGuard Rules (proguard-rules.pro)

# Instabug ProGuard Rules
-keep class com.instabug.** { *; }
-dontwarn com.instabug.**
# Keep custom application class
-keep public class com.example.instabugdemo.InstabugApplication
# Keep methods used in Instabug callbacks
-keepclassmembers class * {
@com.instabug.library.internal.module.InstabugMethod *;
}
# Keep annotation classes
-keepattributes *Annotation*
# For network logging
-keep class okhttp3.** { *; }
-keep class retrofit2.** { *; }
-dontwarn okhttp3.**
-dontwarn retrofit2.**
-keep class com.google.gson.** { *; }
-keep class com.google.** { *; }

Advanced Instabug Configuration

package com.example.instabugdemo.config;
import android.app.Application;
import com.instabug.bug.BugReporting;
import com.instabug.bug.invocation.Option;
import com.instabug.chat.Chats;
import com.instabug.chat.Replies;
import com.instabug.crash.CrashReporting;
import com.instabug.library.Instabug;
import com.instabug.library.InstabugColorTheme;
import com.instabug.library.invocation.InstabugInvocationEvent;
import com.instabug.library.ui.onboarding.WelcomeMessage;
import com.instabug.survey.Surveys;
public class AdvancedInstabugConfig {
public static void configure(Application application, String token) {
try {
new Instabug.Builder(application, token)
.setInvocationEvents(
InstabugInvocationEvent.SHAKE,
InstabugInvocationEvent.SCREENSHOT,
InstabugInvocationEvent.TWO_FINGER_SWIPE_LEFT
)
.setTheme(InstabugColorTheme.Light)
.setWelcomeMessageState(WelcomeMessage.State.BETA)
.setTrackingUserStepsState(Instabug.TrackingState.ENABLED)
.setConsoleLogState(Instabug.TrackingState.ENABLED)
.setUserResponseEnabled(true)
.setSessionProfilerState(Instabug.TrackingState.ENABLED)
.setViewHierarchyState(Instabug.TrackingState.ENABLED)
.setDebugEnabled(true)
.build();
// Advanced Bug Reporting Configuration
BugReporting.setEnabled(true);
BugReporting.setOptions(Option.COMMENT_FIELD_REQUIRED);
BugReporting.setFloatingButtonEdge(BugReporting.FloatingButtonEdge.LEFT);
BugReporting.setShakingThreshold(2500); // Very sensitive
// Crash Reporting
CrashReporting.setEnabled(true);
// Chats & Replies
Chats.setState(Chats.State.ENABLED_WITH_ATTACHMENTS);
Replies.setState(Replies.State.ENABLED);
// Surveys
Surveys.setEnabled(true);
Surveys.setAppStoreURL("https://play.google.com/store/apps/details?id=com.example.instabugdemo");
// Feature Requests
com.instabug.featuresrequest.FeatureRequests.setEnabled(true);
} catch (Exception e) {
// Handle configuration errors
e.printStackTrace();
}
}
public static void setCustomInvocationEvents() {
// Custom invocation events for specific scenarios
Instabug.setInvocationEvents(
InstabugInvocationEvent.SHAKE,
InstabugInvocationEvent.SCREENSHOT,
InstabugInvocationEvent.FLOATING_BUTTON
);
}
}

Testing and Debugging

Test Activity for Instabug Features

package com.example.instabugdemo;
import android.os.Bundle;
import android.widget.Button;
import android.widget.LinearLayout;
import androidx.appcompat.app.AppCompatActivity;
public class TestActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
LinearLayout layout = new LinearLayout(this);
layout.setOrientation(LinearLayout.VERTICAL);
// Add test buttons for various scenarios
addTestButton(layout, "Test Network Error", this::testNetworkError);
addTestButton(layout, "Test UI Freeze", this::testUIFreeze);
addTestButton(layout, "Test Memory Warning", this::testMemoryWarning);
addTestButton(layout, "Test Custom Logs", this::testCustomLogs);
setContentView(layout);
}
private void addTestButton(LinearLayout layout, String text, Runnable action) {
Button button = new Button(this);
button.setText(text);
button.setOnClickListener(v -> action.run());
layout.addView(button);
}
private void testNetworkError() {
// Simulate network error
new Thread(() -> {
try {
throw new RuntimeException("Simulated network error");
} catch (Exception e) {
Instabug.reportException(e);
}
}).start();
}
private void testUIFreeze() {
// Simulate UI freeze
try {
Thread.sleep(5000); // Freeze UI for 5 seconds
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
private void testMemoryWarning() {
// Simulate memory pressure
byte[] memoryHog = new byte[100 * 1024 * 1024]; // 100MB
InstabugApplication.logWarning("Memory test completed");
}
private void testCustomLogs() {
// Test different log levels
InstabugApplication.logVerbose("Verbose log message");
InstabugApplication.logDebug("Debug log message");
InstabugApplication.logWarning("Warning log message");
InstabugApplication.logError("Error log message");
}
}

Best Practices

1. Environment-specific Configuration

public class InstabugConfigManager {
public static void initialize(Application application, BuildType buildType) {
String token;
boolean debugEnabled;
switch (buildType) {
case DEBUG:
token = "DEBUG_TOKEN";
debugEnabled = true;
break;
case STAGING:
token = "STAGING_TOKEN";
debugEnabled = true;
break;
case RELEASE:
token = "RELEASE_TOKEN";
debugEnabled = false;
break;
default:
token = "DEBUG_TOKEN";
debugEnabled = true;
}
new Instabug.Builder(application, token)
.setDebugEnabled(debugEnabled)
.build();
}
public enum BuildType {
DEBUG, STAGING, RELEASE
}
}

2. User Session Management

public class UserSessionManager {
public static void startUserSession(String userId, String userEmail) {
Instabug.identifyUser(userId, userEmail);
Instabug.setUserAttribute("session_start", String.valueOf(System.currentTimeMillis()));
Instabug.setUserAttribute("device_id", getDeviceId());
}
public static void endUserSession() {
Instabug.logout();
}
public static void updateUserProfile(String name, Map<String, String> customAttributes) {
Instabug.setUserName(name);
for (Map.Entry<String, String> entry : customAttributes.entrySet()) {
Instabug.setUserAttribute(entry.getKey(), entry.getValue());
}
}
private static String getDeviceId() {
// Implementation to get device ID
return android.provider.Settings.Secure.getString(
getContentResolver(),
android.provider.Settings.Secure.ANDROID_ID
);
}
}

Conclusion

This comprehensive Instabug implementation for Android provides:

  • Complete setup and configuration for all Instabug features
  • Performance monitoring with custom traces and metrics
  • Network monitoring with Retrofit integration
  • Custom bug reporting with additional context
  • User session management for better debugging
  • Testing utilities for development and QA

Key benefits include reduced time to detect and resolve issues, improved user experience through performance monitoring, and comprehensive insights into app behavior through session replays and user feedback.

Remember to:

  • Use different tokens for different build types
  • Configure appropriate invocation events for your app
  • Add meaningful user data for better context
  • Monitor performance metrics and set appropriate thresholds
  • Test all Instabug features thoroughly before release
  • Follow privacy guidelines when collecting user data

Leave a Reply

Your email address will not be published. Required fields are marked *


Macro Nepal Helper