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
9cb9bfbd
Unverified
Commit
9cb9bfbd
authored
Apr 13, 2020
by
Jonah Williams
Committed by
GitHub
Apr 13, 2020
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
[flutter_tools] use new output location for the apk (#54328)
parent
650592b3
Changes
2
Hide whitespace changes
Inline
Side-by-side
Showing
2 changed files
with
82 additions
and
122 deletions
+82
-122
gradle.dart
packages/flutter_tools/lib/src/android/gradle.dart
+55
-15
gradle_test.dart
...flutter_tools/test/general.shard/android/gradle_test.dart
+27
-107
No files found.
packages/flutter_tools/lib/src/android/gradle.dart
View file @
9cb9bfbd
...
...
@@ -39,7 +39,7 @@ Directory getApkDirectory(FlutterProject project) {
:
project
.
android
.
buildDirectory
.
childDirectory
(
'app'
)
.
childDirectory
(
'outputs'
)
.
childDirectory
(
'apk'
);
.
childDirectory
(
'
flutter-
apk'
);
}
/// The directory where the app bundle artifact is generated.
...
...
@@ -469,25 +469,33 @@ Future<void> buildGradleApp({
return
;
}
// Gradle produced an APK.
final
Iterable
<
File
>
apkFiles
=
findApkFiles
(
project
,
androidBuildInfo
);
final
Iterable
<
String
>
apkFilesPaths
=
project
.
isModule
?
findApkFilesModule
(
project
,
androidBuildInfo
)
:
listApkPaths
(
androidBuildInfo
);
final
Directory
apkDirectory
=
getApkDirectory
(
project
);
final
File
apkFile
=
apkDirectory
.
childFile
(
apkFilesPaths
.
first
);
if
(!
apkFile
.
existsSync
())
{
_exitWithExpectedFileNotFound
(
project:
project
,
fileExtension:
'.apk'
,
);
}
// Copy the first APK to app.apk, so `flutter run` can find it.
// TODO(egarciad): Handle multiple APKs.
apkFile
s
.
first
.
copySync
(
apkDirectory
.
childFile
(
'app.apk'
).
path
);
apkFile
.
copySync
(
apkDirectory
.
childFile
(
'app.apk'
).
path
);
globals
.
printTrace
(
'calculateSha:
$apkDirectory
/app.apk'
);
final
File
apkShaFile
=
apkDirectory
.
childFile
(
'app.apk.sha1'
);
apkShaFile
.
writeAsStringSync
(
_calculateSha
(
apkFile
s
.
first
));
apkShaFile
.
writeAsStringSync
(
_calculateSha
(
apkFile
));
for
(
final
File
apkFile
in
apkFiles
)
{
final
String
appSize
=
(
buildInfo
.
mode
==
BuildMode
.
debug
)
?
''
// Don't display the size when building a debug variant.
:
' (
${getSizeAsMB(apkFile.lengthSync())}
)'
;
globals
.
printStatus
(
'
$successMark
Built
${globals.fs.path.relative(apkFile.path)}$appSize
.'
,
color:
TerminalColor
.
green
,
);
}
final
String
appSize
=
(
buildInfo
.
mode
==
BuildMode
.
debug
)
?
''
// Don't display the size when building a debug variant.
:
' (
${getSizeAsMB(apkFile.lengthSync())}
)'
;
globals
.
printStatus
(
'
$successMark
Built
${globals.fs.path.relative(apkFile.path)}$appSize
.'
,
color:
TerminalColor
.
green
,
);
}
/// Builds AAR and POM files.
...
...
@@ -778,7 +786,7 @@ Future<void> buildPluginsAsAar(
/// Returns the APK files for a given [FlutterProject] and [AndroidBuildInfo].
@visibleForTesting
Iterable
<
File
>
findApkFiles
(
Iterable
<
String
>
findApkFilesModule
(
FlutterProject
project
,
AndroidBuildInfo
androidBuildInfo
,
)
{
...
...
@@ -815,7 +823,39 @@ Iterable<File> findApkFiles(
fileExtension:
'.apk'
,
);
}
return
apks
;
return
apks
.
map
((
File
file
)
=>
file
.
path
);
}
/// Returns the APK files for a given [FlutterProject] and [AndroidBuildInfo].
///
/// The flutter.gradle plugin will copy APK outputs into:
/// $buildDir/app/outputs/flutter-apk/app-<abi>-<flavor-flag>-<build-mode-flag>.apk
@visibleForTesting
Iterable
<
String
>
listApkPaths
(
AndroidBuildInfo
androidBuildInfo
,
)
{
final
String
buildType
=
camelCase
(
androidBuildInfo
.
buildInfo
.
modeName
);
final
List
<
String
>
apkPartialName
=
<
String
>[
if
(
androidBuildInfo
.
buildInfo
.
flavor
?.
isNotEmpty
??
false
)
androidBuildInfo
.
buildInfo
.
flavor
,
'
$buildType
.apk'
,
];
if
(
androidBuildInfo
.
splitPerAbi
)
{
return
<
String
>[
for
(
AndroidArch
androidArch
in
androidBuildInfo
.
targetArchs
)
<
String
>[
'app'
,
getNameForAndroidArch
(
androidArch
),
...
apkPartialName
].
join
(
'-'
)
];
}
return
<
String
>[
<
String
>[
'app'
,
...
apkPartialName
,
].
join
(
'-'
)
];
}
@visibleForTesting
...
...
packages/flutter_tools/test/general.shard/android/gradle_test.dart
View file @
9cb9bfbd
...
...
@@ -44,7 +44,7 @@ void main() {
expect
(
getApkDirectory
(
project
).
path
,
equals
(
globals
.
fs
.
path
.
join
(
'foo'
,
'app'
,
'outputs'
,
'apk'
)),
equals
(
globals
.
fs
.
path
.
join
(
'foo'
,
'app'
,
'outputs'
,
'
flutter-
apk'
)),
);
});
...
...
@@ -312,107 +312,41 @@ void main() {
});
});
group
(
'findApkFiles'
,
()
{
final
Usage
mockUsage
=
MockUsage
();
testUsingContext
(
'Finds APK without flavor in release'
,
()
{
final
FlutterProject
project
=
MockFlutterProject
();
final
AndroidProject
androidProject
=
MockAndroidProject
();
when
(
project
.
android
).
thenReturn
(
androidProject
);
when
(
project
.
isModule
).
thenReturn
(
false
);
when
(
androidProject
.
buildDirectory
).
thenReturn
(
globals
.
fs
.
directory
(
'irrelevant'
));
final
Directory
apkDirectory
=
globals
.
fs
.
directory
(
globals
.
fs
.
path
.
join
(
'irrelevant'
,
'app'
,
'outputs'
,
'apk'
,
'release'
));
apkDirectory
.
createSync
(
recursive:
true
);
apkDirectory
.
childFile
(
'app-release.apk'
).
createSync
();
final
Iterable
<
File
>
apks
=
findApkFiles
(
project
,
group
(
'listApkPaths'
,
()
{
testWithoutContext
(
'Finds APK without flavor in release'
,
()
{
final
Iterable
<
String
>
apks
=
listApkPaths
(
const
AndroidBuildInfo
(
BuildInfo
(
BuildMode
.
release
,
''
,
treeShakeIcons:
false
)),
);
expect
(
apks
.
isNotEmpty
,
isTrue
);
expect
(
apks
.
first
.
path
,
equals
(
globals
.
fs
.
path
.
join
(
'irrelevant'
,
'app'
,
'outputs'
,
'apk'
,
'release'
,
'app-release.apk'
)));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
});
testUsingContext
(
'Finds APK with flavor in release mode'
,
()
{
final
FlutterProject
project
=
MockFlutterProject
();
final
AndroidProject
androidProject
=
MockAndroidProject
();
when
(
project
.
android
).
thenReturn
(
androidProject
);
when
(
project
.
isModule
).
thenReturn
(
false
);
when
(
androidProject
.
buildDirectory
).
thenReturn
(
globals
.
fs
.
directory
(
'irrelevant'
));
final
Directory
apkDirectory
=
globals
.
fs
.
directory
(
globals
.
fs
.
path
.
join
(
'irrelevant'
,
'app'
,
'outputs'
,
'apk'
,
'release'
));
apkDirectory
.
createSync
(
recursive:
true
);
apkDirectory
.
childFile
(
'app-flavor1-release.apk'
).
createSync
();
expect
(
apks
,
<
String
>[
'app-release.apk'
]);
});
final
Iterable
<
File
>
apks
=
findApkFiles
(
project
,
testWithoutContext
(
'Finds APK with flavor in release mode'
,
()
{
final
Iterable
<
String
>
apks
=
listApkPaths
(
const
AndroidBuildInfo
(
BuildInfo
(
BuildMode
.
release
,
'flavor1'
,
treeShakeIcons:
false
)),
);
expect
(
apks
.
isNotEmpty
,
isTrue
);
expect
(
apks
.
first
.
path
,
equals
(
globals
.
fs
.
path
.
join
(
'irrelevant'
,
'app'
,
'outputs'
,
'apk'
,
'release'
,
'app-flavor1-release.apk'
)));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
});
testUsingContext
(
'Finds APK with flavor in release mode - AGP v3'
,
()
{
final
FlutterProject
project
=
MockFlutterProject
();
final
AndroidProject
androidProject
=
MockAndroidProject
();
when
(
project
.
android
).
thenReturn
(
androidProject
);
when
(
project
.
isModule
).
thenReturn
(
false
);
when
(
androidProject
.
buildDirectory
).
thenReturn
(
globals
.
fs
.
directory
(
'irrelevant'
));
final
Directory
apkDirectory
=
globals
.
fs
.
directory
(
globals
.
fs
.
path
.
join
(
'irrelevant'
,
'app'
,
'outputs'
,
'apk'
,
'flavor1'
,
'release'
));
apkDirectory
.
createSync
(
recursive:
true
);
apkDirectory
.
childFile
(
'app-flavor1-release.apk'
).
createSync
();
expect
(
apks
,
<
String
>[
'app-flavor1-release.apk'
]);
});
final
Iterable
<
File
>
apks
=
findApkFiles
(
project
,
testWithoutContext
(
'Finds APK with flavor in release mode - AGP v3'
,
()
{
final
Iterable
<
String
>
apks
=
listApkPaths
(
const
AndroidBuildInfo
(
BuildInfo
(
BuildMode
.
release
,
'flavor1'
,
treeShakeIcons:
false
)),
);
expect
(
apks
.
isNotEmpty
,
isTrue
);
expect
(
apks
.
first
.
path
,
equals
(
globals
.
fs
.
path
.
join
(
'irrelevant'
,
'app'
,
'outputs'
,
'apk'
,
'flavor1'
,
'release'
,
'app-flavor1-release.apk'
)));
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
expect
(
apks
,
<
String
>[
'app-flavor1-release.apk'
]);
});
testUsingContext
(
'apk not found'
,
()
{
final
FlutterProject
project
=
FlutterProject
.
current
();
expect
(
()
{
findApkFiles
(
project
,
const
AndroidBuildInfo
(
BuildInfo
(
BuildMode
.
debug
,
'foo_bar'
,
treeShakeIcons:
false
)),
);
},
throwsToolExit
(
message:
"Gradle build failed to produce an .apk file. It's likely that this file "
"was generated under
${project.android.buildDirectory.path}
, but the tool couldn't find it."
)
testWithoutContext
(
'Finds APK with split-per-abi'
,
()
{
final
Iterable
<
String
>
apks
=
listApkPaths
(
const
AndroidBuildInfo
(
BuildInfo
(
BuildMode
.
release
,
'flavor1'
,
treeShakeIcons:
false
),
splitPerAbi:
true
),
);
verify
(
mockUsage
.
sendEvent
(
any
,
any
,
label:
'gradle-expected-file-not-found'
,
parameters:
const
<
String
,
String
>
{
'cd37'
:
'androidGradlePluginVersion: 5.6.2, fileExtension: .apk'
,
},
),
).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
FileSystem:
()
=>
MemoryFileSystem
(),
ProcessManager:
()
=>
FakeProcessManager
.
any
(),
Usage:
()
=>
mockUsage
,
expect
(
apks
,
unorderedEquals
(<
String
>[
'app-armeabi-v7a-flavor1-release.apk'
,
'app-arm64-v8a-flavor1-release.apk'
,
'app-x86_64-flavor1-release.apk'
,
]));
});
});
...
...
@@ -1415,8 +1349,7 @@ plugin1=${plugin1.path}
fileSystem
.
directory
(
'build'
)
.
childDirectory
(
'app'
)
.
childDirectory
(
'outputs'
)
.
childDirectory
(
'apk'
)
.
childDirectory
(
'release'
)
.
childDirectory
(
'flutter-apk'
)
.
childFile
(
'app-release.apk'
)
.
createSync
(
recursive:
true
);
...
...
@@ -1455,7 +1388,6 @@ plugin1=${plugin1.path}
label:
'gradle-random-event-label-success'
,
parameters:
anyNamed
(
'parameters'
),
)).
called
(
1
);
},
overrides:
<
Type
,
Generator
>{
AndroidSdk:
()
=>
mockAndroidSdk
,
Cache:
()
=>
cache
,
...
...
@@ -1553,17 +1485,6 @@ plugin1=${plugin1.path}
});
testUsingContext
(
'indicates that an APK has been built successfully'
,
()
async
{
when
(
mockProcessManager
.
start
(
any
,
workingDirectory:
anyNamed
(
'workingDirectory'
),
environment:
anyNamed
(
'environment'
)))
.
thenAnswer
((
_
)
{
return
Future
<
Process
>.
value
(
createMockProcess
(
exitCode:
0
,
stdout:
''
,
));
});
fileSystem
.
directory
(
'android'
)
.
childFile
(
'build.gradle'
)
.
createSync
(
recursive:
true
);
...
...
@@ -1581,8 +1502,7 @@ plugin1=${plugin1.path}
fileSystem
.
directory
(
'build'
)
.
childDirectory
(
'app'
)
.
childDirectory
(
'outputs'
)
.
childDirectory
(
'apk'
)
.
childDirectory
(
'release'
)
.
childDirectory
(
'flutter-apk'
)
.
childFile
(
'app-release.apk'
)
.
createSync
(
recursive:
true
);
...
...
@@ -1602,7 +1522,7 @@ plugin1=${plugin1.path}
expect
(
testLogger
.
statusText
,
contains
(
'Built build/app/outputs/
apk/release
/app-release.apk (0.0MB)'
),
contains
(
'Built build/app/outputs/
flutter-apk
/app-release.apk (0.0MB)'
),
);
},
overrides:
<
Type
,
Generator
>{
...
...
@@ -1610,7 +1530,7 @@ plugin1=${plugin1.path}
Cache:
()
=>
cache
,
FileSystem:
()
=>
fileSystem
,
Platform:
()
=>
android
,
ProcessManager:
()
=>
mockProcessManager
,
ProcessManager:
()
=>
FakeProcessManager
.
any
()
,
});
testUsingContext
(
"doesn't indicate how to consume an AAR when printHowToConsumeAaar is false"
,
()
async
{
...
...
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