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

Optimize and fix android dependencies #299

Merged
merged 20 commits into from
Apr 27, 2024

Conversation

cbeyls
Copy link
Contributor

@cbeyls cbeyls commented Apr 25, 2024

This pull request optimizes and fixes the Android and Wear app dependencies and build configuration, with the following effects:

  • Reduce the Android apk file size by around 30% and the Wear apk file size by around 35%
  • Improve Gradle sync and build times
  • Fix crash in Android 7 caused by referencing missing java.time APIs (Java API desugaring must be enabled to be able to use kotlinx.datetime for older Android versions).

Detailed changes:

  • Enable core library desugaring for the Android app (it was previously enabled only for the Wear app) to be able to use the kotlinx.datetime library in all Android versions.
  • Remove duplicate or unused dependencies. Some unused libraries are: Coil (image loader), Kotlinx Serialization Gradle plugin (no @Serializable classes), Compose Material (only Compose Material3 is used), Firebase Installations, Firebase Analytics, Navigation Compose for Android (Wear OS uses Wear Navigation Compose, other apps use Precompose Navigation).
  • Remove AppCompat and Material Components libraries which are not needed in Compose-only apps. These libraries come with a lot of resources that Proguard and the resources shrinker are unable to remove.
  • Exclude AppCompat from transitive dependencies of Koin, Precompose and Moko. Some of these libraries don't actually use AppCompat at all, and others use it for optional features that are not used in the app.
  • Replace AppCompat themes and styles with basic white and dark themes matching the colors of the Compose themes, so the proper colors are shown during app startup before the first screen is loaded.
  • Remove Firebase in-app-messaging. This is an optional feature for push notifications with dependencies on AppCompat and Glide, both taking a lot of space but not used by any other code in the app.
  • Downgrade Androidx Compose to 1.6.4 to match the version upon which Multiplatform Compose is based.
  • Upgrade Compose Multiplatform plugin to 1.6.2
  • Upgrade Androidx Activity Compose to 1.9.0
  • Downgrade Apollo to 4.0.0-beta.2 because newer versions depend on version 2.0.0 of the Kotlin standard library but the project is designed to be built with Kotlin 1.9.23. Alternatively the latest stable version of Apollo 3.x could be used but it has different APIs which require code changes.
  • Remove unneeded Proguard rules (matching no existing classes) and replace default Proguard rules with better defaults. In particular, optimizations are now enabled, which allow builds to become smaller and faster.
  • Disable Kotlin runtime assertions in release builds.
  • Disable Koin debug logging in Android release builds. This generated a LOT of logs and is not suitable for production.
  • Remove Datastore shared counter native library from the APK files (it's only used for cross-process access).
  • Remove random unused files from the APK files.
  • Wear: switch from Horologist 0.6 to Horologist 0.5.25 which is the version compatible with Wear Compose 1.3.x and Compose 1.6.4. Using version 0.6 creates a mismatch with the Wear Compose dependency and the shared compose libraries like androidx.compose.ui:ui-tooling-preview.
  • Disable support vector drawables for Wear because minSDK is >24.

Please confirm if it's OK to remove the Firebase in-app messaging feature, otherwise AppCompat and Glide must be kept in the app just for it.

cbeyls added 16 commits April 25, 2024 13:20
- set the Android theme colors to match the compose theme colors on app startup.
- remove Koin-Android dependency which is not needed when adding Koin-Androidx-Compose dependency.
… on Kotlin 2.0.0 (the project depends on Kotlin 1.9.23)
@martinbonnin
Copy link
Contributor

Wow, nice! Thanks for this ❤️ ! I'll definitely need to take a deeper look but this looks great 👍 . TIL R8 could not tree shake the resources!

Initial comments:

Downgrade Apollo to 4.0.0-beta.2 because newer versions depend on version 2.0.0 of the Kotlin standard library but the project is designed to be built with Kotlin 1.9.23.

I think this is fine? kotlin-stdlib:2.0.0 is backward compatible with 1.9.23 so shouldn't be an issue to use a bigger version of kotlin. It could be an issue that the 1.9.23 compiler cannot read the 2.0.0 metadata but there's a n+1 best effort forward compatibility. So far it has not been an issue so I'm assuming it works for 1.9 -> 2.0 too?

Please confirm if it's OK to remove the Firebase in-app messaging feature

LGTM to remove them. We had plans to introduce some features but never got to it so I'm down for removing the dependency, We can alsways reintroduce later. Ping @enthuan? Ok for you?

@cbeyls
Copy link
Contributor Author

cbeyls commented Apr 26, 2024

I think this is fine? kotlin-stdlib:2.0.0 is backward compatible with 1.9.23 so shouldn't be an issue to use a bigger version of kotlin. It could be an issue that the 1.9.23 compiler cannot read the 2.0.0 metadata but there's a n+1 best effort forward compatibility. So far it has not been an issue so I'm assuming it works for 1.9 -> 2.0 too?

I didn't notice any issue, I just found suspicious that the entire app is using a beta version of the standard library that didn't match the compiler version, especially with the multiplatform stuff.

If you think it's safe then I can revert the change.

@cbeyls
Copy link
Contributor Author

cbeyls commented Apr 26, 2024

TIL R8 could not tree shake the resources!

I'm considering making a talk about limitations and workarounds of code and resources shrinking.

@martinbonnin
Copy link
Contributor

especially with the multiplatform stuff

Right, native could be an issue (JVM has always proven to work quite well in the past). JS doesn't work for an example. If anything, I'll probably update this repo to use 2.0.0-RC1 and keep us moving.

I'm considering making a talk about limitations and workarounds of code and resources shrinking.

Looking forward to it :)

