Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Aapt and Aapt2 MSBuild tasks do not yet use -G and --proguard options to help generate rules when ProGuard or R8 is enabled #3636

Closed
brendanzagaeski opened this issue Sep 16, 2019 · 6 comments · Fixed by #3899
Assignees
Labels
Area: App+Library Build Issues when building Library projects or Application projects.

Comments

@brendanzagaeski
Copy link
Contributor

Previous related reports:

Steps to reproduce

  1. Create a new Single View Android app.
  2. Set Code shrinker to ProGuard or r8 in the Android Options section of the project properties for the Release configuration.
  3. Set the Compile using Android version: (Target Framework) to Android 8.1 (Oreo) as a way to avoid the missing proguard.txt files in the monoandroid90 target framework directories in the Xamarin.Android.Support NuGet packages.
  4. Build and run the app in the Release configuration on an emulator or device.

Example project: SingleViewAndroidApp1.zip

Expected behaviors

In a Gradle build in Android Studio for a matching project, some important types are preserved by app\build\intermediates\proguard-rules\release\aapt_rules.txt. Based on those results, I believe the expected behaviors are:

  • The Aapt2 task passes the --proguard aapt_rules.txt option to aapt2.exe and then passes the resulting aapt_rules.txt file to ProGuard or R8.

    (Or for aapt, the Aapt task passes the -G aapt_rules.txt option to aapt.exe and then passes the resulting aapt_rules.txt file to ProGuard or R8.)

  • The app runs without error.

Actual behaviors

  • The Aapt2 task does not pass the --proguard option to aapt2.exe, and the Aapt task does not pass the -G option to aapt.exe.

  • The app exits during startup because some required types are missing:

    UNHANDLED EXCEPTION:
    Java.Lang.Exception: Binary XML file line #17: Binary XML file line #17: Error inflating class android.support.v7.widget.FitWindowsLinearLayout ---> Java.Lang.Exception: Binary XML file line #17: Error inflating class android.support.v7.widget.FitWindowsLinearLayout ---> Java.Lang.ClassNotFoundException: Didn't find class "android.support.v7.widget.FitWindowsLinearLayout" on path: DexPathList[[zip file "/system/framework/org.apache.http.legacy.boot.jar", zip file "/data/app/com.companyname.SingleViewAndroidApp1-mH2uq3zIMPtg74LEwholzQ==/base.apk"],nativeLibraryDirectories=[/data/app/com.companyname.SingleViewAndroidApp1-mH2uq3zIMPtg74LEwholzQ==/lib/arm64, /data/app/com.companyname.SingleViewAndroidApp1-mH2uq3zIMPtg74LEwholzQ==/base.apk!/lib/arm64-v8a, /system/lib64]]
       --- End of inner exception stack trace ---
       --- End of inner exception stack trace ---
      at Java.Interop.JniEnvironment+InstanceMethods.CallNonvirtualVoidMethod (Java.Interop.JniObjectReference instance, Java.Interop.JniObjectReference type, Java.Interop.JniMethodInfo method, Java.Interop.JniArgumentValue* args) [0x00089] in <a4799c6c501b49678cf6198cb1aef16d>:0 
      at Java.Interop.JniPeerMembers+JniInstanceMethods.InvokeVirtualVoidMethod (System.String encodedMember, Java.Interop.IJavaPeerable self, Java.Interop.JniArgumentValue* parameters) [0x0005d] in <a4799c6c501b49678cf6198cb1aef16d>:0 
      at Android.App.Activity.SetContentView (System.Int32 layoutResID) [0x00022] in <79b6bab2d7a34df8b5739e028c597831>:0 
      at SingleViewAndroidApp1.MainActivity.OnCreate (Android.OS.Bundle savedInstanceState) [0x0000e] in <4106ae493f094976aff9acf26162ea25>:0 
      at Android.App.Activity.n_OnCreate_Landroid_os_Bundle_ (System.IntPtr jnienv, System.IntPtr native__this, System.IntPtr native_savedInstanceState) [0x00011] in <79b6bab2d7a34df8b5739e028c597831>:0 
      at (wrapper dynamic-method) Android.Runtime.DynamicMethodNameCounter.3(intptr,intptr,intptr)
    

