• Don Peter

Detecting ANRs and HTTP(s) call failures in Flutter based Android apps.

Updated: Aug 2

Like any software development activity, when developing an app in flutter we encounter issues. But developers thrive because we are open to fixing issues. This mindset distinguishes great developers from the herd.


The question is how do we get to know about issues and collect the data points necessary to reproduce them. This is where bug detection and reporting tools are needed.


This blog is about using Finotes plugin, which is currently in beta, to capture issues from flutter apps in Android platform. The tool is capable of reporting bugs like crashes, guarded exceptions, ANR issues, HTTP(s) failures and custom issues.


Creating an account

First things first, head over to https://finotes.com and create an account. Then log in to the dashboard using the link in your confirmation email.


Next, create an app in the “Add App” section of the dashboard.

Use the add app section in the dashboard to connect the application with dashboard.
Finotes - Connecting App with dashboard

As Finotes flutter plugin supports Android platform, provide the application-id/package name under the relevant section.


Next step is to connect the plugin to the flutter app. Detailed documentation and installation steps are available at the pub.dev website. https://pub.dev/packages/finotescore


Installing the plugin

Integrating the plugin is easy. Just add the following to your pubspec.yaml file.

finotescore: ^version

Or run the following command in your terminal.

$ flutter pub add finotescore

This will install the plugin to your flutter app.


Initializing the plugin

Next, we need to initialize the plugin by calling the following in your main() function after the runApp() function call.



import 'package:finotescore/finotescore.dart';
...

void main() {
    runApp(const MyApp());

    WidgetsFlutterBinding.ensureInitialized(); //Make sure this is called before init() function
    Fn.init();
}

Just by calling the init function, the plugin will start to report crashes and ANRs.


Setting Activity Markers

ActivityTrail is a chronologically ordered list of markers/events that have occurred prior to an issue occurrence. These markers are tagged along with issue reports. This will aid us to approximate the point of origin of the issues.


To allow the plugin to track widget lifecycle events, we need to extend classes from FnState instead of State and call super on overridden build function.


import 'package:finotescore/state_custom.dart';
...

class _MyAppState extends FnState<MyApp> { //Change State to FnState.
    
    @override
    Widget build(BuildContext context) {
        super.build(context); //Call super here.
    }
}


You can also set custom markers at different points in your code using setActivityMarker API. You will be able to pass a key and value as arguments to this API.


Fn.setActivityMarker("Main App", "User tapped on payment button");

As the memory and CPU overheads in setting activity markers are negligible, developers have the freedom to set any number of them. It is recommended to set activity markers using the setActivityMarker API on all major functions in the codebase.


Reporting crashes

When a crash occurs in the app, the plugin will generate the report and send it to the dashboard.


Crash reports will have a detailed textual description along with the issue occurrence time.

Screenshot of Crash report in dashboard
Finotes - Crash report

Data points like device details and the state of the device at the time of occurrence will be provided as well. Crash reports specifically contain the stack trace of the crash which will help us pinpoint the root cause of the crash.

Screenshot of stccktrace in a crash report
Finotes - Stacktrace in crash report

Here the stack trace clearly points to line number 81 of main.dart file Which is the point of origin of the issue. Once the developer reworks this code block, the issue will be fixed.


Capturing ANR

ANRs are detected when the main thread of the application gets stuck for 5000 milliseconds or more. The plugin is capable of reporting blocks in UI thread all the way from 500 milliseconds.

Screenshot of UI block reported in Finotes dashboard
Finotes - ANR report

Along with device and device state parameters, the Activity trail will help developers approximate the point of origin.

Screenshot of activity trail from an issue reported in dashboard.
Finotes - Activity Trail

Here, a closer inspection of the ActivityTrail reveals that the last event "User tapped on compute" got registered at 12:22:51:425 and the issue occurred at 12:22:56:610. This shows the ANR could have triggered when the user was executing this user tap.


This will provide an approximation to the point of origin of the issue.


Tracking HTTP(S) calls

To get reports on status code errors, duplicate HTTP(s) calls being triggered, and delayed network calls, use the custom client provided by the plugin.


Replace the following,

var client = http.Client(); 

with,

import 'package:finotescore/fn_client.dart';
...

var client = FnClient();
Screenshot of API call returning 500 status code error
Finotes - HTTP(s) call failure

It is clear from the issue report, that this GET request had a malformed URL. Here, the system is trying to fetch a resource (user) with user-id specified does not exist which is the reason for 404 status code. Correcting the way user-id is handled while forming the URL should fix the issue.


For HTTP(S) related issues Finotes provides request and response headers, request body and response body, query parameters, response code. Any sensitive header information like keys and tokens can be masked if the developer chooses so.


Currently, the plugin is in beta and supports the Android platform. Tracking and reporting of issues like memory leaks, abnormal memory usage, and frame rate issues will be supported in future versions. Support for iOS platform is also getting ready.


To try out beta version of Finotes Flutter plugin for Android platform, reach out to us using the form here.


Finotes is available with full set of features for Java and Kotlin in Android and for Objective-C and Swift in iOS and watchOS platforms.