// 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:async'; import 'dart:convert'; import 'dart:io' show Directory, File, Process, ProcessSignal; import '../framework/devices.dart'; import '../framework/framework.dart'; import '../framework/task_result.dart'; import '../framework/utils.dart'; const String _messagePrefix = 'entrypoint:'; const String _entrypointName = 'entrypoint'; const String _dartCode = ''' import 'package:flutter/widgets.dart'; @pragma('vm:entry-point') void main() { print('$_messagePrefix main'); runApp(const ColoredBox(color: Color(0xffcc0000))); } @pragma('vm:entry-point') void $_entrypointName() { print('$_messagePrefix $_entrypointName'); runApp(const ColoredBox(color: Color(0xff00cc00))); } '''; const String _kotlinCode = ''' package com.example.entrypoint_dart_registrant import io.flutter.embedding.android.FlutterActivity class MainActivity: FlutterActivity() { override fun getDartEntrypointFunctionName(): String { return "$_entrypointName" } } '''; Future<TaskResult> _runWithTempDir(Directory tempDir) async { const String testDirName = 'entrypoint_dart_registrant'; final String testPath = '${tempDir.path}/$testDirName'; await inDirectory(tempDir, () async { await flutter('create', options: <String>[ '--platforms', 'android', testDirName, ]); }); final String mainPath = '${tempDir.path}/$testDirName/lib/main.dart'; print(mainPath); File(mainPath).writeAsStringSync(_dartCode); final String activityPath = '${tempDir.path}/$testDirName/android/app/src/main/kotlin/com/example/entrypoint_dart_registrant/MainActivity.kt'; File(activityPath).writeAsStringSync(_kotlinCode); final Device device = await devices.workingDevice; await device.unlock(); final String entrypoint = await inDirectory(testPath, () async { // The problem only manifested when the dart plugin registrant was used // (which path_provider has). await flutter('pub', options: <String>['add', 'path_provider:2.0.9']); // The problem only manifested on release builds, so we test release. final Process process = await startFlutter('run', options: <String>['--release']); final Completer<String> completer = Completer<String>(); final StreamSubscription<String> stdoutSub = process.stdout .transform<String>(const Utf8Decoder()) .transform<String>(const LineSplitter()) .listen((String line) async { print(line); if (line.contains(_messagePrefix)) { completer.complete(line); } }); final String entrypoint = await completer.future; await stdoutSub.cancel(); process.stdin.write('q'); await process.stdin.flush(); process.kill(ProcessSignal.sigint); return entrypoint; }); if (entrypoint.contains('$_messagePrefix $_entrypointName')) { return TaskResult.success(null); } else { return TaskResult.failure('expected entrypoint:"$_entrypointName" but found:"$entrypoint"'); } } /// Asserts that the custom entrypoint works in the presence of the dart plugin /// registrant. TaskFunction entrypointDartRegistrant() { return () async { final Directory tempDir = Directory.systemTemp.createTempSync('entrypoint_dart_registrant.'); try { return await _runWithTempDir(tempDir); } finally { rmTree(tempDir); } }; }