@@ -38,7 +38,7 @@ class SigningConfigPlugin : Plugin<Project> {
isMinifyEnabled = true
isShrinkResources = true
proguardFiles(
getDefaultProguardFile("proguard-android.txt"),

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Wouldn't it be better to use proguard-android-optimized here to benefit from default rules with all possible optimizations?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

These rules are better but still way too conservative in my opinion, and they haven't been updated for ages. I can give you a detailed explanation later.

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am aware that they are outdated. My thought was it might be still safer for a small project.

I totally agree that adding rules based on your project is better.

@@ -35,6 +35,11 @@ kotlin {
}
}

configurations.configureEach {
// Remove unnecessary dependency of Precompose and Moko
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should we file a bug there?

Copy link
Contributor Author

@cbeyls cbeyls Apr 26, 2024

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yes, as far as I can tell these libraries depend on Core, Activity, or Lifecycle but not on AppCompat directly.

It's an old habit to just add AppCompat as a dependency with all the dependencies it brings along but if the code doesn't use Views and doesn't directly depend on any code in the package androidx.appcompat, it's a mistake.

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@cbeyls
Copy link
Contributor Author

cbeyls commented Apr 27, 2024

I focused on the Wear app and applied similar optimizations. I noticed a mismatch of Compose versions caused by Horologist, plus a bogus dependency from Horologist to both Material Components and AppCompat (!) and fixed these.

@martinbonnin
Copy link
Contributor

AppCompat is everywhere!

@martinbonnin martinbonnin merged commit e940908 into paug:main Apr 27, 2024
1 check passed
@martinbonnin
Copy link
Contributor

Follow up PR to bump Kotlin to 2.0.0-RC1: #304

@cbeyls
Copy link
Contributor Author

cbeyls commented Apr 28, 2024

..., plus a bogus dependency from Horologist to both Material Components and AppCompat (!) and fixed these.

I created a pull request to fix the dependencies of Horologist 0.5.x: google/horologist#2215

@cbeyls cbeyls deleted the chore/optimize_android_dependencies branch May 2, 2024 15:56
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants