Skip to content

Commit 57b169a

Browse files
Merge pull request #619 from Instabug/feat/screen-render-debugging
Feat/screen render debugging
2 parents 55340b3 + 7244bcc commit 57b169a

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1323
-1211
lines changed

CHANGELOG.md

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,17 @@
11
# Changelog
22

3+
## [Unreleased](https://github.com/Instabug/Instabug-Flutter/compare/v15.0.2...dev)
4+
5+
### Changed
6+
7+
- **BREAKING** Remove deprecated APIs ([#614](https://github.com/Instabug/Instabug-Flutter/pull/614)). See migration guide for more details.
8+
### Added
9+
10+
- Add support for Advanced UI customization with comprehensive theming capabilities. ([#599](https://github.com/Instabug/Instabug-Flutter/pull/599))
11+
12+
- Add screen rendering monitoring functionality within the APM product. ([#605](https://github.com/Instabug/Instabug-Flutter/pull/605))
13+
14+
315
## [15.0.2](https://github.com/Instabug/Instabug-Flutter/compare/v14.3.0...15.0.2) (Jul 7, 2025)
416

517
### Added

android/build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ android {
5252
}
5353

5454
dependencies {
55-
api 'com.instabug.library:instabug:15.0.2.7020723-SNAPSHOT'
55+
api 'com.instabug.library:instabug:15.0.2.7085294-SNAPSHOT'
5656
testImplementation 'junit:junit:4.13.2'
5757
testImplementation "org.mockito:mockito-inline:3.12.1"
5858
testImplementation "io.mockk:mockk:1.13.13"

android/src/main/java/com/instabug/flutter/modules/ApmApi.java

Lines changed: 28 additions & 87 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
import com.instabug.apm.InternalAPM;
1010
import com.instabug.apm.configuration.cp.APMFeature;
1111
import com.instabug.apm.configuration.cp.FeatureAvailabilityCallback;
12-
import com.instabug.apm.model.ExecutionTrace;
12+
import com.instabug.apm.configuration.cp.ToleranceValueCallback;
1313
import com.instabug.apm.networking.APMNetworkLogger;
1414
import com.instabug.apm.networkinterception.cp.APMCPNetworkLog;
1515
import com.instabug.apm.screenrendering.models.cp.IBGFrameData;
@@ -31,11 +31,10 @@
3131

3232
public class ApmApi implements ApmPigeon.ApmHostApi {
3333
private final String TAG = ApmApi.class.getName();
34-
private final HashMap<String, ExecutionTrace> traces = new HashMap<>();
35-
private final Callable<Float> refreshRate;
34+
private final Callable<Float> refreshRateCallback;
3635

3736
public ApmApi(Callable<Float> refreshRate) {
38-
this.refreshRate = refreshRate;
37+
this.refreshRateCallback = refreshRate;
3938
}
4039

4140
public static void init(BinaryMessenger messenger, Callable<Float> refreshRateProvider) {
@@ -94,57 +93,22 @@ public void setAutoUITraceEnabled(@NonNull Boolean isEnabled) {
9493
}
9594
}
9695

97-
/**
98-
* Starts an execution trace and handles the result
99-
* using callbacks.
100-
*
101-
* @param id The `id` parameter is a non-null String that represents the identifier of the execution
102-
* trace.
103-
* @param name The `name` parameter in the `startExecutionTrace` method represents the name of the
104-
* execution trace that will be started. It is used as a reference to identify the trace during
105-
* execution monitoring.
106-
* @param result The `result` parameter in the `startExecutionTrace` method is an instance of
107-
* `ApmPigeon.Result<String>`. This parameter is used to provide the result of the execution trace
108-
* operation back to the caller. The `success` method of the `result` object is called with the
109-
* @deprecated see {@link #startFlow}
110-
*/
111-
@Override
112-
public void startExecutionTrace(@NonNull String id, @NonNull String name, ApmPigeon.Result<String> result) {
113-
ThreadManager.runOnBackground(new Runnable() {
114-
@Override
115-
public void run() {
116-
try {
117-
ExecutionTrace trace = APM.startExecutionTrace(name);
118-
if (trace != null) {
119-
traces.put(id, trace);
120-
121-
ThreadManager.runOnMainThread(new Runnable() {
122-
@Override
123-
public void run() {
124-
result.success(id);
125-
}
126-
});
127-
} else {
128-
ThreadManager.runOnMainThread(new Runnable() {
129-
@Override
130-
public void run() {
131-
result.success(null);
132-
}
133-
});
134-
}
135-
} catch (Exception e) {
136-
e.printStackTrace();
137-
138-
ThreadManager.runOnMainThread(new Runnable() {
139-
@Override
140-
public void run() {
141-
result.success(null);
142-
}
143-
});
144-
}
145-
}
146-
});
147-
}
96+
/**
97+
* Starts an execution trace and handles the result
98+
* using callbacks.
99+
*
100+
* @param id The `id` parameter is a non-null String that represents the identifier of the execution
101+
* trace.
102+
* @param name The `name` parameter in the `startExecutionTrace` method represents the name of the
103+
* execution trace that will be started. It is used as a reference to identify the trace during
104+
* execution monitoring.
105+
* @param result The `result` parameter in the `startExecutionTrace` method is an instance of
106+
* `ApmPigeon.Result<String>`. This parameter is used to provide the result of the execution trace
107+
* operation back to the caller. The `success` method of the `result` object is called with the
108+
*
109+
* @deprecated see {@link #startFlow}
110+
*/
111+
148112

149113
/**
150114
* Starts an AppFlow with the specified name.
@@ -209,37 +173,7 @@ public void endFlow(@NonNull String name) {
209173
}
210174
}
211175

212-
/**
213-
* Adds a new attribute to trace
214-
*
215-
* @param id String id of the trace.
216-
* @param key attribute key
217-
* @param value attribute value. Null to remove attribute
218-
* @deprecated see {@link #setFlowAttribute}
219-
*/
220-
@Override
221-
public void setExecutionTraceAttribute(@NonNull String id, @NonNull String key, @NonNull String value) {
222-
try {
223-
traces.get(id).setAttribute(key, value);
224-
} catch (Exception e) {
225-
e.printStackTrace();
226-
}
227-
}
228176

229-
/**
230-
* Ends a trace
231-
*
232-
* @param id string id of the trace.
233-
* @deprecated see {@link #endFlow}
234-
*/
235-
@Override
236-
public void endExecutionTrace(@NonNull String id) {
237-
try {
238-
traces.get(id).end();
239-
} catch (Exception e) {
240-
e.printStackTrace();
241-
}
242-
}
243177

244178
/**
245179
* Starts a UI trace.
@@ -504,9 +438,16 @@ public void invoke(boolean isEnabled) {
504438
}
505439

506440
@Override
507-
public void deviceRefreshRate(@NonNull ApmPigeon.Result<Double> result) {
441+
public void getDeviceRefreshRateAndTolerance(@NonNull ApmPigeon.Result<List<Double>> result) {
508442
try {
509-
result.success(refreshRate.call().doubleValue());
443+
final double refreshRate = refreshRateCallback.call().doubleValue();
444+
InternalAPM._getToleranceValueForScreenRenderingCP(new ToleranceValueCallback() {
445+
@Override
446+
public void invoke(long tolerance) {
447+
result.success(java.util.Arrays.asList(refreshRate, (double) tolerance));
448+
}
449+
});
450+
510451
} catch (Exception e) {
511452
e.printStackTrace();
512453
}

android/src/main/java/com/instabug/flutter/modules/BugReportingApi.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -184,7 +184,7 @@ public void setCommentMinimumCharacterCount(@NonNull Long limit, @Nullable List<
184184
reportTypesArray[i] = ArgsRegistry.reportTypes.get(key);
185185
}
186186
}
187-
BugReporting.setCommentMinimumCharacterCount(limit.intValue(), reportTypesArray);
187+
BugReporting.setCommentMinimumCharacterCountForBugReportType(limit.intValue(), reportTypesArray);
188188
}
189189

190190
@Override

android/src/main/java/com/instabug/flutter/modules/InstabugApi.java

Lines changed: 154 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
import android.graphics.Bitmap;
66
import android.graphics.BitmapFactory;
77
import android.net.Uri;
8+
import android.graphics.Typeface;
89
import android.util.Log;
910
import androidx.annotation.NonNull;
1011
import androidx.annotation.Nullable;
@@ -176,7 +177,6 @@ public void setWelcomeMessageMode(@NonNull String mode) {
176177

177178
@Override
178179
public void setPrimaryColor(@NonNull Long color) {
179-
Instabug.setPrimaryColor(color.intValue());
180180
}
181181

182182
@Override
@@ -228,20 +228,7 @@ public void run() {
228228
);
229229
}
230230

231-
@Override
232-
public void addExperiments(@NonNull List<String> experiments) {
233-
Instabug.addExperiments(experiments);
234-
}
235-
236-
@Override
237-
public void removeExperiments(@NonNull List<String> experiments) {
238-
Instabug.removeExperiments(experiments);
239-
}
240231

241-
@Override
242-
public void clearAllExperiments() {
243-
Instabug.clearAllExperiments();
244-
}
245232

246233
@Override
247234
public void addFeatureFlags(@NonNull Map<String, String> featureFlags) {
@@ -509,4 +496,157 @@ public void setNetworkLogBodyEnabled(@NonNull Boolean isEnabled) {
509496
e.printStackTrace();
510497
}
511498
}
499+
500+
@Override
501+
public void setTheme(@NonNull Map<String, Object> themeConfig) {
502+
try {
503+
Log.d(TAG, "setTheme called with config: " + themeConfig.toString());
504+
505+
com.instabug.library.model.IBGTheme.Builder builder = new com.instabug.library.model.IBGTheme.Builder();
506+
507+
if (themeConfig.containsKey("primaryColor")) {
508+
builder.setPrimaryColor(getColor(themeConfig, "primaryColor"));
509+
}
510+
if (themeConfig.containsKey("secondaryTextColor")) {
511+
builder.setSecondaryTextColor(getColor(themeConfig, "secondaryTextColor"));
512+
}
513+
if (themeConfig.containsKey("primaryTextColor")) {
514+
builder.setPrimaryTextColor(getColor(themeConfig, "primaryTextColor"));
515+
}
516+
if (themeConfig.containsKey("titleTextColor")) {
517+
builder.setTitleTextColor(getColor(themeConfig, "titleTextColor"));
518+
}
519+
if (themeConfig.containsKey("backgroundColor")) {
520+
builder.setBackgroundColor(getColor(themeConfig, "backgroundColor"));
521+
}
522+
523+
if (themeConfig.containsKey("primaryTextStyle")) {
524+
builder.setPrimaryTextStyle(getTextStyle(themeConfig, "primaryTextStyle"));
525+
}
526+
if (themeConfig.containsKey("secondaryTextStyle")) {
527+
builder.setSecondaryTextStyle(getTextStyle(themeConfig, "secondaryTextStyle"));
528+
}
529+
if (themeConfig.containsKey("ctaTextStyle")) {
530+
builder.setCtaTextStyle(getTextStyle(themeConfig, "ctaTextStyle"));
531+
}
532+
533+
setFontIfPresent(themeConfig, builder, "primaryFontPath", "primaryFontAsset", "primary");
534+
setFontIfPresent(themeConfig, builder, "secondaryFontPath", "secondaryFontAsset", "secondary");
535+
setFontIfPresent(themeConfig, builder, "ctaFontPath", "ctaFontAsset", "CTA");
536+
537+
com.instabug.library.model.IBGTheme theme = builder.build();
538+
Instabug.setTheme(theme);
539+
Log.d(TAG, "Theme applied successfully");
540+
541+
} catch (Exception e) {
542+
Log.e(TAG, "Error in setTheme: " + e.getMessage());
543+
e.printStackTrace();
544+
}
545+
}
546+
547+
548+
549+
/**
550+
* Retrieves a color value from the Map.
551+
*
552+
* @param map The Map object.
553+
* @param key The key to look for.
554+
* @return The parsed color as an integer, or black if missing or invalid.
555+
*/
556+
private int getColor(Map<String, Object> map, String key) {
557+
try {
558+
if (map != null && map.containsKey(key) && map.get(key) != null) {
559+
String colorString = (String) map.get(key);
560+
return android.graphics.Color.parseColor(colorString);
561+
}
562+
} catch (Exception e) {
563+
e.printStackTrace();
564+
}
565+
return android.graphics.Color.BLACK;
566+
}
567+
568+
/**
569+
* Retrieves a text style from the Map.
570+
*
571+
* @param map The Map object.
572+
* @param key The key to look for.
573+
* @return The corresponding Typeface style, or Typeface.NORMAL if missing or invalid.
574+
*/
575+
private int getTextStyle(Map<String, Object> map, String key) {
576+
try {
577+
if (map != null && map.containsKey(key) && map.get(key) != null) {
578+
String style = (String) map.get(key);
579+
switch (style.toLowerCase()) {
580+
case "bold":
581+
return Typeface.BOLD;
582+
case "italic":
583+
return Typeface.ITALIC;
584+
case "bold_italic":
585+
return Typeface.BOLD_ITALIC;
586+
case "normal":
587+
default:
588+
return Typeface.NORMAL;
589+
}
590+
}
591+
} catch (Exception e) {
592+
e.printStackTrace();
593+
}
594+
return Typeface.NORMAL;
595+
}
596+
597+
/**
598+
* Sets a font on the theme builder if the font configuration is present in the theme config.
599+
*
600+
* @param themeConfig The theme configuration map
601+
* @param builder The theme builder
602+
* @param fileKey The key for font file path
603+
* @param assetKey The key for font asset path
604+
* @param fontType The type of font (for logging purposes)
605+
*/
606+
private void setFontIfPresent(Map<String, Object> themeConfig, com.instabug.library.model.IBGTheme.Builder builder,
607+
String fileKey, String assetKey, String fontType) {
608+
if (themeConfig.containsKey(fileKey) || themeConfig.containsKey(assetKey)) {
609+
Typeface typeface = getTypeface(themeConfig, fileKey, assetKey);
610+
if (typeface != null) {
611+
switch (fontType) {
612+
case "primary":
613+
builder.setPrimaryTextFont(typeface);
614+
break;
615+
case "secondary":
616+
builder.setSecondaryTextFont(typeface);
617+
break;
618+
case "CTA":
619+
builder.setCtaTextFont(typeface);
620+
break;
621+
}
622+
}
623+
}
624+
}
625+
626+
private Typeface getTypeface(Map<String, Object> map, String fileKey, String assetKey) {
627+
String fontName = null;
628+
629+
if (assetKey != null && map.containsKey(assetKey) && map.get(assetKey) != null) {
630+
fontName = (String) map.get(assetKey);
631+
} else if (fileKey != null && map.containsKey(fileKey) && map.get(fileKey) != null) {
632+
fontName = (String) map.get(fileKey);
633+
}
634+
635+
if (fontName == null) {
636+
return Typeface.DEFAULT;
637+
}
638+
639+
try {
640+
String assetPath = "fonts/" + fontName;
641+
return Typeface.createFromAsset(context.getAssets(), assetPath);
642+
} catch (Exception e) {
643+
try {
644+
return Typeface.create(fontName, Typeface.NORMAL);
645+
} catch (Exception e2) {
646+
return Typeface.DEFAULT;
647+
}
648+
}
649+
}
650+
651+
512652
}

0 commit comments

Comments
 (0)