dotnet / android

.NET for Android provides open-source bindings of the Android SDK for use with .NET managed languages such as C#
MIT License
1.93k stars 525 forks source link

Link out unused Resources from the apk. #5203

Open dellis1972 opened 3 years ago

dellis1972 commented 3 years ago

Context https://developer.android.com/studio/build/shrink-code#shrink-resources

Android includes a system where unused resources from the apk are removed as part of the build process. This will result in smaller abb/apk files. We should look at doing something similar, it will take some investigation though.

Initial thoughts would be.

  1. Analyse the use of Resources.Foo Items in the linked C# code via Cecil. Use this information to generate a .java stub file which contains only the use resources.
  2. when compiling the java code we include this .java stub .
  3. Somehow tell aapt2 to remove unused resources, or manually remove them ourselves?

more investigation will be needed. However I think this is something we should look at.

dellis1972 commented 3 years ago

Some code to take a look at

https://github.com/luori366/android-platform-tools-base/blob/49d23734981c27378c9dea00266e402f7f1e5de8/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ShrinkResources.groovy https://github.com/luori366/android-platform-tools-base/blob/49d23734981c27378c9dea00266e402f7f1e5de8/build-system/gradle-core/src/main/groovy/com/android/build/gradle/tasks/ResourceUsageAnalyzer.java

We can probably create a task which can replicate those.

The process seems to run as follows

  1. Collect R id values from the final merged R class, which incorporates the final id's of all the libraries (if ProGuard hasn't inlined these, we don't need to do this; we can look for actual R.id's instead!)
  2. Collect used R values from all the .class files, and R.x.y references too!
  3. Compute the set of remaining/used id’s
  4. Add in any found in the manifest
  5. Look through all resources and produce a graph of reachable resources
  6. Compute unused resources by visiting all resources and ignoring those that were reachable
  7. In addition, if we find a call to Resources#getIdentifier(), we collect all strings in the class files, and also mark as used any resources that match potential string lookups

This will need to be updated to use our C# Resouce.desinger.cs as well as the R.java classes. But once we have a list of used resources we can remove the unused from the apk. Can must be taken to make sure transient resources are kept.

jonathanpeppers commented 3 years ago

Is this at all related to aapt2 optimize? See: https://github.com/xamarin/xamarin-android/issues/5116

dellis1972 commented 3 years ago

As far as I know its not. This seems to related to a post Java link step that runs to remove unused resources.

dellis1972 commented 3 years ago

Also #5116 seems to only work on .apk files, where as this would work on both apk and aab files.