Manual workaround, proof of concept

  1. If the project has Use incremental Android packaging system (aapt2) enabled, add the following lines to the .csproj file:

    <PropertyGroup>
      <AndroidAapt2LinkExtraArgs>--proguard aapt_rules.txt $(AndroidAapt2LinkExtraArgs)</AndroidAapt2LinkExtraArgs>
    </PropertyGroup>

    Or if the project does not have the incremental Android packaging system enabled, add the following lines instead:

    <PropertyGroup>
      <AndroidResgenExtraArgs>-G aapt_rules.txt $(AndroidResgenExtraArgs)</AndroidResgenExtraArgs>
    </PropertyGroup>
  2. Build and run the app again to generate the aapt_rules.txt file in the project directory.

  3. Add the new aapt_rules.txt file to project in the Solution Explorer, and set the Build Action to ProguardConfiguration.

  4. Remove the lines from the .csproj that were added in step 1 (to keep the generated aapt_fules.txt under careful manual control for this proof of concept).

  5. Clean, rebuild, and rerun the app.

The app now launches successfully.

Version information

This behavior exists in Visual Studio 2019 version 16.4 Int Preview with Xamarin.Android 10.0.0.40.

This behavior has been the same for the built-in template projects since back to at least Visual Studio 2019 version 16.1 with Xamarin.Android 9.3.0.23.

@brendanzagaeski brendanzagaeski added the Area: App+Library Build Issues when building Library projects or Application projects. label Sep 16, 2019
@brendanzagaeski brendanzagaeski added this to the Under Consideration milestone Sep 16, 2019
@brendanzagaeski
Copy link
Contributor Author

I'd be happy to take a try setting up a PR to add these options to the Aapt and Aapt2 tasks when I get a chance. But anyone else feel free to take care of it before then if you like.

@ndastur
Copy link

ndastur commented Sep 18, 2019

I wonder if the Xamarin team could place a higher priority on this bug. Xamarin app are already really large in terms of App Store size and essentially this means Proguard can't be used at all. With upcoming app store changes around the use of bundles etc all this sort of stuff is going to be critical.

@brendanzagaeski
Copy link
Contributor Author

I should probably add a few words to my previous comment for clarity. Instead of "anyone else," I should have said "anyone else on the team." I suspect someone else on the team might beat me to adding this functionality.

jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this issue Nov 11, 2019
…ules

Context: https://developer.android.com/studio/build/shrink-code#configuration-files
Fixes: http://work.azdo.io/825420
Fixes: dotnet#3636

Let's say you used the following code fragment in an Android layout:

    <android.support.v7.widget.Toolbar />

Currently, you would need to add a ProGuard rule regardless if you
were using ProGuard or R8.

Fortunately, `aapt2` has a command-line switch:

    > aapt2 link -h
    ...
    --proguard arg    Output file for generated Proguard rules.

According to the Google docs for R8:

    AAPT2 generates keep rules based on references to classes in your
    app’s manifest, layouts, and other app resources. For example, AAPT2
    includes a keep rule for each Activity that you register in your app’s
    manifest as an entry point.

I added a new `ProguardRuleOutput` property for `<Aapt2Link/>` and set
it in cases where `$(AndroidLinkTool)` is not blank. I added this file
to `@(ProguardConfiguration)`, so it will get picked up by ProGuard or
R8.

I updated an existing test for this scenario, checking that a type is
generated in the rules and exists in the final `classes.dex` file.
jonathanpeppers added a commit to jonathanpeppers/xamarin-android that referenced this issue Nov 12, 2019
…ules

Context: https://developer.android.com/studio/build/shrink-code#configuration-files
Fixes: http://work.azdo.io/825420
Fixes: dotnet#3636

