Updating a 5 Year Old Android To Build With Android Studio 2024.1.2


A (long) while back I built a simple android app to help me manage my text messages. It was kind of novel and fit a niche use case I had. Eventually I moved on to other approaches and the code sat dormant for 5 years. I decided to revive the project and build an APK which would work on my Android 14 device. My expectation is that I would open the project, build / deploy it to my phone and then start tinkering on feature enhancements.

The reality is that 'bit rot' has set in and the effort to simply get the project to build was substantial. This post describes the process I followed to debug and update this extremely simple Android app to build in again in 2024.


References

The Unabridged Journey

Initial Look

Upon opening my old android project, I was greeted with this delightful assortment of errors:

  • 62 Errors in my MainActivity
  • Gradle spat out these errors:
A problem occurred configuring project ':app'.
> Failed to notify project evaluation listener.
  > Could not create task ':app:compileDebugAndroidTestKotlin'.
     > Cannot use @TaskAction annotation on method AbstractKotlinCompile.execute() because interface org.gradle.api.tasks.incremental.IncrementalTaskInputs is not a valid parameter to an action method.
  > KotlinJvmAndroidCompilation with name 'debugAndroidTest' not found.

My assumption was that I would need to update a few supporting components, like gradle, and then I'd be up and running. Time to test the hypothesis...

Android Gradle Plugin Upgrade

Guidance online indicated that I should upgrade Gradle, so I ran the AGP Upgrade Assistant...

This is available at Tools -> AGP Upgrade Assistant...

The tool recommended that I update the Android Gradle Plugin from 4.2.2 to 7.4.2. I also checked the box to include the Recommended post-upgrade steps:

I didn't see guidance online to check the 'Recommended' checkbox, but I did so anyway to hopefully save time. Execution of this step took about 5 minutes, which felt excessively long for such a simple project (2 activities total) on my i9-10885H.

The AGP Upgrade assistant indicated that **Sync succeeded** :

Build, Troubleshoot, Fix, Repeat

Round 1

With the Android Gradle Plugin upgrade and 'recommended post-upgrade steps' completed, an attempt was made to 'build' the project. This resulted in a few errors:

