talkback.dart 2.33 KB
// Copyright 2014 The Flutter Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

import 'dart:io' as io;

import 'package:path/path.dart' as path;
import 'package:pub_semver/pub_semver.dart';

String adbPath() {
  final String? androidHome = io.Platform.environment['ANDROID_HOME'] ?? io.Platform.environment['ANDROID_SDK_ROOT'];
  if (androidHome == null) {
    return 'adb';
  } else {
    return path.join(androidHome, 'platform-tools', 'adb');
  }
}

Future<Version> getTalkbackVersion() async {
  final io.ProcessResult result = await io.Process.run(adbPath(), const <String>[
    'shell',
    'dumpsys',
    'package',
    'com.google.android.marvin.talkback',
  ]);
  if (result.exitCode != 0) {
    throw Exception('Failed to get TalkBack version: ${result.stdout as String}\n${result.stderr as String}');
  }
  final List<String> lines = (result.stdout as String).split('\n');
  String? version;
  for (final String line in lines) {
    if (line.contains('versionName')) {
      version = line.replaceAll(RegExp(r'\s*versionName='), '');
      break;
    }
  }
  if (version == null) {
    throw Exception('Unable to determine TalkBack version.');
  }

  // Android doesn't quite use semver, so convert the version string to semver form.
  final RegExp startVersion = RegExp(r'(?<major>\d+)\.(?<minor>\d+)\.(?<patch>\d+)(\.(?<build>\d+))?');
  final RegExpMatch? match = startVersion.firstMatch(version);
  if (match == null) {
    return Version(0, 0, 0);
  }
  return Version(
    int.parse(match.namedGroup('major')!),
    int.parse(match.namedGroup('minor')!),
    int.parse(match.namedGroup('patch')!),
    build: match.namedGroup('build'),
  );
}

Future<void> enableTalkBack() async {
  final io.Process run = await io.Process.start(adbPath(), const <String>[
    'shell',
    'settings',
    'put',
    'secure',
    'enabled_accessibility_services',
    'com.google.android.marvin.talkback/com.google.android.marvin.talkback.TalkBackService',
  ]);
  await run.exitCode;

  print('TalkBack version is ${await getTalkbackVersion()}');
}

Future<void> disableTalkBack() async {
  final io.Process run = await io.Process.start(adbPath(), const <String>[
    'shell',
    'settings',
    'put',
    'secure',
    'enabled_accessibility_services',
    'null',
  ]);
  await run.exitCode;
}