google-site-verification: google61fe8ba583a51912.html
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