Skip to content

Commit 0fd5fef

Browse files
committed
Use Android SDK tools to fix up APK after patching.
1 parent 901ef1f commit 0fd5fef

File tree

3 files changed

+59
-7
lines changed

3 files changed

+59
-7
lines changed

src/tasks/AndroidAppBuilder/ApkBuilder.cs

Lines changed: 31 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -463,7 +463,7 @@ public ApkBuilder(TaskLoggingHelper logger)
463463
// 4. Align APK
464464

465465
string alignedApk = Path.Combine(OutputDir, "bin", $"{ProjectName}.apk");
466-
Utils.RunProcess(logger, zipalign, $"-v 4 {apkFile} {alignedApk}", workingDir: OutputDir);
466+
AlignApk(apkFile, alignedApk, zipalign);
467467
// we don't need the unaligned one any more
468468
File.Delete(apkFile);
469469

@@ -475,6 +475,11 @@ public ApkBuilder(TaskLoggingHelper logger)
475475
return (alignedApk, packageId);
476476
}
477477

478+
private void AlignApk(string unalignedApkPath, string apkOutPath, string zipalign)
479+
{
480+
Utils.RunProcess(logger, zipalign, $"-v 4 {unalignedApkPath} {apkOutPath}", workingDir: OutputDir);
481+
}
482+
478483
private void SignApk(string apkPath, string apksigner)
479484
{
480485
string defaultKey = Path.Combine(OutputDir, "debug.keystore");
@@ -495,6 +500,31 @@ private void SignApk(string apkPath, string apksigner)
495500
$"--ks-pass pass:android --key-pass pass:android {apkPath}", workingDir: OutputDir);
496501
}
497502

503+
public void ZipAndSignApk(string apkPath)
504+
{
505+
if (string.IsNullOrEmpty(AndroidSdk))
506+
AndroidSdk = Environment.GetEnvironmentVariable("ANDROID_SDK_ROOT");
507+
508+
if (string.IsNullOrEmpty(AndroidSdk) || !Directory.Exists(AndroidSdk))
509+
throw new ArgumentException($"Android SDK='{AndroidSdk}' was not found or incorrect (can be set via ANDROID_SDK_ROOT envvar).");
510+
511+
if (string.IsNullOrEmpty(BuildToolsVersion))
512+
BuildToolsVersion = GetLatestBuildTools(AndroidSdk);
513+
514+
if (string.IsNullOrEmpty(MinApiLevel))
515+
MinApiLevel = DefaultMinApiLevel;
516+
517+
string buildToolsFolder = Path.Combine(AndroidSdk, "build-tools", BuildToolsVersion);
518+
string zipalign = Path.Combine(buildToolsFolder, "zipalign");
519+
string apksigner = Path.Combine(buildToolsFolder, "apksigner");
520+
521+
string alignedApkPath = $"{apkPath}.aligned";
522+
AlignApk(apkPath, alignedApkPath, zipalign);
523+
logger.LogMessage(MessageImportance.High, $"\nMoving '{alignedApkPath}' to '{apkPath}'.\n");
524+
File.Move(alignedApkPath, apkPath, overwrite: true);
525+
SignApk(apkPath, apksigner);
526+
}
527+
498528
public void ReplaceFileInApk(string file)
499529
{
500530
if (string.IsNullOrEmpty(AndroidSdk))

src/tasks/TestExclusionListTasks/PatchExclusionListInApks.cs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -18,19 +18,38 @@ public class PatchExclusionListInApks : Task
1818
[Required]
1919
public ITaskItem[]? ExcludedTests { get; set; }
2020

21+
public string? AndroidSdk { get; set; }
22+
23+
public string? MinApiLevel { get; set; }
24+
25+
public string? BuildToolsVersion { get; set; }
26+
27+
public string? KeyStorePath { get; set; }
28+
2129
public override bool Execute()
2230
{
31+
var apkBuilder = new ApkBuilder(Log);
32+
apkBuilder.AndroidSdk = AndroidSdk;
33+
apkBuilder.MinApiLevel = MinApiLevel;
34+
apkBuilder.BuildToolsVersion = BuildToolsVersion;
35+
apkBuilder.KeyStorePath = KeyStorePath;
36+
2337
string testExclusionList = string.Join(
2438
'\n',
2539
(ExcludedTests ?? Enumerable.Empty<ITaskItem>()).Select(t => t.ItemSpec));
2640
foreach (ITaskItem apk in ApkPaths ?? Enumerable.Empty<ITaskItem>())
2741
{
28-
using ZipArchive apkArchive = ZipFile.Open(apk.GetMetadata("FullPath"), ZipArchiveMode.Update);
29-
ZipArchiveEntry assetsZipEntry = apkArchive.GetEntry("assets/assets.zip")!;
30-
using ZipArchive assetsArchive = new ZipArchive(assetsZipEntry.Open(), ZipArchiveMode.Update);
31-
ZipArchiveEntry testExclusionListEntry = assetsArchive.GetEntry("TestExclusionList.txt")!;
32-
using StreamWriter textExclusionListWriter = new StreamWriter(testExclusionListEntry.Open());
33-
textExclusionListWriter.WriteLine(testExclusionList);
42+
string apkPath = apk.GetMetadata("FullPath")!;
43+
apkBuilder.OutputDir = Path.GetDirectoryName(apkPath)!;
44+
using (ZipArchive apkArchive = ZipFile.Open(apkPath, ZipArchiveMode.Update))
45+
{
46+
ZipArchiveEntry assetsZipEntry = apkArchive.GetEntry("assets/assets.zip")!;
47+
using ZipArchive assetsArchive = new ZipArchive(assetsZipEntry.Open(), ZipArchiveMode.Update);
48+
ZipArchiveEntry testExclusionListEntry = assetsArchive.GetEntry("TestExclusionList.txt")!;
49+
using StreamWriter textExclusionListWriter = new StreamWriter(testExclusionListEntry.Open());
50+
textExclusionListWriter.WriteLine(testExclusionList);
51+
}
52+
apkBuilder.ZipAndSignApk(apkPath);
3453
}
3554
return true;
3655
}

src/tasks/TestExclusionListTasks/TestExclusionListTasks.csproj

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,13 @@
55
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
66
<EnableDefaultCompileItems>false</EnableDefaultCompileItems>
77
<Nullable>enable</Nullable>
8+
<NoWarn>$(NoWarn),CA1050</NoWarn>
89
</PropertyGroup>
910

1011
<ItemGroup>
1112
<Compile Include="PatchExclusionListInApks.cs" />
13+
<Compile Include="../AndroidAppBuilder/ApkBuilder.cs" />
14+
<Compile Include="../Common/Utils.cs" />
1215
</ItemGroup>
1316
<ItemGroup>
1417
<PackageReference Include="Microsoft.Build.Tasks.Core" Version="$(MicrosoftBuildTasksCoreVersion)" />

0 commit comments

Comments
 (0)