android_builder.dart 5.07 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59
// Copyright 2019 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 'package:meta/meta.dart';

import '../base/common.dart';
import '../base/context.dart';
import '../build_info.dart';
import '../project.dart';

import 'android_sdk.dart';
import 'gradle.dart';

/// The builder in the current context.
AndroidBuilder get androidBuilder => context.get<AndroidBuilder>() ?? _AndroidBuilderImpl();

/// Provides the methods to build Android artifacts.
abstract class AndroidBuilder {
  /// Builds an AAR artifact.
  Future<void> buildAar({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
    @required String outputDir,
  });

  /// Builds an APK artifact.
  Future<void> buildApk({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
  });

  /// Builds an App Bundle artifact.
  Future<void> buildAab({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
  });
}

/// Default implementation of [AarBuilder].
class _AndroidBuilderImpl extends AndroidBuilder {
  _AndroidBuilderImpl();

  /// Builds the AAR and POM files for the current Flutter module or plugin.
  @override
  Future<void> buildAar({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
    @required String outputDir,
  }) async {
    if (!project.android.isUsingGradle) {
      throwToolExit(
          'The build process for Android has changed, and the current project configuration '
60 61 62
          'is no longer valid. Please consult\n\n'
          '  https://github.com/flutter/flutter/wiki/Upgrading-Flutter-projects-to-build-with-gradle\n\n'
          'for details on how to upgrade the project.'
63 64 65 66 67 68 69 70 71
      );
    }
    if (!project.manifest.isModule && !project.manifest.isPlugin) {
      throwToolExit('AARs can only be built for plugin or module projects.');
    }
    // Validate that we can find an Android SDK.
    if (androidSdk == null) {
      throwToolExit('No Android SDK found. Try setting the `ANDROID_SDK_ROOT` environment variable.');
    }
72 73 74 75 76 77 78 79 80 81
    try {
      await buildGradleAar(
        project: project,
        androidBuildInfo: androidBuildInfo,
        target: target,
        outputDir: outputDir,
      );
    } finally {
      androidSdk.reinitialize();
    }
82 83 84 85 86 87 88 89 90
  }

  /// Builds the APK.
  @override
  Future<void> buildApk({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
  }) async {
91
    if (!project.android.isUsingGradle) {
92 93
      throwToolExit(
          'The build process for Android has changed, and the current project configuration '
94 95 96
          'is no longer valid. Please consult\n\n'
          '  https://github.com/flutter/flutter/wiki/Upgrading-Flutter-projects-to-build-with-gradle\n\n'
          'for details on how to upgrade the project.'
97 98 99 100 101 102
      );
    }
    // Validate that we can find an android sdk.
    if (androidSdk == null) {
      throwToolExit('No Android SDK found. Try setting the ANDROID_SDK_ROOT environment variable.');
    }
103 104 105 106 107 108 109 110 111 112
    try {
      await buildGradleProject(
        project: project,
        androidBuildInfo: androidBuildInfo,
        target: target,
        isBuildingBundle: false,
      );
    } finally {
      androidSdk.reinitialize();
    }
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133
  }

  /// Builds the App Bundle.
  @override
  Future<void> buildAab({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
  }) async {
    if (!project.android.isUsingGradle) {
      throwToolExit(
          'The build process for Android has changed, and the current project configuration '
          'is no longer valid. Please consult\n\n'
          'https://github.com/flutter/flutter/wiki/Upgrading-Flutter-projects-to-build-with-gradle\n\n'
          'for details on how to upgrade the project.'
      );
    }
    // Validate that we can find an android sdk.
    if (androidSdk == null) {
      throwToolExit('No Android SDK found. Try setting the ANDROID_HOME environment variable.');
    }
134 135 136 137 138 139 140 141 142 143

    try {
      await buildGradleProject(
        project: project,
        androidBuildInfo: androidBuildInfo,
        target: target,
        isBuildingBundle: true,
      );
    } finally {
      androidSdk.reinitialize();
144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172
    }
  }
}

/// A fake implementation of [AndroidBuilder].
@visibleForTesting
class FakeAndroidBuilder implements AndroidBuilder {
  @override
  Future<void> buildAar({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
    @required String outputDir,
  }) async {}

  @override
  Future<void> buildApk({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
  }) async {}

  @override
  Future<void> buildAab({
    @required FlutterProject project,
    @required AndroidBuildInfo androidBuildInfo,
    @required String target,
  }) async {}
}