Skip to content

Feat: persistent early crashes #584

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 4 commits into
base: dev
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,8 @@

### Added

- Add support for persistent early crashes detection and reporting. ([#584](https://github.com/Instabug/Instabug-Flutter/pull/584))

- Add support for xCode 16. ([#574](https://github.com/Instabug/Instabug-Flutter/pull/574))

- Add support for BugReporting user consents. ([#573](https://github.com/Instabug/Instabug-Flutter/pull/573))
Expand Down
33 changes: 11 additions & 22 deletions android/src/main/java/com/instabug/flutter/modules/InstabugApi.java
Original file line number Diff line number Diff line change
Expand Up @@ -9,11 +9,12 @@
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.VisibleForTesting;

import com.instabug.bug.BugReporting;
import com.instabug.flutter.generated.InstabugPigeon;
import com.instabug.flutter.util.ArgsRegistry;
import com.instabug.flutter.util.Reflection;
import com.instabug.flutter.util.ThreadManager;
import com.instabug.library.ReproMode;
import com.instabug.library.internal.crossplatform.CoreFeature;
import com.instabug.library.internal.crossplatform.CoreFeaturesState;
import com.instabug.library.internal.crossplatform.FeaturesStateListener;
Expand All @@ -23,7 +24,6 @@
import com.instabug.library.InstabugColorTheme;
import com.instabug.library.InstabugCustomTextPlaceHolder;
import com.instabug.library.IssueType;
import com.instabug.library.Platform;
import com.instabug.library.ReproConfigurations;
import com.instabug.library.featuresflags.model.IBGFeatureFlag;
import com.instabug.library.internal.module.InstabugLocale;
Expand Down Expand Up @@ -68,20 +68,6 @@ public InstabugApi(Context context, Callable<Bitmap> screenshotProvider, Instabu
this.featureFlagsFlutterApi = featureFlagsFlutterApi;
}

@VisibleForTesting
public void setCurrentPlatform() {
try {
Method method = Reflection.getMethod(Class.forName("com.instabug.library.Instabug"), "setCurrentPlatform", int.class);
if (method != null) {
method.invoke(null, Platform.FLUTTER);
} else {
Log.e(TAG, "setCurrentPlatform was not found by reflection");
}
} catch (Exception e) {
e.printStackTrace();
}
}

@Override
public void setEnabled(@NonNull Boolean isEnabled) {
try {
Expand All @@ -106,8 +92,6 @@ public Boolean isEnabled() {

@Override
public void init(@NonNull String token, @NonNull List<String> invocationEvents, @NonNull String debugLogsLevel) {
setCurrentPlatform();

InstabugInvocationEvent[] invocationEventsArray = new InstabugInvocationEvent[invocationEvents.size()];
for (int i = 0; i < invocationEvents.size(); i++) {
String key = invocationEvents.get(i);
Expand All @@ -117,10 +101,15 @@ public void init(@NonNull String token, @NonNull List<String> invocationEvents,
final Application application = (Application) context;
final int parsedLogLevel = ArgsRegistry.sdkLogLevels.get(debugLogsLevel);

new Instabug.Builder(application, token)
.setInvocationEvents(invocationEventsArray)
.setSdkDebugLogsLevel(parsedLogLevel)
.build();
Log.i(TAG, "Instabug is built: " + Instabug.isBuilt());

if (Instabug.isBuilt()) {
Instabug.setSdkDebugLogsLevel(parsedLogLevel);
BugReporting.setInvocationEvents(invocationEventsArray);
} else {
InstabugInitializer.Builder builder = new InstabugInitializer.Builder(application, token, parsedLogLevel, invocationEventsArray);
builder.build();
}

Instabug.setScreenshotProvider(screenshotProvider);
}
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,95 @@
package com.instabug.flutter.modules;

import android.app.Application;
import android.util.Log;

import androidx.annotation.VisibleForTesting;

import com.instabug.flutter.util.Reflection;
import com.instabug.library.Instabug;
import com.instabug.library.Platform;
import com.instabug.library.invocation.InstabugInvocationEvent;

import java.lang.reflect.Method;

public class InstabugInitializer {
private final String TAG = InstabugApi.class.getName();
private static InstabugInitializer instance;

private InstabugInitializer() {}

public static InstabugInitializer getInstance() {
if (instance == null) {
synchronized (InstabugInitializer.class) {
if (instance == null) {
instance = new InstabugInitializer();
}
}
}
return instance;
}

@VisibleForTesting
public void setCurrentPlatform() {
try {
Method method = Reflection.getMethod(Class.forName("com.instabug.library.Instabug"), "setCurrentPlatform", int.class);
if (method != null) {
method.invoke(null, Platform.FLUTTER);
} else {
Log.e(TAG, "setCurrentPlatform was not found by reflection");
}
} catch (Exception e) {
Log.e(TAG, "Error setting current platform", e);
}
}

public static class Builder {
/**
* Application instance to initialize Instabug.
*/
private Application application;

/**
* The application token obtained from the Instabug dashboard.
*/
private String applicationToken;

/**
* The level of detail in logs that you want to print.
*/
private int logLevel;

/**
* The events that trigger the SDK's user interface.
*/
private InstabugInvocationEvent[] invocationEvents;

/**
* Initialize Instabug SDK with application token and invocation trigger events
*
* @param application Application object for initialization of library
* @param applicationToken The app's identifying token, available on your dashboard.
* @param invocationEvents The events that trigger the SDK's user interface.
* <p>Choose from the available events listed in {@link InstabugInvocationEvent}.</p>
*/
public Builder(Application application, String applicationToken, int logLevel, InstabugInvocationEvent... invocationEvents) {
this.application = application;
this.applicationToken = applicationToken;
this.logLevel = logLevel;
this.invocationEvents = invocationEvents;
}

public void build() {
try {
InstabugInitializer.getInstance().setCurrentPlatform();

Instabug.Builder instabugBuilder = new Instabug.Builder(application, applicationToken, invocationEvents)
.setSdkDebugLogsLevel(logLevel);

instabugBuilder.build();
} catch (Exception e) {
Log.e(InstabugInitializer.instance.TAG, "Error building Instabug", e);
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -122,13 +122,6 @@ public void testInit() {
mHostApi.verify(() -> InstabugPigeon.InstabugHostApi.setup(eq(messenger), any(InstabugApi.class)));
}

@Test
public void testSetCurrentPlatform() {
api.setCurrentPlatform();

reflected.verify(() -> MockReflected.setCurrentPlatform(Platform.FLUTTER));
}

@Test
public void testSdkInit() {
String token = "app-token";
Expand All @@ -153,7 +146,7 @@ public void testSdkInit() {
1,
mInstabugBuilder.constructed().size()
);
verify(builder).setInvocationEvents(InstabugInvocationEvent.FLOATING_BUTTON);

verify(builder).setSdkDebugLogsLevel(LogLevel.ERROR);
verify(builder).build();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,47 @@
package com.instabug.flutter;

import static com.instabug.flutter.util.GlobalMocks.reflected;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.mockStatic;
import static org.mockito.Mockito.spy;

import com.instabug.flutter.modules.InstabugInitializer;
import com.instabug.flutter.util.GlobalMocks;
import com.instabug.flutter.util.MockReflected;
import com.instabug.library.Instabug;
import com.instabug.library.Platform;

import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import org.mockito.MockedStatic;

import io.flutter.plugin.common.BinaryMessenger;

public class InstabugInitializerTest {
private InstabugInitializer api;
private MockedStatic<Instabug> mInstabug;

@Before
public void setUp() throws NoSuchMethodException {

BinaryMessenger mMessenger = mock(BinaryMessenger.class);
api = spy(InstabugInitializer.getInstance());
mInstabug = mockStatic(Instabug.class);
GlobalMocks.setUp();
}

@After
public void cleanUp() {
mInstabug.close();
GlobalMocks.close();

}

@Test
public void testSetCurrentPlatform() {
api.setCurrentPlatform();

reflected.verify(() -> MockReflected.setCurrentPlatform(Platform.FLUTTER));
}
}
4 changes: 4 additions & 0 deletions example/android/app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,10 @@
android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
android:hardwareAccelerated="true"
android:windowSoftInputMode="adjustResize">
<meta-data
android:name="com.instabug.library.application_token"
android:value="ed6f659591566da19b67857e1b9d40ab"/>

<!-- Specifies an Android theme to apply to this Activity as soon as
the Android process has started. This theme is visible to the user
while the Flutter UI initializes. After that, this theme continues
Expand Down