Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Submit feedback
Sign in
Toggle navigation
F
Front-End
Project
Project
Details
Activity
Releases
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
abdullh.alsoleman
Front-End
Commits
da90156f
Unverified
Commit
da90156f
authored
Jan 13, 2021
by
Emmanuel Garcia
Committed by
GitHub
Jan 13, 2021
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Fix plugin java class desugar (#73758)
parent
49667ba2
Changes
4
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
117 additions
and
63 deletions
+117
-63
gradle_desugar_classes_test.dart
dev/devicelab/bin/tasks/gradle_desugar_classes_test.dart
+44
-0
apk_utils.dart
dev/devicelab/lib/framework/apk_utils.dart
+32
-18
utils.dart
dev/devicelab/lib/framework/utils.dart
+2
-0
flutter.gradle
packages/flutter_tools/gradle/flutter.gradle
+39
-45
No files found.
dev/devicelab/bin/tasks/gradle_desugar_classes_test.dart
0 → 100644
View file @
da90156f
// 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'
;
import
'package:flutter_devicelab/framework/apk_utils.dart'
;
import
'package:flutter_devicelab/framework/framework.dart'
;
import
'package:flutter_devicelab/framework/task_result.dart'
;
import
'package:flutter_devicelab/framework/utils.dart'
;
Future
<
void
>
main
()
async
{
await
task
(()
async
{
try
{
await
runProjectTest
((
FlutterProject
flutterProject
)
async
{
section
(
'APK contains plugin classes'
);
flutterProject
.
addPlugin
(
'google_maps_flutter'
,
value:
'^1.0.10'
);
await
inDirectory
(
flutterProject
.
rootPath
,
()
async
{
await
flutter
(
'build'
,
options:
<
String
>[
'apk'
,
'--debug'
,
'--target-platform=android-arm'
,
]);
final
File
apk
=
File
(
'
${flutterProject.rootPath}
/build/app/outputs/flutter-apk/app-debug.apk'
);
if
(!
apk
.
existsSync
())
{
throw
TaskResult
.
failure
(
'Expected
${apk.path}
to exist, but it doesn
\'
t'
);
}
// https://github.com/flutter/flutter/issues/72185
await
checkApkContainsMethods
(
apk
,
<
String
>[
'io.flutter.plugins.googlemaps.GoogleMapController void onFlutterViewAttached(android.view.View)'
,
'io.flutter.plugins.googlemaps.GoogleMapController void onFlutterViewDetached()'
,
]);
});
});
return
TaskResult
.
success
(
null
);
}
on
TaskResult
catch
(
taskResult
)
{
return
taskResult
;
}
catch
(
e
)
{
return
TaskResult
.
failure
(
e
.
toString
());
}
});
}
dev/devicelab/lib/framework/apk_utils.dart
View file @
da90156f
...
...
@@ -115,12 +115,14 @@ String get _androidHome {
/// Executes an APK analyzer subcommand.
Future
<
String
>
_evalApkAnalyzer
(
List
<
String
>
args
,
{
bool
printStdout
=
tru
e
,
bool
printStdout
=
fals
e
,
String
workingDirectory
,
})
async
{
final
String
javaHome
=
await
findJavaHome
();
final
String
apkAnalyzer
=
path
if
(
javaHome
==
null
||
javaHome
.
isEmpty
)
{
throw
Exception
(
'No JAVA_HOME set.'
);
}
final
String
apkAnalyzer
=
path
.
join
(
_androidHome
,
'cmdline-tools'
,
'latest'
,
'bin'
,
Platform
.
isWindows
?
'apkanalyzer.bat'
:
'apkanalyzer'
);
if
(
canRun
(
apkAnalyzer
))
{
return
eval
(
...
...
@@ -165,6 +167,7 @@ class ApkExtractor {
bool
_extracted
=
false
;
Set
<
String
>
_classes
=
const
<
String
>{};
Set
<
String
>
_methods
=
const
<
String
>{};
Future
<
void
>
_extractDex
()
async
{
if
(
_extracted
)
{
...
...
@@ -177,22 +180,17 @@ class ApkExtractor {
apkFile
.
path
,
],
);
final
List
<
String
>
lines
=
packages
.
split
(
'
\n
'
);
_classes
=
Set
<
String
>.
from
(
packages
.
split
(
'
\n
'
)
.
where
((
String
line
)
=>
line
.
startsWith
(
'C'
))
.
map
<
String
>((
String
line
)
=>
line
.
split
(
'
\t
'
).
last
),
lines
.
where
((
String
line
)
=>
line
.
startsWith
(
'C'
))
.
map
<
String
>((
String
line
)
=>
line
.
split
(
'
\t
'
).
last
),
);
assert
(
_classes
.
isNotEmpty
);
_extracted
=
true
;
}
// Removes any temporary directory.
void
dispose
()
{
if
(!
_extracted
)
{
return
;
}
_classes
=
const
<
String
>{};
_methods
=
Set
<
String
>.
from
(
lines
.
where
((
String
line
)
=>
line
.
startsWith
(
'M'
))
.
map
<
String
>((
String
line
)
=>
line
.
split
(
'
\t
'
).
last
)
);
assert
(
_methods
.
isNotEmpty
);
_extracted
=
true
;
}
...
...
@@ -201,6 +199,13 @@ class ApkExtractor {
await
_extractDex
();
return
_classes
.
contains
(
className
);
}
/// Returns true if the APK contains a given method.
/// For example: io.flutter.plugins.googlemaps.GoogleMapController void onFlutterViewAttached(android.view.View)
Future
<
bool
>
containsMethod
(
String
methodName
)
async
{
await
_extractDex
();
return
_methods
.
contains
(
methodName
);
}
}
/// Gets the content of the `AndroidManifest.xml`.
...
...
@@ -223,7 +228,16 @@ Future<void> checkApkContainsClasses(File apk, List<String> classes) async {
throw
Exception
(
"APK doesn't contain class `
$className
`."
);
}
}
extractor
.
dispose
();
}
/// Checks that the methods are defined in the APK, throws otherwise.
Future
<
void
>
checkApkContainsMethods
(
File
apk
,
List
<
String
>
methods
)
async
{
final
ApkExtractor
extractor
=
ApkExtractor
(
apk
);
for
(
final
String
method
in
methods
)
{
if
(!(
await
extractor
.
containsMethod
(
method
)))
{
throw
Exception
(
"APK doesn't contain method `
$method
`."
);
}
}
}
class
FlutterProject
{
...
...
@@ -288,7 +302,7 @@ subprojects {
String
content
=
await
pubspec
.
readAsString
();
content
=
content
.
replaceFirst
(
'
${platformLineSep}
dependencies:
$platformLineSep
'
,
'
${platformLineSep}
dependencies:
$platformLineSep
$plugin
:
$value$platformLineSep
'
,
'
${platformLineSep}
dependencies:
$platformLineSep
$plugin
:
$value$platformLineSep
'
,
);
await
pubspec
.
writeAsString
(
content
,
flush:
true
);
}
...
...
dev/devicelab/lib/framework/utils.dart
View file @
da90156f
...
...
@@ -456,6 +456,8 @@ List<String> flutterCommandArgs(String command, List<String> options) {
];
}
/// Runs the flutter `command`, and returns the exit code.
/// If `canFail` is `false`, the future completes with an error.
Future
<
int
>
flutter
(
String
command
,
{
List
<
String
>
options
=
const
<
String
>[],
bool
canFail
=
false
,
// as in, whether failures are ok. False means that they are fatal.
...
...
packages/flutter_tools/gradle/flutter.gradle
View file @
da90156f
...
...
@@ -101,6 +101,19 @@ class FlutterPlugin implements Plugin<Project> {
void
apply
(
Project
project
)
{
this
.
project
=
project
// Configure the Maven repository.
String
hostedRepository
=
System
.
env
.
FLUTTER_STORAGE_BASE_URL
?:
DEFAULT_MAVEN_HOST
String
repository
=
useLocalEngine
()
?
project
.
property
(
'local-engine-repo'
)
:
"$hostedRepository/download.flutter.io"
project
.
rootProject
.
allprojects
{
repositories
{
maven
{
url
repository
}
}
}
project
.
extensions
.
create
(
"flutter"
,
FlutterExtension
)
this
.
addFlutterTasks
(
project
)
...
...
@@ -184,8 +197,7 @@ class FlutterPlugin implements Plugin<Project> {
localEngine
=
engineOut
.
name
localEngineSrcPath
=
engineOut
.
parentFile
.
parent
}
project
.
android
.
buildTypes
.
each
this
.&
addFlutterDependencies
project
.
android
.
buildTypes
.
whenObjectAdded
this
.&
addFlutterDependencies
project
.
android
.
buildTypes
.
all
this
.&
addFlutterDependencies
}
/**
...
...
@@ -199,21 +211,16 @@ class FlutterPlugin implements Plugin<Project> {
if
(!
supportsBuildMode
(
flutterBuildMode
))
{
return
}
String
hostedRepository
=
System
.
env
.
FLUTTER_STORAGE_BASE_URL
?:
DEFAULT_MAVEN_HOST
String
repository
=
useLocalEngine
()
?
project
.
property
(
'local-engine-repo'
)
:
"$hostedRepository/download.flutter.io"
project
.
rootProject
.
allprojects
{
repositories
{
maven
{
url
repository
}
}
// The embedding is set as an API dependency in a Flutter plugin.
// Therefore, don't make the app project depend on the embedding if there are Flutter
// plugins.
// This prevents duplicated classes when using custom build types. That is, a custom build
// type like profile is used, and the plugin and app projects have API dependencies on the
// embedding.
if
(!
isFlutterAppProject
()
||
getPluginList
().
size
()
==
0
)
{
addApiDependencies
(
project
,
buildType
.
name
,
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion"
)
}
// Add the embedding dependency.
addApiDependencies
(
project
,
buildType
.
name
,
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion"
)
List
<
String
>
platforms
=
getTargetPlatforms
().
collect
()
// Debug mode includes x86 and x64, which are commonly used in emulators.
if
(
flutterBuildMode
==
"debug"
&&
!
useLocalEngine
())
{
...
...
@@ -303,7 +310,7 @@ class FlutterPlugin implements Plugin<Project> {
}
// Add plugin dependency to the app project.
project
.
dependencies
{
implementation
pluginProject
api
pluginProject
}
Closure
addEmbeddingDependencyToPlugin
=
{
buildType
->
String
flutterBuildMode
=
buildModeFor
(
buildType
)
...
...
@@ -318,39 +325,23 @@ class FlutterPlugin implements Plugin<Project> {
pluginProject
.
android
.
buildTypes
{
"${buildType.name}"
{}
}
// The embedding is
a compileOnly dependency of a Flutter plugin,
//
however prior to Gradle 6.0.0, it must be an API dependency
.
// The embedding is
API dependency of the plugin, so the AGP is able to desugar
//
default method implementations when the interface is implemented by a plugin
.
//
// Not doing so, causes transitive dependency resolution conflicts.
// That is, the embedding dependencies resolved in the plugin are
// different than the ones resolved in the app.
if
(
isGradleVersionGraterOrEqualThan
(
'6.0.0'
))
{
addCompileOnlyDependency
(
pluginProject
,
buildType
.
name
,
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion"
)
}
else
{
addApiDependencies
(
pluginProject
,
buildType
.
name
,
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion"
)
}
// See https://issuetracker.google.com/139821726, and
// https://github.com/flutter/flutter/issues/72185 for more details.
addApiDependencies
(
pluginProject
,
buildType
.
name
,
"io.flutter:flutter_embedding_$flutterBuildMode:$engineVersion"
)
}
// Wait until the Android plugin loaded.
pluginProject
.
afterEvaluate
{
project
.
android
.
buildTypes
.
each
addEmbeddingDependencyToPlugin
project
.
android
.
buildTypes
.
whenObjectAdded
addEmbeddingDependencyToPlugin
project
.
android
.
buildTypes
.
all
addEmbeddingDependencyToPlugin
}
}
// Returns `true` if the current Gradle version is greater or equal to the given version.
private
isGradleVersionGraterOrEqualThan
(
String
version
)
{
return
VersionNumber
.
parse
(
project
.
gradle
.
gradleVersion
)
.
compareTo
(
VersionNumber
.
parse
(
version
))
>=
0
}
// Returns `true` if the given path contains an `android/build.gradle` file.
//
// TODO(egarciad): Fix https://github.com/flutter/flutter/issues/39657.
...
...
@@ -659,6 +650,10 @@ class FlutterPlugin implements Plugin<Project> {
return
variant
.
hasProperty
(
"assembleProvider"
)
?
variant
.
assembleProvider
.
get
()
:
variant
.
assemble
}
private
boolean
isFlutterAppProject
()
{
return
project
.
android
.
hasProperty
(
"applicationVariants"
)
}
private
void
addFlutterTasks
(
Project
project
)
{
if
(
project
.
state
.
failure
)
{
return
...
...
@@ -816,8 +811,7 @@ class FlutterPlugin implements Plugin<Project> {
}
return
copyFlutterAssetsTask
}
boolean
isFlutterAppProject
=
project
.
android
.
hasProperty
(
"applicationVariants"
)
if
(
isFlutterAppProject
)
{
if
(
isFlutterAppProject
())
{
project
.
android
.
applicationVariants
.
all
{
variant
->
Task
assembleTask
=
getAssembleTask
(
variant
)
if
(!
shouldConfigureFlutterTask
(
assembleTask
))
{
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment