Skip to content

Commit

Permalink
[Xamarin.Android.Build.Tasks] Skip binding lib AndroidManifest.xml's (d…
Browse files Browse the repository at this point in the history
…otnet#4812)

Fixes: dotnet#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.
  • Loading branch information
dellis1972 authored Jun 25, 2020
1 parent e6603ba commit ba3fd5b
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 6 deletions.
13 changes: 13 additions & 0 deletions Documentation/release-notes/Issue4804.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
#### Wrong AndroidManifest.xml packaged to the APK while using binding library

* [GitHub 4812][0]: We were overwriting the AndroidManifest.xml file
in the apk with ones from Support Libraries. This manifests itself
with the following 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:
```


[0]: https://github.com/xamarin/xamarin-android/pull/4812
14 changes: 9 additions & 5 deletions src/Xamarin.Android.Build.Tasks/Tasks/BuildApk.cs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ public class BuildApk : AndroidTask

[Required]
public string ApkInputPath { get; set; }

[Required]
public string ApkOutputPath { get; set; }

Expand Down Expand Up @@ -101,7 +101,7 @@ bool _Debug {
}

SequencePointsMode sequencePointsMode = SequencePointsMode.None;

public ITaskItem[] LibraryProjectJars { get; set; }
string [] uncompressedFileExtensions;

Expand Down Expand Up @@ -241,6 +241,10 @@ void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOut
Log.LogDebugMessage ($"Skipping {path} as the archive file is up to date.");
continue;
}
if (apk.Archive.Any (e => e.FullName == path)) {
Log.LogDebugMessage ("Failed to add jar entry {0} from {1}: the same file already exists in the apk", name, Path.GetFileName (jarFile));
continue;
}
byte [] data;
using (var d = new MemoryStream ()) {
jarItem.Extract (d);
Expand All @@ -256,7 +260,7 @@ void ExecuteWithAbi (string [] supportedAbis, string apkInputPath, string apkOut
count = 0;
}
}
// Clean up Removed files.
// Clean up Removed files.
foreach (var entry in existingEntries) {
Log.LogDebugMessage ($"Removing {entry} as it is not longer required.");
apk.Archive.DeleteEntry (entry);
Expand Down Expand Up @@ -296,7 +300,7 @@ public override bool RunTask ()
var apk = Path.GetFileNameWithoutExtension (ApkOutputPath);
ExecuteWithAbi (new [] { abi }, String.Format ("{0}-{1}", ApkInputPath, abi),
Path.Combine (path, String.Format ("{0}-{1}.apk", apk, abi)),
debug, compress, compressedAssembliesInfo);
debug, compress, compressedAssembliesInfo);
outputFiles.Add (Path.Combine (path, String.Format ("{0}-{1}.apk", apk, abi)));
}
}
Expand Down Expand Up @@ -548,7 +552,7 @@ string GetNativeLibraryAbi (ITaskItem lib)
{
// If Abi is explicitly specified, simply return it.
var lib_abi = MonoAndroidHelper.GetNativeLibraryAbi (lib);

if (string.IsNullOrWhiteSpace (lib_abi)) {
Log.LogCodedError ("XA4301", lib.ItemSpec, 0, Properties.Resources.XA4301_ABI, lib.ItemSpec);
return null;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -672,7 +672,7 @@ public void CheckTheCorrectRuntimeAssemblyIsUsedFromNuget ()
ns.SetProperty ("Description", "Test");
ns.SetProperty ("PackageOutputPath", path);


var xa = new XamarinAndroidApplicationProject () {
ProjectName = "App",
PackageReferences = {
Expand Down Expand Up @@ -789,5 +789,53 @@ public void MissingSatelliteAssemblyInApp ()
}
}
}

[Test]
public void IgnoreManifestFromJar ()
{
string java = @"
package com.xamarin.testing;
public class Test
{
}
";
var path = Path.Combine (Root, "temp", TestName);
var javaDir = Path.Combine (path, "java", "com", "xamarin", "testing");
if (Directory.Exists (javaDir))
Directory.Delete (javaDir, true);
Directory.CreateDirectory (javaDir);
File.WriteAllText (Path.Combine (javaDir, "..", "..", "..", "AndroidManifest.xml"), @"<?xml version='1.0' ?><maniest />");
var lib = new XamarinAndroidBindingProject () {
AndroidClassParser = "class-parse",
ProjectName = "Binding1",
};
lib.MetadataXml = "<metadata></metadata>";
lib.Jars.Add (new AndroidItem.EmbeddedJar (Path.Combine ("java", "test.jar")) {
BinaryContent = new JarContentBuilder () {
BaseDirectory = Path.Combine (path, "java"),
JarFileName = "test.jar",
JavaSourceFileName = Path.Combine ("com", "xamarin", "testing", "Test.java"),
JavaSourceText = java,
AdditionalFileExtensions = "*.xml",
}.Build
});
var app = new XamarinAndroidApplicationProject {
IsRelease = true,
};
app.References.Add (new BuildItem.ProjectReference ($"..\\{lib.ProjectName}\\{lib.ProjectName}.csproj", lib.ProjectName, lib.ProjectGuid));

using (var builder = CreateDllBuilder (Path.Combine (path, lib.ProjectName))) {
Assert.IsTrue (builder.Build (lib), "Build of jar should have succeeded.");
using (var zip = ZipHelper.OpenZip (Path.Combine (path, "java", "test.jar"))) {
Assert.IsTrue (zip.ContainsEntry ($"AndroidManifest.xml"), "Jar should contain AndroidManifest.xml");
}
using (var b = CreateApkBuilder (Path.Combine (path, app.ProjectName))) {
Assert.IsTrue (b.Build (app), "Build of jar should have succeeded.");
string expected = "Failed to add jar entry AndroidManifest.xml from test.jar: the same file already exists in the apk";
Assert.IsTrue (b.LastBuildOutput.ContainsText (expected), $"AndroidManifest.xml for test.jar should have been ignored.");
}
}
}
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ public class JarContentBuilder : ContentBuilder
public string JavaSourceFileName { get; set; }
public string JavaSourceText { get; set; }

public string AdditionalFileExtensions { get; set; }

public JarContentBuilder ()
{
Action<TraceLevel, string> logger = (level, value) => {
Expand Down Expand Up @@ -57,6 +59,10 @@ public override byte [] Build ()
File.Delete (jarfile);
var args = new string [] { "cvf", JarFileName };
var classes = Directory.GetFiles (Path.GetDirectoryName (src), "*.class", SearchOption.AllDirectories);
if (!string.IsNullOrEmpty (AdditionalFileExtensions)) {
var additionalFiles = Directory.GetFiles (Path.GetDirectoryName (BaseDirectory), AdditionalFileExtensions, SearchOption.AllDirectories);
classes = classes.Concat (additionalFiles).ToArray ();
}
var jarPsi = new ProcessStartInfo () {
FileName = JarFullPath,
Arguments = string.Join (" ", args.Concat (classes.Select (c => c.Substring (BaseDirectory.Length + 1)).ToArray ())),
Expand Down

0 comments on commit ba3fd5b

Please sign in to comment.