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
- Manage manifest files [developer.android.com]
- App manifest file - [developer.android.com]
- Can't find android.support.design.widget.Snackbar in support design library [stackoverflow.com]
- Tools: replace not replacing in Android manifest [stackoverflow.com]
- Android X: tools:replace specified at line: for attribute, but no new value specified [stackoverflow.com]
- "Module was compiled with an incompatible version of Kotlin. The binary version of its metadata is 1.5.1, expected version is 1.1.16" [stackoverflow.com]
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.- See https://developer.android.com/r/studio-ui/build/manifest-merger for more information about the manifest merger.
- 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:
- 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.
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 theandroid.useAndroidX
property is not enabled, which may cause runtime issues.
Setandroid.useAndroidX=true
in thegradle.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!