Let's say you used the following code fragment in an Android layout:

    <android.support.v7.widget.Toolbar />

Currently, you would need to add a ProGuard rule regardless if you
were using ProGuard or R8.

Fortunately, `aapt2` has a command-line switch:

    > aapt2 link -h
    ...
    --proguard arg    Output file for generated Proguard rules.

According to the Google docs for R8:

    AAPT2 generates keep rules based on references to classes in your
    app’s manifest, layouts, and other app resources. For example, AAPT2
    includes a keep rule for each Activity that you register in your app’s
    manifest as an entry point.

I added a new `ProguardRuleOutput` property for `<Aapt2Link/>` and set
it in cases where `$(AndroidLinkTool)` is not blank. I added this file
to `@(ProguardConfiguration)`, so it will get picked up by ProGuard or
R8.

I updated an existing test for this scenario, checking that a type is
generated in the rules and exists in the final `classes.dex` file.
jonathanpeppers added a commit that referenced this issue Nov 12, 2019
…ules (#3899)

Context: https://developer.android.com/studio/build/shrink-code#configuration-files
Fixes: http://work.azdo.io/825420
Fixes: #3636

Let's say you used the following code fragment in an Android layout:

    <android.support.v7.widget.Toolbar />

Currently, you would need to add a ProGuard rule regardless if you
were using ProGuard or R8.

Fortunately, `aapt2` has a command-line switch:

    > aapt2 link -h
    ...
    --proguard arg    Output file for generated Proguard rules.

According to the Google docs for R8:

    AAPT2 generates keep rules based on references to classes in your
    app’s manifest, layouts, and other app resources. For example, AAPT2
    includes a keep rule for each Activity that you register in your app’s
    manifest as an entry point.

I added a new `ProguardRuleOutput` property for `<Aapt2Link/>` and set
it in cases where `$(AndroidLinkTool)` is not blank. I added this file
to `@(ProguardConfiguration)`, so it will get picked up by ProGuard or
R8.

I updated an existing test for this scenario, checking that a type is
generated in the rules and exists in the final `classes.dex` file.
@brendanzagaeski
Copy link
Contributor Author

Release status update

A new Preview version has now been published on Windows that includes the fix for this item. The fix is not yet included in a Release version. I will update this item again when a Release version is available that includes the fix.

The fix is not yet available on macOS. I will update this item again when a Preview version with the fix is available on macOS.

Fix included in Xamarin.Android 10.2.100.7

Fix included on Windows in Visual Studio 2019 version 16.6 Preview 1. To try the Preview version that includes the fix, check for the latest updates in Visual Studio Preview.

Fix not yet available on macOS.

@brendanzagaeski
Copy link
Contributor Author

Release status update

A new Preview version has now been published on macOS that includes the fix for this item. The fix is not yet included in a Release version. I will update this again when a Release version is available that includes the fix.

Fix included in Xamarin.Android 10.3.0.33.

Fix included on macOS in Visual Studio 2019 for Mac version 8.6 Preview 1. To try the Preview version that includes the fix, check for the latest updates on the Preview updater channel.

(Fix also included on Windows in Visual Studio 2019 version 16.6 Preview 1 and higher. To try the Preview version that includes the fix, check for the latest updates in Visual Studio Preview.)

@brendanzagaeski
Copy link
Contributor Author

Release status update

A new Release version has now been published that includes the fix for this item.

Fix included in Xamarin.Android 10.3.1.0.

Fix included on Windows in Visual Studio 2019 version 16.6. To get the new version that includes the fix, check for the latest updates or install the latest version from https://visualstudio.microsoft.com/downloads/.

Fix included on macOS in Visual Studio 2019 for Mac version 8.6. To get the new version that includes the fix, check for the latest updates on the Stable updater channel.

@ghost ghost locked as resolved and limited conversation to collaborators Jun 5, 2022
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Area: App+Library Build Issues when building Library projects or Application projects.
Projects
None yet
3 participants