AndroidX migrate dependency / libraries - android

I have successfully migrated my project to AndroidX. App is running perfectly, but I am getting compile time errors, because my dependencies use support package.
Reason of this error
Because PhotoView is a dependency class, which uses android.support.v7.widget.AppCompatImageView which is no more available in my project. Because it is now androidx.appcompat.widget.AppCompatImageView
Project still run?
Yes, android.enableJetifier convert this dependency to AndroidX at runtime, but I want to get rid of compile time errors.
Is there a quick fix for now?

If you depend on a library that references the older Support Library, Android Studio will update that library to reference androidx instead via dependency translation. Dependency translation is automatically applied by the Android Gradle Plugin 3.2.0-alpha14, which rewrites bytecode and resources of JAR and AAR dependencies (and transitive dependencies) to reference the new androidx-packaged classes and artifacts. We will also provide a standalone translation tool as a JAR.
I see (using ./gradlew app:dependencies) that rxbinding's design dependency is updated to the new com.google.android.material dependency. Passing com.google.android.material.snackbar.Snackbar to a library function that references android.support.design.widget.Snackbar themselves makes Android Studio show a compiler error, but actually compiling and running the app works. I assume AS can't really handle these changes yet.
It seems there are some caching issues, removing .idea/libraries and performing a Gradle sync makes the errors disappear.

I solved this issue by deleting .idea folder and syncing project again.
This seems a bug of IDE not Jetifier, it does not re-sync dependencies after migrating.
Jetifier does its work well. It converts all dependencies support libraries into androidx at building time. See #this post for good explaination.

My fix for this was converting the library with the compile time error to AndroidX and submitting a pull request to the library.

Related

AndroidX Jetifier unable/failed to transform 3rd-party transitive dependency that still use Support Library

I've recently migrated my project to use AndroidX
My apps crashes, after I migrate to AndroidX, due to library still using Support Library. Here's a list of my 3rd-party dependencies/library, that failed to transform into AndroidX:
com.clevertap.android:clevertap-android-sdk:3.4.2
com.readystatesoftware.chuck:library:1.1.0
com.ncapdevi:frag-nav:2.4.0
jp.wasabeef:recyclerview-animators:2.3.0
com.github.chivorns:smartmaterialspinner:1.1.6
com.facebook.android:facebook-android-sdk:5.0.1
com.github.PierfrancescoSoffritti:AndroidYouTubePlayer:7.0.1 (I still cannot upgrade it to 10.x.x, because major API changes)
com.github.nikartm:image-support:1.0.5
My Setups:
AS & AGP: 3.6.2
targetSdk: 29
minSdk: 16
Data & View Binding: Both enabled
Gradle DSL: Kotlin
Gradle: gradle-6.0.1-all
What I've done so far:
Using Refactor -> Migrate to AndroidX tools from Android Studio, but ended-up force close it, because takes a long time
android.enableJetifier=true & android.useAndroidX=true
Using the shell scripts to manually mapping artifact, class and imports from Support Library to AndroidX, thanks #Danlew, also #Danlew mentioned in ADS '19 talks here
Already checked my :app:dependencies that 3rd-party dependencies already migrated to use AndroidX artifacts, but only a few of them (failed for the above dependencies list)
Deleting ./root_project/.idea, ./root_project/.gradle & ~/.gradle/caches (to fix compile-error/IDE error, references: AndroidX migrate dependency / libraries
Understanding the jetifier: What is Jetifier? & official android docs
Did a workaround to use AndroidX for annotation processor like: Glide & Dagger
Checking the ~/.gradle directories for the jetified-* libs the jetified aar exist, unfortunately it's failed for clevertap & others libs listed above.
My conclusions, the jetifier works by rewriting the binary .class of our 3rd-party library if Support Library imports/class detected, and modify (jetified/mapping it) into AndroidX respectively.
But in my case, the dependencies listed above doesn't use correct AndroidX imports and resulting runtime crash, due to having a transitive dependent for Support Library.
Does jetifier currently doesn't support transitive dependency inside 3rd-party library as well? But, strangely it works for a few library (unlisted from above)
[UPDATED 1]
In the meantime (quickfix):
I did downloading all the transitive dependencies of the libraries exhaustively one-by-one
Using jetifier-standalone commands instead for the libraries aar
Manually adding the libraries aar and its dependencies to app/build.gradle.kts as flatDirs
Is this really a workaround, is there anything better I can do?
[UPDATED 2]
I've using a maintained version of chuck as well. But found this same issue as well:
cannot generate view binders com.sun.tools.javac.code.Symbol$CompletionFailure: class file for android.support.v7.widget.AppCompatImageView not found
After checking my 3rd-party libs, I also ended-up manually adding the aar after I use jetifier-standalone for this library:
com.clevertap.android:clevertap-android-sdk:3.4.2
com.github.nikartm:image-support:1.0.5
Many also recommends to use api instead of implementation but for me, I don't want to bloated my project with transitive dependency
In other SO also recommends below:
either remove the library,
forked it to support androidx / waiting for the author to upgrade it
manually using jetifier-standalone for those specicif libs, and include as local aar (this is my best approach, right now)
Unless the jetifier able to state this into official documentation, for its limitation: https://developer.android.com/jetpack/androidx/releases/jetifier
Seems like there's the least we can do, and hope, many of the 3rd-party authors will upgrade to AndroidX soon.
Here's a bonus article for references:
You can use can-i-drop-jetifier libs to detects does your libs (transitively) needs jetifier enabled or not
The time is right to migrate to AndroidX with this baby-steps
Better structure packaging with AndroidX and also a headache along the way
Turns out my current workaround was using this approach: https://github.com/bumptech/glide/issues/3080#issuecomment-495430590
Magical regex to turns a blacklist into a whiteliset
android.jetifier.blacklist=^(?!.*[\\\\/](com\\.github\\.bumptech\\.glide|com\\.clevertap\\.android|com\\.facebook\\.android|com\\.github\\.nikartm|com\\.github\\.PierfrancescoSoffritti|com\\.github\\.prolificinteractive)[\\\\/]).*$
If NoClassDef exceptions thrown, then I add the library package name into the android.jetifier.blacklist to whitelisted them.
In the above cases, I'm trying to whitelist:
glide
clevertap
nikartm
facebook-sdk
YoutubeAndroidPlayer (v7) still not using v10
prolificinteractive

Undo migration to AndroidX

I've refactored my Android Studio codebase to AndroidX successfully. But it is causing a few problems with some of my libraries.
I need to revert it since the app is going into production soon. How can I do it?
I had gone through the same, Follow the steps to undo the AndroidX Migration:
Remove following lines in gradle.properties:
android.enableJetifier=true
android.useAndroidX=true
Remove AndroidX dependencies in build.gradle of your app and replace them with their equivalent Non AndroidX dependencies:
e.g.
implementation 'androidx.core:core:1.0.0-beta01'
implementation 'androidx.appcompat:appcompat:1.0.0-beta01'
Sync Project with Gradle Files
After syncing you may have import errors in java files, you can remove the androidx imports and re add the equivalent non androidx imports
I hope it will help everyone facing migration rollback problem. If you get any conflict issues while performing above steps in Android Studio, try to clean and rebuild the project.
You can simply choose Migrate App to appCompat from Refactor menu in Android Studio.
Also, don't forget to delete these lines from gradle.properties:
android.useAndroidX=true
android.enableJetifier=true
I couldn't simply roll back in version control, because the app I wanted to roll back was androidx from its initial commit, but I was tasked with integrating the app module into a larger project without androidx.
Here's what I did:
Try syncing gradle and inevitably you'll get some kind of error. Here is the first error I saw:
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)
Take note of the androidx package in the above error.
Run gradlew dependencies inside the module you're trying to migrate back.
Search the output for the androidx package mentioned in the above error. Figure out which of your dependencies from your build.gradle file is bringing in that package, then revert that package to its equivalent support library mapping.
Repeat steps 1-4 until Gradle sync finishes successfully.
Now you need to search all your .java files for androidx and replace each import statement with its support library package name. Tip for this step: turn on "Add unambiguous imports on the fly" in Android Studio preferences and just delete all the androidx imports. Most of them will auto-repopulate with the correct support packages.
Now your project should build successfully, but you'll likely run into runtime crashes due to androidx view components used in layout files.
Search all xml files for androidx and com.google.android.material, and replace each view with its support equivalent name.
Don't forget to fix any compilation issues in your tests, and re-run them to make sure they still all pass.
Do a hard reset on repository which was working before migration to android x.
Delete the node_modules folder, and type npm install.

