diff --git a/dev/devicelab/bin/tasks/module_test.dart b/dev/devicelab/bin/tasks/module_test.dart new file mode 100644 index 00000000000..20faa2e22ab --- /dev/null +++ b/dev/devicelab/bin/tasks/module_test.dart @@ -0,0 +1,89 @@ +// Copyright (c) 2018 The Chromium 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:io'; +import 'package:flutter_devicelab/framework/framework.dart'; +import 'package:flutter_devicelab/framework/utils.dart'; +import 'package:path/path.dart' as path; + +/// Tests that the Flutter module project template works and supports +/// adding Flutter to an existing Android app. +Future main() async { + await task(() async { + + section('Create Flutter module project'); + + final Directory directory = await Directory.systemTemp.createTemp('module'); + try { + await inDirectory(directory, () async { + await flutter( + 'create', + options: ['--org', 'io.flutter.devicelab', '-t', 'module', 'hello'], + ); + }); + + section('Build Android .aar'); + + await inDirectory(new Directory(path.join(directory.path, 'hello', '.android')), () async { + await exec('./gradlew', ['flutter:assembleDebug']); + }); + + final bool aarBuilt = exists(new File(path.join( + directory.path, + 'hello', + 'build', + 'android_gen', + 'outputs', + 'aar', + 'flutter-debug.aar', + ))); + + if (!aarBuilt) { + return new TaskResult.failure('Failed to build .aar'); + } + + section('Add to Android app'); + + final Directory hostApp = new Directory(path.join(directory.path, 'hello_host_app')); + mkdir(hostApp); + recursiveCopy( + new Directory(path.join(flutterDirectory.path, 'dev', 'integration_tests', 'android_host_app')), + hostApp, + ); + copy( + new File(path.join(directory.path, 'hello', '.android', 'gradlew')), + hostApp, + ); + copy( + new File(path.join(directory.path, 'hello', '.android', 'gradle', 'wrapper', 'gradle-wrapper.jar')), + new Directory(path.join(hostApp.path, 'gradle', 'wrapper')), + ); + + await inDirectory(hostApp, () async { + await exec('chmod', ['+x', 'gradlew']); + await exec('./gradlew', ['app:assembleDebug']); + }); + + final bool appBuilt = exists(new File(path.join( + hostApp.path, + 'app', + 'build', + 'outputs', + 'apk', + 'debug', + 'app-debug.apk', + ))); + + if (!appBuilt) { + return new TaskResult.failure('Failed to build .apk'); + } + return new TaskResult.success(null); + } catch (e) { + return new TaskResult.failure(e.toString()); + } finally { + rmTree(directory); + } + }); +} diff --git a/dev/devicelab/manifest.yaml b/dev/devicelab/manifest.yaml index 9e9057a8005..17ecdc20226 100644 --- a/dev/devicelab/manifest.yaml +++ b/dev/devicelab/manifest.yaml @@ -261,6 +261,13 @@ tasks: stage: devicelab required_agent_capabilities: ["linux/android"] + module_test: + description: > + Checks that the module project template works and supports add2app on Android. + stage: devicelab + required_agent_capabilities: ["linux/android"] + flaky: true + flutter_gallery_instrumentation_test: description: > Same as flutter_gallery__transition_perf but uses Android instrumentation diff --git a/dev/integration_tests/android_host_app/README.md b/dev/integration_tests/android_host_app/README.md new file mode 100644 index 00000000000..1523329f41a --- /dev/null +++ b/dev/integration_tests/android_host_app/README.md @@ -0,0 +1,8 @@ +# Android host app + +Android host app for a Flutter module created using +``` +$ flutter create -t module hello +``` +and placed in a sibling folder to (a clone of) the host app. +Used by the `module_test.dart` device lab test. diff --git a/dev/integration_tests/android_host_app/app/build.gradle b/dev/integration_tests/android_host_app/app/build.gradle new file mode 100644 index 00000000000..bd3e4ba067c --- /dev/null +++ b/dev/integration_tests/android_host_app/app/build.gradle @@ -0,0 +1,18 @@ +apply plugin: 'com.android.application' + +android { + compileSdkVersion 27 + defaultConfig { + applicationId "io.flutter.add2app" + minSdkVersion 16 + targetSdkVersion 27 + versionCode 1 + versionName "1.0" + testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner" + } +} + +dependencies { + implementation project(':flutter') + implementation 'com.android.support:appcompat-v7:27.1.1' +} diff --git a/dev/integration_tests/android_host_app/app/src/main/AndroidManifest.xml b/dev/integration_tests/android_host_app/app/src/main/AndroidManifest.xml new file mode 100644 index 00000000000..dd1f37f3e26 --- /dev/null +++ b/dev/integration_tests/android_host_app/app/src/main/AndroidManifest.xml @@ -0,0 +1,10 @@ + + + + + + + diff --git a/dev/integration_tests/android_host_app/app/src/main/java/io/flutter/add2app/MainActivity.java b/dev/integration_tests/android_host_app/app/src/main/java/io/flutter/add2app/MainActivity.java new file mode 100644 index 00000000000..1c3ead7a992 --- /dev/null +++ b/dev/integration_tests/android_host_app/app/src/main/java/io/flutter/add2app/MainActivity.java @@ -0,0 +1,14 @@ +package io.flutter.add2app; + +import android.support.v7.app.AppCompatActivity; +import android.os.Bundle; +import io.flutter.facade.Flutter; + +public class MainActivity extends AppCompatActivity { + + @Override + protected void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + setContentView(Flutter.createView(this, getLifecycle(), "route1")); + } +} diff --git a/dev/integration_tests/android_host_app/build.gradle b/dev/integration_tests/android_host_app/build.gradle new file mode 100644 index 00000000000..fb0b97c43b0 --- /dev/null +++ b/dev/integration_tests/android_host_app/build.gradle @@ -0,0 +1,20 @@ +buildscript { + repositories { + google() + jcenter() + } + dependencies { + classpath 'com.android.tools.build:gradle:3.1.3' + } +} + +allprojects { + repositories { + google() + jcenter() + } +} + +task clean(type: Delete) { + delete rootProject.buildDir +} diff --git a/dev/integration_tests/android_host_app/gradle.properties b/dev/integration_tests/android_host_app/gradle.properties new file mode 100644 index 00000000000..6ed0f8f9609 --- /dev/null +++ b/dev/integration_tests/android_host_app/gradle.properties @@ -0,0 +1 @@ +org.gradle.jvmargs=-Xmx1536m diff --git a/dev/integration_tests/android_host_app/gradle/wrapper/gradle-wrapper.properties b/dev/integration_tests/android_host_app/gradle/wrapper/gradle-wrapper.properties new file mode 100644 index 00000000000..49c1f431d2d --- /dev/null +++ b/dev/integration_tests/android_host_app/gradle/wrapper/gradle-wrapper.properties @@ -0,0 +1,6 @@ +#Mon Jun 25 14:13:36 CEST 2018 +distributionBase=GRADLE_USER_HOME +distributionPath=wrapper/dists +zipStoreBase=GRADLE_USER_HOME +zipStorePath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-4.4-all.zip diff --git a/dev/integration_tests/android_host_app/settings.gradle b/dev/integration_tests/android_host_app/settings.gradle new file mode 100644 index 00000000000..ecc9eb957c3 --- /dev/null +++ b/dev/integration_tests/android_host_app/settings.gradle @@ -0,0 +1,3 @@ +include ':app' +setBinding(new Binding([gradle: this])) +evaluate(new File(settingsDir.parentFile, 'hello/.android/include_flutter.groovy'))