I've created a library to be released as an aar. In this library I'm using Facebook Stetho so in my library dependencies I'm using:
compile "com.facebook.stetho:stetho:1.4.1"
I've also added the following lines to my library proguard file:
-keep class com.facebook.stetho.** { *; }
-dontwarn com.facebook.stetho.**
After the aar is generated I'm incorporating it on a app using Android Studio File -> New Module -> Import .JAR/.AAR so
compile project(':MyTestProject')
Is added to the app build.gradle file.
When I run the app, the app crashes with the log
java.lang.NoClassDefFoundError: Failed resolution of: Lcom/facebook/stetho/Stetho;
....
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.facebook.stetho.Stetho" on path:.....
If I add the compile "com.facebook.stetho:stetho:1.4.1" dependency to the app build.gradle is working as expected.
Any idea why?
Related
I've created a project with one module. e.g
app
module
When I'm using the following code in the app's build.gradle, It's working fine
implementation project(':module')
When I'm creating .aar for module with minifyEnabled true and using it in build.gradle using bellow code
implementation files('module-release.aar')
It gives the following error
Caused by: java.lang.ClassCastException: com.mypackage.DaggerMainApplication_HiltComponents_ApplicationC$ActivityRetainedCImpl$ActivityCImpl cannot be cast to com.com.mypackage.MyActivity_GeneratedInjector
I am having an external library (constants.aar) file. I have kept this .aar file in to my Android library module project's (sdk-module)/lib folder. This sdk-module has classes which uses methods from constants.aar.
Compiling the sdk-module generates sdk-module.aar file.
In my application i am including this sdk-module.aar file. When i am trying to use certain class files of sdk-module, i am getting NoClassDefFoundError.
java.lang.NoClassDefFoundError: Failed resolution of: "class file from constant.aar";
Caused by: java.lang.ClassNotFoundException: Didn't find class "xyz" on path:
I have unzipped the sdk-module.aar file and i can see that constants.aar file is available in its /lib folder.
How to resolve this issue?
android {
defaultConfig {
....
multiDexEnabled true // Add this line in your build.gradle file
}
dependencies {
implementation 'com.android.support:multidex:1.0.3'
}
Extend : MultiDexApplication Class In in your ApplicationClass.java
public class BusinessCardApplication extends MultiDexApplication { ... }
OR
MultiDex.install(this); //add this line
Either, See this library's Issues File. If It Is from library's issue there is also define this error detail
I am migrating my Android project to Gradle 4.4 and Android Gradle plugin 3.1.2.
It has a library module which depends on parceler library and defines its dependency as follows:
build.gradle of library module:
...
// parceler for serialization (https://github.com/johncarl81/parceler)
implementation "org.parceler:parceler-api:1.0.4"
annotationProcessor "org.parceler:parceler:1.0.4"
...
This seems to compile well and generates my aar file.
Further, my main app module also has a direct dependency on parceler module and contains above lines as dependencies in its build.gradle, along with above aar file.
build.gradle of main app module:
...
api(group: 'com.example.mylibrary', name: 'mylibrary', version: "1.0.7", ext: 'aar') {
transitive = true;
changing = true
}
// parceler for serialization (https://github.com/johncarl81/parceler)
implementation "org.parceler:parceler-api:1.0.4"
annotationProcessor "org.parceler:parceler:1.0.4"
...
Everything works until I try to generate my APK, which fails with the following error.
D8: Program type already present: org.parceler.Parceler$$Parcels$1
Task :MPCApp:transformDexArchiveWithDexMergerForRelease FAILED
When I expand my library project in Android studio, I see Parcels.class under org.parceler package. But it seems similar file is also generated by main app module under the same package which is causing the clash.
Upgrade to the latest (currently 1.1.10) - We got rid of the Parcels generated class.
I'm updating our project to use Gradle 4.1 and Android Gradle plugin 3.0.1. I have updated our dependency configuration to the new configuration and the project successfully compiles. However, there are lots of unresolved dependencies (incl. Kotlin standard library's top-level functions) when compiling android tests (assembleAndroidTest Gradle task). I was suspecting that Proguard might cause this (although it didn't before updating Gradle), but even adding explicit rules to keep symbols/classes doesn't help. We use Kotlin 1.2.10 and Kotlin-Kapt plugin.
I appreciate any help.
I don't use ProGuard for debug but the following answers seem useful.
I would revise your Gradle configuration another time following the migration guide, and first of all clean and invalidate caches.
Proguard
Chech this question and answers about how to use Kotlin with Proguard.
Disable these directives in your build.gradle file to discard Proguard.
minifyEnabled false
shrinkResources false
Configure Proguard for Kotlin.
You don't need to do anything special. Kotlin works with ProGuard out
of the box. But you may face some strange errors when processing your
application with ProGuard. In this case just add:
-dontwarn kotlin.**
You also can add:
-keep class kotlin.** { *; }
-keep class kotlin.Metadata { *; }
-dontwarn kotlin.**
-keepclassmembers class **$WhenMappings {
<fields>;
}
-keepclassmembers class kotlin.Metadata {
public <methods>;
}
-assumenosideeffects class kotlin.jvm.internal.Intrinsics {
static void checkParameterIsNotNull(java.lang.Object, java.lang.String);
}
Check this related questions to either enable Proguard for tests or not:
proguard gradle debug build but not the tests
Specify the Proguard file to use on the instrumentation tests.
runProguard is old. It was replaced with minifyEnabled
With minifyEnabled (and other changes in new versions of Gradle) you
will may encounter issues where the Proguard config works for your
debug apk but not for the instrumentation tests. The apk created for
instrumentation tests will use its own proguard file, so changing your
existing proguard file will have no effect.
In this case, you need to specify the proguard file to use on the
instrumentation tests. It can be quite permissive because it's not
affecting your debug and release builds at all.
// inside android block
debug {
shrinkResources true // removes unused graphics etc
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
testProguardFile('test-proguard-rules.pro')
}
Android Unit Tests with proguard enabled
Add a custom proguard rules file
/project/app/proguard-test-rules.pro
# Proguard rules that are applied to your test apk/code.
-ignorewarnings
-keepattributes *Annotation*
-dontnote junit.framework.**
-dontnote junit.runner.**
-dontwarn android.test.**
-dontwarn android.support.test.**
-dontwarn org.junit.**
-dontwarn org.hamcrest.**
-dontwarn com.squareup.javawriter.JavaWriter
# Uncomment this if you use Mockito
#-dontwarn org.mockito.**
The add the following to your build.gradle for your app. To use the proguard file when testing.
/project/app/build.gradle
android {
debug {
minifyEnabled true
testProguardFile 'proguard-test-rules.pro'
}
}
Add a buidType for testing
I've solved this problem in my build by having an additional "dev"
buildType where I enable proguard, but configure it to keep all code
in my own package, and a few specific library classes that happen to
be used from tests only. I also disable obfuscation in the dev
buildType so that it can be debugged from an IDE.
For debug and release builds I use my "real" proguard settings
including obfuscation and optimizations.
Use separate test modules
Separate test modules are now variant-aware. This means that
specifying targetVariant is no longer necessary.
Each variant in the test module will attempt to test a matching
variant in the target project. By default, test modules contain only a
debug variant, but you can create new build types and new flavors to
create new variants to match the tested app project. A connectedCheck
task is created for each variant.
To make the test module test a different build type only, and not the
debug one, use VariantFilter to disable the debug variant in the test
project, as shown below:
android {
variantFilter { variant ->
if (variant.buildType.name.equals('debug')) {
variant.setIgnore(true);
}
}
}
If you want a test module to target only certain flavors or build
types of an app, you can use the matchingFallbacks property to target
only the variants you want to test. This also prevents the test module
from having to configure those variants for itself.
Gradle
Revise your Gradle configuration. In order to to build an Android project written in Kotlin:
Set up the kotlin-android gradle plugin and apply it to your project.
Add kotlin-stdlib dependencies.
Those actions may also be performed automatically in IntelliJ IDEA /
AS by invoking the action:
Tools | Kotlin | Configure Kotlin in Project
kotlin-android
buildscript {
ext.kotlin_version = '1.2.10'
...
dependencies {
classpath "org.jetbrains.kotlin:kotlin-gradle-plugin:$kotlin_version"
}
}
apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
kotlin-stdlib
Don't forget to configure the standard library dependency:
repositories {
mavenCentral()
}
dependencies {
compile "org.jetbrains.kotlin:kotlin-stdlib"
}
Revise your dependencies configuration using the migration
guide.
Note: compile, provided, and apk are currently still available.
However, they will be removed in the next major release of
the Android plugin.
Provide version manually
Starting with Kotlin 1.1.2, the dependencies with group
org.jetbrains.kotlin are by default resolved with the version taken
from the applied plugin.
You can provide the version manually using the full dependency
notation like this:
compile "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
Resolution strategy
You also can force the resolution strategy:
configurations.all {
resolutionStrategy {
force "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
}
}
As you are using Android Gradle plugin 3.0.1:
// Instead, because the new build model delays dependency resolution, you
// should query and modify the resolution strategy using the Variant API:
android {
applicationVariants.all { variant ->
variant.getCompileConfiguration().resolutionStrategy {
...
}
variant.runtimeConfiguration.resolutionStrategy {
...
}
variant.getAnnotationProcessorConfiguration().resolutionStrategy {
...
}
}
}
Exclude app dependencies from test configurations using the Variant API:
On previous versions of the Android plugin, you could exclude certain
transitive dependencies of your app from your tests using the exclude
keyword. However, with the new dependency configurations, you must do
it at execution time using the Variant API:
android.testVariants.all { variant ->
variant.getCompileConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
variant.getRuntimeConfiguration().exclude group: 'com.jakewharton.threetenabp', module: 'threetenabp'
}
Extended versions of the Kotlin standard library
If you're targeting JDK 7 or JDK 8, you can use extended versions of
the Kotlin standard library which contain additional extension
functions for APIs added in new JDK versions. Instead of
kotlin-stdlib, use one of the following dependencies:
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk7"
compile "org.jetbrains.kotlin:kotlin-stdlib-jdk8"
In Kotlin 1.1.x, use kotlin-stdlib-jre7 and kotlin-stdlib-jre8
instead.
Kotlin reflection
If your project uses Kotlin
reflection
or testing facilities, you need to add the corresponding dependencies
as well:
compile "org.jetbrains.kotlin:kotlin-reflect"
testCompile "org.jetbrains.kotlin:kotlin-test"
testCompile "org.jetbrains.kotlin:kotlin-test-junit"
Kapt
See the description of Kotlin annotation processing tool (kapt).
Apply the kotlin-kapt Gradle plugin:
apply plugin: 'kotlin-kapt'
I have an Android project, inside I have a library module, my project works fine, compile the project I get the .aar included in a test project and everything ok.
Now,I have added in my library module a Activity that extends Application, Y Added this class in the manifiest.xml of the library
<application
android:allowBackup="true"
android:label="#string/app_name"
android:name=".MyActivityExtendsApplications"
When I test the project it works perfect, but when I take the .aar and test it on other project fails. The problem is that it does not find the activity extend Application ... I have decompiled the aar and I see that everything is correct, all class are inside the folder
The error is
Caused by: java.lang.ClassNotFoundException: Didn't find class "com.mylibrary.MyActivityExtendsApplications" on path: DexPathList[[zip file "/data/app/com.myapplication-1/base.apk"],nativeLibraryDirectories=[/data/app/com.myapplication-1/lib/arm, /vendor/lib, /system/lib]]
Suppressed: java.lang.ClassNotFoundException: com.mylibrary.MyActivityExtendsApplications
at java.lang.Class.classForName(Native Method)
at java.lang.BootClassLoader.findClass(ClassLoader.java:781)
at java.lang.BootClassLoader.loadClass(ClassLoader.java:841)
at java.lang.ClassLoader.loadClass(ClassLoader.java:504)
... 12 more
Caused by: java.lang.NoClassDefFoundError: Class not found using the boot class loader; no stack trace available
I adding grandle dependency to library .aar In all cases in the same way
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
androidTestCompile('com.android.support.test.espresso:espresso-core:2.2.2', {
exclude group: 'com.android.support', module: 'support-annotations'
})
compile 'com.android.support:appcompat-v7:24.2.1'
compile 'com.android.support:design:24.2.1'
testCompile 'junit:junit:4.12'
compile 'mylibrary-debug.mylibrary-debug#aar'
}
repositories{
flatDir{
dirs 'libs'
}
}
I check merged manifest in my test Project and the activity is there
application
android:name="com.mylibrary.MyActivityExtendsApplications"
android:allowBackup="true"
And I can import this Activity in my test Project and see the code
And I added mylibrary in libs folder.
When I remove the activity MyActivityExtendsApplications, my library works fine.
The issue may be the the Android Beacon Library aar files are missing when you generate your library aar, and the exception description is simply misleading. I don't think classes from aar files are automatically merged when generating a new aar file. You might check to see if these files (like Beacon.class) are missing from your aar.
If this is indeed the problem, there are two possible solutions:
In your application, reference both your library aar file and the Android Beacon Library aar file.
Merge the classes from the first aar file into your new aar file. I have done this before with rather a rather inelegant shell script that I am happy to share, but there may be a better way to accomplish the same thing.