Library not adding its dependencies when used

I made a library, but when I tried to use it with implementation 'com.example:mylibrary:1.3.0' in my app's build.gradle, I keep getting an error saying the ConstraintLayout dependency (which the library uses but not the app) is not found. However it was explicitly defined in the library's build.gradle with implementation.
When I ran gradlew app:dependencies on the terminal, it shows that the library has no dependencies, even though it actually has 2. This seems to be the source of the problem, Gradle can't detect the dependencies of the library.
I didn't run into this problem for a while but when I decided to remove the ConstraintLayout dependency from my app an error appears during build.
When you're using implementation for the dependencies in your library, the project which is dependent with it will not see the dependencies. You need to use api instead of implementation.

Android Studio 3 and Gradle 4.3 -> Library modules no longer process local JARs -> how to handle this?

Upgrade to Android Studio 3.0.0 mentions this, and doesn't elaborate on how to handle it:
Library modules no longer process local JARs. This is to speed up incremental builds that are caused by changes to a library module's code.
So I have a project with a library project in it. In my library project's build.gradle file I have this:
compile files('libs/com.somelib.somepackage.jar')
I changed compile to implementation and when I tried to run my app, all my classes that tried to access the import com.somelib.somepackage.SomeClass import statement threw an error that this package didnt exist.
I changed back to compile and I was able to build and run my app.
I want to comply to the new rules since compile is deprecated and will be removed with the next Gradle release, so how do I go about doing that?
If you are trying to access classes from the .jar that is included in the library project from the app project, you will have to use api instead of implementation otherwise the classes will only be accessible in the library project:
implementation files('libs/com.somelib.somepackage.jar')
should be
api files('libs/com.somelib/somepackage.jar')
As said by the documentation:
... When a module includes an api dependency, it's letting Gradle know
that the module wants to transitively export that dependency to other
modules, so that it's available to them at both runtime and compile
time ...
Reference:
https://developer.android.com/studio/build/gradle-plugin-3-0-0-migration.html#new_configurations

How to use forked git project in Android Studio

I am switching from Eclipse to Android Studio. I have couple of 3rd party libraries that I have added features or modified a little bit. Since the libraries in Eclipse are also projects and we can access the code, I had no problem.
In Android Studio compile tag in dependencies is great but in my case I cannot use it unfortunately.
I fork the project and made necessary changes and add the project as a module in Android Studio. Since the library project already has settings.gradle and example and library modules, there is a mess in my project and it does not compile at all.
Has anybody experienced such a problem? What to do and what is the correct way to forked libraries?
What we've done in my project is create gradle scripts for our dependencies that don't have them, and modify the gradle scripts for dependencies that do have them. Gradle does not play very well with modular dependencies, unfortunately: Each sub-project must know its place in the larger overall project. Since you've already forked the github project, modifying it further shouldn't be a problem.

Categories

Resources