A reliable way to get the Dart VM service URL

176 Views Asked by At

I'm building a no-code test automation tool for Flutter and Flutter driver.

For Flutter driver to connect it needs the url of the Dart VM Service.

In Flutter this is reported as follows when running a debug build.

A Dart VM Service on sdk gphone64 arm64 is available at: http://127.0.0.1:56083/oOR_LvT4RT4=/

Over the past 3 years, the way this is reported has changed 4 times if I remember correctly.

I know because when it changes my software breaks .

This questions is to figure out if there's a way that I can query the device dart is running on to get the URL of an active Dart VM service.

I rely on regex now to get the URL out and it's more stable since I don't rely on things like "available at:" , but this is matching other urls that show up in the logs, that actually do match as well.

I would still like a more guaranteed URL retrieval implementation

1

There are 1 best solutions below

3
On

The Dart VM service URL is available via the app.debugPort event

You can get the Dart VM service URL for a running Flutter app reliably by listening to the app.debugPort event.

The app.debugPort event is sent by the flutter daemon server when a VM service port is available for a started app.

The app.debugPort event is also exposed via flutter run --machine so you can start the app with the command and handle the app.debugPort event.

More information:

Sample Message:

Here is a sample message for the app.debugPort event. The Dart VM service URL is contained in the wsUri parameter.

[
  {
    "event": "app.debugPort",
    "params": {
      "appId": "fdcfd2e1-776d-4893-8fbf-c84f399f589d",
      "port": 51591,
      "wsUri": "ws://127.0.0.1:51591/TlaVIlUAMyg=/ws",
      "baseUri": "file:///Users/username/Library/Developer/CoreSimulator/Devices/F04970CF-22B1-46A3-BCA9-BE7E654EDFCD/data/Containers/Data/Application/2A8AA29F-7C61-447B-9D60-98BCC712225D/tmp/demoJhXgVe/demo/"
    }
  }
]

Sample Code:

From your tool, you can get the Dart VM service URL using the code below:

import 'dart:convert';
import 'package:process_run/process_run.dart';

...

const workingDirectory = 'path/to/flutter/project';

final shell = Shell(workingDirectory: workingDirectory);

// Run the Flutter app with the --machine argument
final process = await shell.run('flutter run --machine');

process[0].stdout.transform(utf8.decoder).listen((message) {
  final Object? jsonData;

  try {
    jsonData = jsonDecode(message);
  } on FormatException {
    // The message is not valid JSON.
    return;
  }

  if (jsonData is List && jsonData.length == 1) {
    final payload = jsonData.single;

    if (payload is Map<String, Object?>) {
      final event = payload['event'];

      if (event == 'app.debugPort') {
        final params = payload['params'];

        if (params is Map<String, Object?>) {
          final vmServiceUri = params['wsUri'];

          print('Dart VM service URL is $vmServiceUri');
        }
      }
    }
  }
});

Note: The Shell object is available via the process_run package.

The console will print out this message:

Dart VM service URL is ws://127.0.0.1:51591/TlaVIlUAMyg=/ws