Skip to content

Commit 88b8363

Browse files
dellis1972jonpryor
authored andcommitted
[Xamarin.Android.Build.Tasks] Skip binding lib AndroidManifest.xml's (#4812)
Fixes: #4804 We were overwriting the `AndroidManifest.xml` file in the `.apk` with ones from Support Libraries. This manifests itself with the following runtime error: Failed to parse APK info: failed to parse AndroidManifest.xml, error: %!s() deploy failed, error: failed to get apk infos, output: W/ResourceType( 5266): Bad XML block: This commit fixes this issue by ignoring files from `.jar` files which already exist in the `.apk`. This stops things from being overwritten. A test has also been added.
1 parent 90d067b commit 88b8363

File tree

4 files changed

+77
-6
lines changed

4 files changed

+77
-6
lines changed
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
#### Wrong AndroidManifest.xml packaged to the APK while using binding library
2+
3+
* [GitHub 4812][0]: We were overwriting the AndroidManifest.xml file
4+
in the apk with ones from Support Libraries. This manifests itself
5+
with the following error
6+
7+
```
8+
Failed to parse APK info: failed to parse AndroidManifest.xml, error: %!s()
9+
deploy failed, error: failed to get apk infos, output: W/ResourceType( 5266): Bad XML block:
10+
```
11+
12+
13+
[0]: https://github.com/xamarin/xamarin-android/pull/4812

src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs

Lines changed: 9 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ public class BuildApk : AndroidTask
2828

2929
[Required]
3030
public string ApkInputPath { get; set; }
31-
31+
3232
[Required]
3333
public string ApkOutputPath { get; set; }
3434

@@ -101,7 +101,7 @@ bool _Debug {
101101
}
102102

103103
SequencePointsMode sequencePointsMode = SequencePointsMode.None;
104-
104+
105105
public ITaskItem[] LibraryProjectJars { get; set; }
106106
string [] uncompressedFileExtensions;
107107

