multidex.dart 3.42 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
// 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 'package:xml/xml.dart';

import '../base/file_system.dart';

// These utility methods are used to generate the code for multidex support as
// well as verifying the project is properly set up.

File _getMultiDexApplicationFile(Directory projectDir) {
  return projectDir.childDirectory('android')
    .childDirectory('app')
    .childDirectory('src')
    .childDirectory('main')
    .childDirectory('java')
    .childDirectory('io')
    .childDirectory('flutter')
    .childDirectory('app')
    .childFile('FlutterMultiDexApplication.java');
}

/// Creates the FlutterMultiDexApplication.java if it does not exist.
void ensureMultiDexApplicationExists(final Directory projectDir) {
  final File applicationFile = _getMultiDexApplicationFile(projectDir);
  if (applicationFile.existsSync()) {
28 29 30 31 32 33
    // This checks for instances of legacy versions of this file. Legacy versions maintained
    // compatibility with v1 embedding by extending FlutterApplication. If we detect this,
    // we replace the file with the modern v2 embedding version.
    if (applicationFile.readAsStringSync().contains('android.app.Application;')) {
      return;
    }
34 35 36 37 38 39
  }
  applicationFile.createSync(recursive: true);

  final StringBuffer buffer = StringBuffer();
  buffer.write('''
// Generated file.
40
//
41
// If you wish to remove Flutter's multidex support, delete this entire file.
42 43 44
//
// Modifications to this file should be done in a copy under a different name
// as this file may be regenerated.
45 46 47

package io.flutter.app;

48
import android.app.Application;
49 50 51 52 53
import android.content.Context;
import androidx.annotation.CallSuper;
import androidx.multidex.MultiDex;

/**
54
 * Extension of {@link android.app.Application}, adding multidex support.
55
 */
56
public class FlutterMultiDexApplication extends Application {
57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95
  @Override
  @CallSuper
  protected void attachBaseContext(Context base) {
    super.attachBaseContext(base);
    MultiDex.install(this);
  }
}
''');
  applicationFile.writeAsStringSync(buffer.toString(), flush: true);
}

/// Returns true if FlutterMultiDexApplication.java exists.
///
/// This function does not verify the contents of the file.
bool multiDexApplicationExists(final Directory projectDir) {
  if (_getMultiDexApplicationFile(projectDir).existsSync()) {
    return true;
  }
  return false;
}

File _getManifestFile(Directory projectDir) {
  return projectDir.childDirectory('android')
    .childDirectory('app')
    .childDirectory('src')
    .childDirectory('main')
    .childFile('AndroidManifest.xml');
}

/// Returns true if the `app` module AndroidManifest.xml includes the
/// <application android:name="${applicationName}"> attribute.
bool androidManifestHasNameVariable(final Directory projectDir) {
  final File manifestFile = _getManifestFile(projectDir);
  if (!manifestFile.existsSync()) {
    return false;
  }
  XmlDocument document;
  try {
    document = XmlDocument.parse(manifestFile.readAsStringSync());
96
  } on XmlException {
97
    return false;
98 99 100 101 102 103 104 105 106 107 108 109
  } on FileSystemException {
    return false;
  }
  // Check for the ${androidName} application attribute.
  for (final XmlElement application in document.findAllElements('application')) {
    final String? applicationName = application.getAttribute('android:name');
    if (applicationName == r'${applicationName}') {
      return true;
    }
  }
  return false;
}