Initial set of build errors:

  • The 'kotlin-android-extensions' Gradle plugin is deprecated. Please use this migration guide (https://goo.gle/kotlin-android-extensions-deprecation) to start working with View Binding (https://developer.android.com/topic/libraries/view-binding) and the 'kotlin-parcelize' plugin.
  • /app/src/main/AndroidManifest.xml:14:9-23:20 Error: android:exported needs to be explicitly specified for element <activity#com.s7thzero.psms.MainActivity>. Apps targeting Android 12 and higher are required to specify an explicit value for **android:exported** when the corresponding component has an intent filter defined. See https://developer.android.com/guide/topics/manifest/activity-element#exported for details.
  • Manifest merger failed with multiple errors, see logs

Examining the documentation supplied in the error message lead me to examine the AndroidManifest.xml file referenced in the error. I can see that the xml indicates an error in the .MainActivity, so it seems likely that the new 'exported' property needs to be specified here:

Altering the file to include an 'exported' property set to "true" seems to clear up the error. Here's what it looks like with the property addition:

Round 2

Rebuilding the application resulted in a few new errors:

Errors, round 2:

  • AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/home/rion/src/android/pSMS-old/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml","position":{"startLine":591}}],"original":"ERROR:/home/rion/src/android/pSMS-old/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml:592: AAPT: error: resource color/colorPrimary (aka com.s7thzero.psms:color/colorPrimary) not found.\n ","tool":"AAPT"}
  • AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/home/rion/src/android/pSMS-old/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml","position":{"startLine":592}}],"original":"ERROR:/home/rion/src/android/pSMS-old/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml:593: AAPT: error: resource color/colorPrimaryDark (aka com.s7thzero.psms:color/colorPrimaryDark) not found.\n ","tool":"AAPT"}
  • AGPBI: {"kind":"error","text":"Android resource linking failed","sources":[{"file":"/home/rion/src/android/pSMS-old/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml","position":{"startLine":593}}],"original":"ERROR:/home/rion/src/android/pSMS-old/app/build/intermediates/incremental/debug/mergeDebugResources/merged.dir/values/values.xml:594: AAPT: error: resource color/colorAccent (aka com.s7thzero.psms:color/colorAccent) not found.\n ","tool":"AAPT"}

The same errors are repeated a few times, all centering around missing xml values:

  • error: resource color/colorPrimary (aka com.s7thzero.psms:color/colorPrimary) not found
  • error: resource color/colorPrimaryDark (aka com.s7thzero.psms:color/colorPrimaryDark) not found
  • error: resource color/colorAccent (aka com.s7thzero.psms:color/colorAccent) not found

After poking around online trying to refresh my memory on how the **values.xml** file gets built, I fumbled my way into the app/src/main/res/values/styles.xml file. Opening this file in the Android Studio editor view showed me a few places where colors weren't able to be referenced:

As for 'where' these values should be defined... I found out by creating a new 'empty' android studio project and checking the default xml files stored under the /app/src/main/res/values folder. Looks like there's one called colors.xml so I copy/pasted it into my old project and rebuilt.

Contents of the colors.xml file:

<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="colorPrimary">#008577</color>
    <color name="colorPrimaryDark">#00574B</color>
    <color name="colorAccent">#D81B60</color>
</resources>

This cleared up the error indicators in styles.xml:

Round 3

Building the project again - this time it seems to work! Running the apk in emulator functioned as expected so it looks like the migration process is complete... or is it?

Migrate Away From Deprecated Libraries

Looking back over the error messages I encountered while updating this project, I remembered this one:

It appears that if I want my app to be truly updated that there is more work for me to do! Looking at the first link it says:

Kotlin Android Extensions is deprecated, which means that using Kotlin synthetics for view binding is no longer supported. If your app uses Kotlin synthetics for view binding, use this guide to migrate to Jetpack view binding.

Change 1: Adjust Gradle

My app definitely made use of Kotlin synthetics- what needs to be changed?:

  • app/build.gradle needs to be adjusted to:
    • set viewBinding = true
    • remove kotlin-android-extensions (if **Parcelable** features aren't used... which I don't think I am?)

This is what the relevant changes look like to the app/build.gradle file:

Building the project at this point results in a bunch of errors. For brevity, here's the text:

  • e: /home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt: (11, 8): Unresolved reference: kotlinx
  • e: /home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt: (62, 9): Unresolved reference: smsLinearLayout
  • e: /home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt: (72, 29): Unresolved reference: toolbar
  • e: /home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt: (100, 9): Unresolved reference: fab
  • e: /home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt: (100, 34): Cannot infer a type for this parameter. Please specify it explicitly.

I edited my kotlin files to comment out the 'synthetic' imports and 'android.support.*' references so they look more like this:

At the same time I imported a missing class AppCompatActivity via an IDE tool tip:

Rebuilding resulted in errors like this:

  • e: /home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt: (6, 36): Unresolved reference: snackbar
  • e: /home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt: (8, 17): Unresolved reference: appcompat

Looks like the com.android.support:design, com.android.support:appcompat-v7 dependencies are deprecated and needs to be replaced with com.google.android.material:material like this in the app gradle 'dependencies' section:

Rebuilding again shows this error:

> Task :app:processDebugMainManifest FAILED
[com.android.support:animated-vector-drawable:28.0.0] /home/rion/.gradle/caches/transforms-3/845717d8109af35e1b4fcfc3b9cf5cb7/transformed/animated-vector-drawable-28.0.0/AndroidManifest.xml Warning:
    Namespace 'android.support.graphics.drawable' used in: com.android.support:animated-vector-drawable:28.0.0, com.android.support:support-vector-drawable:28.0.0.
[com.android.support:versionedparcelable:28.0.0] /home/rion/.gradle/caches/transforms-3/b874e29f357a492ef29a4f711929b955/transformed/versionedparcelable-28.0.0/AndroidManifest.xml Warning:
    Namespace 'androidx.versionedparcelable' used in: com.android.support:versionedparcelable:28.0.0, androidx.versionedparcelable:versionedparcelable:1.1.0.
/home/rion/src/android/pSMS-old/app/src/main/AndroidManifest.xml:22:18-91 Error:
    Attribute application@appComponentFactory value=(android.support.v4.app.CoreComponentFactory) from [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91
    is also present at [androidx.core:core:1.1.0] AndroidManifest.xml:24:18-86 value=(androidx.core.app.CoreComponentFactory).
    Suggestion: add 'tools:replace="android:appComponentFactory"' to <application> element at AndroidManifest.xml:5:5-25:19 to override.

See https://developer.android.com/r/studio-ui/build/manifest-merger for more information about the manifest merger.

Doing a Clean and Rebuild solved the above error

Now I see:

  • Configuration :app:debugRuntimeClasspath contains AndroidX dependencies, but the android.useAndroidX property is not enabled, which may cause runtime issues.
    Set android.useAndroidX=true in the gradle.properties file and retry.

Easy enough to address by modifying gradle.properties and adding a property:

Change 2: AndroidManifest.xml

Rebuilding now shows me this error:

  • Error:
    Attribute application@appComponentFactory value=(androidx.core.app.CoreComponentFactory) from [androidx.core:core:1.1.0] AndroidManifest.xml:24:18-86
    is also present at [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91 value=(android.support.v4.app.CoreComponentFactory).
    Suggestion: add 'tools:replace="android:appComponentFactory"' to element at AndroidManifest.xml:5:5-25:19 to override.

I edited my 'application' entry in main/AndroidManifest.xml to include tools:replace="android:appComponentFactory" (and also include xmlns:tools="http://schemas.android.com/tools" in the manifest xml entry) like this:

Now when I rebuild I see this error:

  • Error:
    tools:replace specified at line:6 for attribute android:appComponentFactory, but no new value specified

This is puzzling as I put in the line suggested by the previous error... what else is needed? Looks like I need to pull out these new XML entries (thanks https://stackoverflow.com/a/53277062/1076507 for the tip!) and I had to remove a conflicting import line from one of my activities (didn't full comment out the old android.support.v7.app.AppCompatActivity lines, apparently...

Rebuilding results in this error:

  • Error:
    Attribute application@appComponentFactory value=(androidx.core.app.CoreComponentFactory) from [androidx.core:core:1.1.0] AndroidManifest.xml:24:18-86
    is also present at [com.android.support:support-compat:28.0.0] AndroidManifest.xml:22:18-91 value=(android.support.v4.app.CoreComponentFactory).
    Suggestion: add 'tools:replace="android:appComponentFactory"' to element at AndroidManifest.xml:5:5-25:19 to override.
  • Manifest merger failed with multiple errors, see logs

After digging around, I eventually found that my layout XMLs (main/res/layout/*.xml) had to be updated to support newer reference types. I had to move from:

  • android.support.design.widget.AppBarLayout
  • android.support.v7.widget.Toolbar
  • android.support.design.widget.FloatingActionButton

To:

  • com.google.android.material.appbar.AppBarLayout
  • androidx.appcompat.widget.Toolbar
  • com.google.android.material.floatingactionbutton.FloatingActionButton

In pictures - OLD:

NEW:

The errors were of no help figuring this out whatsoever. Very frustrating and time consuming! Also, this didn't solve my problem.

Change 3: Re-run the AGP Upgrade tool

Looks like The upgrade to 7.4.2 might not have been enough, so I ran through the upgrade tool again to get to version 8.6.0 (which appears to have been successful:

On build I found an error like this:

  • "Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.8.22, expected version is 1.6.21"

To get around this I:

  • Changed build.gradle ext.kotlin_version to equal 1.8.22

On rebuild I found this error:

  • Execution failed for task ':app:compileDebugKotlin'.

'compileDebugJavaWithJavac' task (current target is 1.8) and 'compileDebugKotlin' task (current target is 17) jvm target compatibility should be set to the same Java version.
Consider using JVM toolchain: https://kotl.in/gradle/jvm/toolchain

To fix this error, I set this option in the App build.gradle:

    kotlinOptions{
        jvmTarget = "1.8"
    }

See:

Rebuilding I see these errors:

  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:34:12 Unresolved reference: minLines
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:35:12 Unresolved reference: maxLines
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:36:12 Unresolved reference: textSize
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:62:12 Unresolved reference: text
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:64:12 Unresolved reference: setOnClickListener
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:64:31 Cannot infer a type for this parameter. Please specify it explicitly.
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:66:25 Type mismatch: inferred type is TextViewWithContext but View was expected
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:70:33 Type mismatch: inferred type is TextViewWithContext but View! was expected
  • e: file:///home/rion/src/android/pSMS-old/app/src/main/java/com/s7thzero/psms/MainActivity.kt:119:36 Unresolved reference: text

This is another example where the error message points me to where I need to go 'indirectly', as the issue isn't in the MainView, it's in the TextView component I had setup... I missed another androidx import:

  • androidx.appcompat.widget.AppCompatTextView

Rebuilding again I found these errors:

  • error: package android.support.design.widget does not exist
    import android.support.design.widget.CoordinatorLayout;
  • error: cannot find symbol
    private final CoordinatorLayout rootView;
    ^

Which were addressed by opening up the res/layout/activity_main.xml file again and doing another androidx conversion

From:

  • android.support.design.widget.CoordinatorLayout

To:

  • androidx.coordinatorlayout.widget.CoordinatorLayout

Rebuilding again, I see a similar set of messages:

  • error: package android.support.constraint does not exist
    import android.support.constraint.ConstraintLayout;

Editing my res/layout/activity_reply.xml file addressed the issue:

From:

  • android.support.constraint.ConstraintLayout

To:

  • androidx.constraintlayout.widget.ConstraintLayout

Change 4: Refactor Synthetics

Since that seems to be going in circles, I addressed the kotlin errors in my code related to migrating away from synthetics. I was able to do this before:

  • smsLinearLayout.addView(tv)

But now I have to do this:

  • val smsLinearLayout = findViewById(R.id.smsLinearLayout)
  • smsLinearLayout.addView(tv)

See:

Without Synthetics I have to be more 'verbose'

End State

I've (finally) successfully migrated my old android app so it compiles and runs in the latest Android Studio. In addition, I've migrated away from the 'synthetic' views and 'old' way of doing things and integated with 'androidx'. I can only hope that the next 5 years will find a more smooth experience when I need to update & rebuild again!