@@ -246,6 +246,10 @@ void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOut
246246
Log.LogDebugMessage ($"Skipping {path} as the archive file is up to date.");
247247
continue;
248248
}
249+
if (apk.Archive.Any (e => e.FullName == path)) {
250+
Log.LogDebugMessage ("Failed to add jar entry {0} from {1}: the same file already exists in the apk", name, Path.GetFileName (jarFile));
251+
continue;
252+
}
249253
byte [] data;
250254
using (var d = new MemoryStream ()) {
251255
jarItem.Extract (d);
@@ -261,7 +265,7 @@ void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOut
261265
count = 0;
262266
}
263267
}
264-
// Clean up Removed files.
268+
// Clean up Removed files.
265269
foreach (var entry in existingEntries) {
266270
Log.LogDebugMessage ($"Removing {entry} as it is not longer required.");
267271
apk.Archive.DeleteEntry (entry);
@@ -301,7 +305,7 @@ public override bool RunTask ()
301305
var apk = Path.GetFileNameWithoutExtension (ApkOutputPath);
302306
ExecuteWithAbi (new [] { abi }, String.Format ("{0}-{1}", ApkInputPath, abi),
303307
Path.Combine (path, String.Format ("{0}-{1}.apk", apk, abi)),
304-
debug, compress, compressedAssembliesInfo);
308+
debug, compress, compressedAssembliesInfo);
305309
outputFiles.Add (Path.Combine (path, String.Format ("{0}-{1}.apk", apk, abi)));
306310
}
307311
}
@@ -541,7 +545,7 @@ string GetNativeLibraryAbi (ITaskItem lib)
541545
{
542546
// If Abi is explicitly specified, simply return it.
543547
var lib_abi = MonoAndroidHelper.GetNativeLibraryAbi (lib);
544-
548+
545549
if (string.IsNullOrWhiteSpace (lib_abi)) {
546550
Log.LogCodedError ("XA4301", lib.ItemSpec, 0, Properties.Resources.XA4301_ABI, lib.ItemSpec);
547551
return null;

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.Android.Build.Tests/PackagingTest.cs

Lines changed: 49 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -674,7 +674,7 @@ public void CheckTheCorrectRuntimeAssemblyIsUsedFromNuget ()
674674
ns.SetProperty ("Description", "Test");
675675
ns.SetProperty ("PackageOutputPath", path);
676676

677-
677+
678678
var xa = new XamarinAndroidApplicationProject () {
679679
ProjectName = "App",
680680
PackageReferences = {
@@ -791,5 +791,53 @@ public void MissingSatelliteAssemblyInApp ()
791791
}
792792
}
793793
}
794+
795+
[Test]
796+
public void IgnoreManifestFromJar ()
797+
{
798+
string java = @"
799+
package com.xamarin.testing;
800+
801+
public class Test
802+
{
803+
}
804+
";
805+
var path = Path.Combine (Root, "temp", TestName);
806+
var javaDir = Path.Combine (path, "java", "com", "xamarin", "testing");
807+
if (Directory.Exists (javaDir))
808+
Directory.Delete (javaDir, true);
809+
Directory.CreateDirectory (javaDir);
810+
File.WriteAllText (Path.Combine (javaDir, "..", "..", "..", "AndroidManifest.xml"), @"<?xml version='1.0' ?><maniest />");
811+
var lib = new XamarinAndroidBindingProject () {
812+
AndroidClassParser = "class-parse",
813+
ProjectName = "Binding1",
814+
};
815+
lib.MetadataXml = "<metadata></metadata>";
816+
lib.Jars.Add (new AndroidItem.EmbeddedJar (Path.Combine ("java", "test.jar")) {
817+
BinaryContent = new JarContentBuilder () {
818+
BaseDirectory = Path.Combine (path, "java"),
819+
JarFileName = "test.jar",
820+
JavaSourceFileName = Path.Combine ("com", "xamarin", "testing", "Test.java"),
821+
JavaSourceText = java,
822+
AdditionalFileExtensions = "*.xml",
823+
}.Build
824+
});
825+
var app = new XamarinAndroidApplicationProject {
826+
IsRelease = true,
827+
};
828+
app.References.Add (new BuildItem.ProjectReference ($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid));
829+
830+
using (var builder = CreateDllBuilder (Path.Combine (path, lib.ProjectName))) {
831+
Assert.IsTrue (builder.Build (lib), "Build of jar should have succeeded.");
832+
using (var zip = ZipHelper.OpenZip (Path.Combine (path, "java", "test.jar"))) {
833+
Assert.IsTrue (zip.ContainsEntry ($"AndroidManifest.xml"), "Jar should contain AndroidManifest.xml");
834+
}
835+
using (var b = CreateApkBuilder (Path.Combine (path, app.ProjectName))) {
836+
Assert.IsTrue (b.Build (app), "Build of jar should have succeeded.");
837+
string expected = "Failed to add jar entry AndroidManifest.xml from test.jar: the same file already exists in the apk";
838+
Assert.IsTrue (b.LastBuildOutput.ContainsText (expected), $"AndroidManifest.xml for test.jar should have been ignored.");
839+
}
840+
}
841+
}
794842
}
795843
}

src/Xamarin.Android.Build.Tasks/Tests/Xamarin.ProjectTools/Android/JarContentBuilder.cs

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,8 @@ public class JarContentBuilder : ContentBuilder
1616
public string JavaSourceFileName { get; set; }
1717
public string JavaSourceText { get; set; }
1818

19+
public string AdditionalFileExtensions { get; set; }
20+
1921
public JarContentBuilder ()
2022
{
2123
Action<TraceLevel, string> logger = (level, value) => {
@@ -57,6 +59,10 @@ public override byte [] Build ()
5759
File.Delete (jarfile);
5860
var args = new string [] { "cvf", JarFileName };
5961
var classes = Directory.GetFiles (Path.GetDirectoryName (src), "*.class", SearchOption.AllDirectories);
62+
if (!string.IsNullOrEmpty (AdditionalFileExtensions)) {
63+
var additionalFiles = Directory.GetFiles (Path.GetDirectoryName (BaseDirectory), AdditionalFileExtensions, SearchOption.AllDirectories);
64+
classes = classes.Concat (additionalFiles).ToArray ();
65+
}
6066
var jarPsi = new ProcessStartInfo () {
6167
FileName = JarFullPath,
6268
Arguments = string.Join (" ", args.Concat (classes.Select (c => c.Substring (BaseDirectory.Length + 1)).ToArray ())),

0 commit comments

Comments
 (0)