Add the Flutter SDK to your project

Overview

Add the Flutter SDK and instrument your iOS and Android applications developed with the Flutter framework for logging and analysis.

Before you begin

Set up the appropriate environment. For more information, see Set up an editor.

📘

Note:

The Acoustic Flutter plug-in supports Flutter SDK version 3.3.0 and above. Verify the correct Flutter SDK is installed when setting up your environment.

Create a Flutter project

Create a new Flutter project from your IDE. For example, from Android Studio you can create a project as follows:

  1. Click File > New> New Flutter project and click Next.
  2. Name your project, select the Android and iOS language for your project and the iOS and Android platforms, and click Finish.
  3. Open your newly created project.

Install Acoustic Flutter plug-in

You can install the Tealeaf Flutter plugin from the pub.dev site by completing the following instructions.

  1. In your IDE's terminal, run the following to install the plugin.
flutter pub add tl_flutter_plugin
  1. Import the plugin into your project's main.dart.
import 'package:tl_flutter_plugin/tl_flutter_plugin.dart';

Configure Tealeaf

Update the TealeafConfig.json file with AppKey, PostMessageUrl, and KillSwitchUrl assigned to your organization to configure Tealeaf SDK.

  1. Copy the Tealeaf Automation CLI Folder to your home folder.

    cp -r $HOME/.pub-cache/hosted/pub.dev/tl_flutter_plugin-<TEALEAF-PLUGIN-VERSION>/package/tealeaf_cli $HOME/tealeaf_cli
    
    

    Where is the Tealeaf SDK version. Replace it with the SDK version you have installed. You can find the latest versions at:
    Android
    Acoustic Analytics - Tealeaf
    Acoustic Analytics - EOCore
    IOS
    Acoustic Analytics - TealeafDebug
    Acoustic Analytics - Tealeaf

  2. Open a Terminal in the Tealeaf Automation CLI Folder.

     cd $HOME/tealeaf_cli
    
  3. Run the dart pub get command in the Terminal to retrieve and fetch the dependencies in your project.

     dart pub get
    
  4. Change the directory to your Flutter project folder.

    cd <YOUR_PROJECT_PATH>
    

    Where <YOUR_PROJECT_PATH> is the location of your project directory. Replace it with the directory path to yourproject.

  5. Run the following command to configure the Tealeaf Flutter plugin.

     dart run $HOME/tealeaf_cli/bin/tealeaf_cli.dart <AppKey> <PostMessageURL>
       
    

    Where

    • <AppKey>– is the Tealeaf AppKey. You must replace it with your Tealeaf AppKey.
    • <PostMessageURL> – is the Tealeaf PostMessageURL. Replace it with your Tealeaf URL.
  6. If TealeafConfig.json does not exist in the app's root folder, it will be created. Commit the TealeafConfig.json to source control.

  7. To edit or update the TealeafConfig.json file Tealeaf plugin configuration updates, run the Tealeaf CLI, similar to the previous Step 5.

  8. (Optional) The [sample app] () includes a launch.json task for VS Code IDE that integrates the above steps into an App's pre-build flow.

    1. Create a .vscode folder and add the prelaunch task labeledRun Tealeaf CLI.

              "preLaunchTask": "Run Tealeaf CLI"
      

    2. Copy the tasks.json file to your App's .vscode folder. Update the "args" using the same parameters as in step 2).

Example TealeafConfig.json file

{
    "Tealeaf": {
        "AppKey": "fa47722a7fef4bcd8677fd8d6d113a0d",
        "PostMessageUrl": "https://lib-us-2.brilliantcollector.com/collector/collectorPost",
        "KillSwitchUrl": "https://lib-us-2.brilliantcollector.com/collector/switch/fa47722a7fef4bcd8677fd8d6d113a0d",
        "useRelease": false,
        "iOSVersion":"10.6.279",
        "AndroidEOCoreVersion": "2.0.343",
        "AndroidTealeafVersion": "10.3.359",
        "layoutConfig": {
        "AutoLayout": {
          "GlobalScreenSettings": {
           "ScreenChange": true,
           "DisplayName": "Example",
           "CaptureLayoutDelay": 500,
           "ScreenShot": true,
           "NumberOfWebViews": 0,
           "CaptureUserEvents": true,
           "CaptureScreenVisits": false,
           "CaptureLayoutOn": 2,
           "CaptureScreenshotOn": 2,
           "Masking": {
            "HasMasking": true,
            "HasCustomMask": true,
            "Sensitive": {
              "capitalCaseAlphabet": "X",
              "number": "9",
              "smallCaseAlphabet": "x",
              "symbol": "#"
            },
            "MaskAccessibilityLabelList": [
              "username",
              "Shrine - Tealeaf masking label"
            ]
          }
        }
      },
      "AppendMapIds": {
        "[w,9290],[v,0]": {
          "mid": "ASimpleUIView"
        },
        "tag2999999": {
          "mid": "giveAdditionalId1"
        },
        "idxPathValue": {
          "mid": "giveAdditionalId2"
        }
      }
    }
  }
}

Add Tealeaf Wrapper and Navigation Observer to Flutter App

  1. Tealeaf - Wrapper for the App enables auto instrumentation.
  2. Tealeaf.loggingNavigatorObserver - Handles App's navigation route change event logging.
void main() async {
  ///
  /// Add Tealeaf Wrapper for auto instrumentation
  /// 
  runApp(Tealeaf(
    child: const GalleryApp()));
}

class GalleryApp extends StatelessWidget {
  ...
  @override
  Widget build(BuildContext context) {
    return ModelBinding(
      child: Builder(
        builder: (context) {
          return MaterialApp(
            ///
            /// Add the required Tealeaf loggingNavigatorObserver to the navigatorObservers list
            /// 
            navigatorObservers: [Tealeaf.loggingNavigatorObserver],

            ...
          );
      
      

TabBar, TabBarView and BottomNavigationBar

TabBar and TabBarView: These widgets handle navigation between tabs without pushing or popping routes. They use a TabController to manage the selected tab, and therefore, the Navigator and its observers are not involved in their navigation events.

BottomNavigationBar without Route-based navigation: If a BottomNavigationBar is used without a proper Route-based navigation setup (e.g., by showing and hiding widgets within the same screen), LoggingNavigatorObserver won't be able to log navigation events.

To log navigation events for these types of widgets, you would need to add below code snippets when the user interacts with these widgets (e.g., onTap or onChanged callback functions).:

    PluginTealeaf.logScreenLayout('logicalPageName');

HTTP Connection Logging

HTTP connection logging is the process of recording information about requests made to a server. It helps to monitor and analyze user behavior and gain insights into application performance and issues.

The Tealeaf plugin for Flutter supports HTTP connection logging through a custom HTTP client: TlHttpClient. The TlHttpClient extends FLutter's http.BaseClient and exposes the same interface so it can be used to replace http.BaseClient.

Example usage:

import 'package:tl_flutter_plugin/tl_http_client.dart';

Future<String> fetchData() async {
    var client = TlHttpClient();
    var url = Uri.parse('https://www.google.com/');
    final response =
        await client.get(url);

    if (response.statusCode == 200) {
        // If server returns an OK response
        return  'Success';
    } else {
        // If that response was not OK
        return 'Failed to load page';
    }
}

TextField focus change listener

The TextField focus change listener lets you detect when the user's input focus moves in and out of a Text Field component in your application.

The Tealeaf plugin for Fluter supports TextField focus change listener. To add the listener, complete the following steps:

  1. Set the Key to the widget. It allows you to identify and reference the widget using the key.
    final mywidgetkey = GlobalKey();
    Container(
        key:mywidgetkey
    )
    
    Where,
    myWidgetKey is a GlobalKey assigned to the key property of the Container widget.
  2. Declare the focus node to implement on TextField. The focus node allows you to listen for focus changes and control the focus behavior of the TextField widget.
    FocusNode myfocus = FocusNode();
    
    Where,
    myFocus is the FocusNode class, which will be used to manage the focus state of the TextField.
  3. Implement the FocusNode to TextField or TextFormField:
    TextField(
        focusNode: myfocus,
    )
    
    Where:
    The focusNode property of the TextField widget is set to the previously declared myFocus FocusNode. This setting associates the FocusNode with the TextField, allowing you to listen for focus changes on the TextField using the FocusNode.
  4. Add the focus listener to the Focusnode. It allows you to set up a focus listener to react to focus changes on the TextField associated with the FocusNode.
    myfocus.addListener(() {
        TlTextFieldListener.setupFocusListener(mywidgetkey, myfocus.hasFocus);
      }
    );
    
    Where,
    The addListener method is called on the myFocus FocusNode.
    A callback function is triggered whenever the focus state of the FocusNode myFocus changes.
    TlTextFieldListener.setupFocusListener is called with the key of the widget (myWidgetKey) and the current focus state (myFocus.hasFocus).

Example usage:

import 'package:tl_flutter_plugin/tl_text_field_listener.dart';

final widgetKey = GlobalKey();
    FocusNode widgetFocusNode = FocusNode();

    widgetFocusNode.addListener(() {
      TlTextFieldListener.setupFocusListener(widgetKey, widgetFocusNode.hasFocus);
    });

    Form(
      key: _formKey,
      autovalidateMode: AutovalidateMode.values[_autoValidateModeIndex.value],
      child: Scrollbar(
        child: SingleChildScrollView(
          restorationId: 'text_field_demo_scroll_view',
          padding: const EdgeInsets.symmetric(horizontal: 16),
          child: Column(
            children: [
              sizedBoxSpace,
              TextFormField(
                key: widgetKey,
                restorationId: 'name_field',
                focusNode: widgetFocusNode,
              ),
              sizedBoxSpace,
            ],
          ),
        ),
      ),
    );

Performance logging

Performance logging involves recording and analyzing various performance metrics. The Tealeaf plugin for Flutter facilitates logging the following performance metrics:

  • Navigation Type (navigationType):

    • NAVIGATE = Default 0. Navigation is initiated by a user action like tapping on a button or initializing through a script operation, excluding TYPE_RELOAD and TYPE_BACK_FORWARD.
    • RELOAD = 1: Navigation through the reload operation.
    • BACK_FORWARD = 2: Navigation through a history traversal operation.
    • RESERVED = 255: Any navigation types not defined by the above values.
  • Redirect Count (redirectCount):
    Default 0. The number of redirects since the last non-redirect navigation under the current browsing context. If there is no redirect or any redirect is not from the same origin as the destination screen, this attribute must be zero.

  • Navigation Start Time (navigationStart):
    Default 0. Returns the time immediately after the user finishes prompting to unload the previous screen.

  • Unload Event Start Time (unloadEventStart):
    Default 0. Represents the time immediately before the app starts the unload event of the previous screen, i.e., the pop of the current page.

  • Unload Event End Time (unloadEventEnd):
    Default 0. Indicates the time ending from redirectStart immediately after the user app finishes the unload event of the previous screen.

  • Redirect Start Time (redirectStart):
    Default 0. If there are HTTP redirects or equivalents during navigation and if they all originate at the same place, this attribute returns the starting time of the fetch that initiates the redirect. Otherwise, it returns zero.

  • Redirect End Time (redirectEnd):
    Time ending from redirectStart. If there are HTTP redirects or equivalents during navigation and if they all originate at the same place, this attribute returns the time immediately after receiving the last byte of the response of the last redirect, i.e., use push/pop of the current page. Otherwise, it returns zero.

  • Load Event Start Time (loadEventStart):
    Default 0. Returns the time immediately before the load event of the current screen is fired. It returns zero when the load event is not fired, i.e., initState.

  • Load Event End Time (loadEventEnd):
    End time of loading page. Returns the time when the load event of the current document is completed. It returns zero when the load event is not fired or not completed, i.e., onFocusGained when the page finished rendering or displayed.

Example usage:

import 'package:tl_flutter_plugin/tl_flutter_plugin.dart';

PluginTealeaf.logPerformanceEvent(
            navigationType: 0,
            redirectCount: 0,
            navigationStart: 0,
            unloadEventStart: 10,
            unloadEventEnd: 20,
            redirectStart: 0,
            redirectEnd: 0,
            loadEventStart: 30,
            loadEventEnd: 40);

Replay sessions for your Flutter app

  1. After you set your AppKey and PostMessageUrl, run and build your project.
  2. Find the session ID and copy it from the build console.
  3. Go to your Tealeaf environment > session search screen.
  4. Paste the session ID, and now you will be able to see the session replay.