Parceler class not generating error in Android - android

I have a core branch where following dependencies is decalared
implementation "org.parceler:parceler-api:$rootProject.ext.parcelVersion"
annotationProcessor "org.parceler:parceler:$rootProject.ext.parcelVersion"
I am declaring a dependency in one of my library module as below
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation project(':core')
}
Here is the class that I will be parceling in my activity
#Parcel(parcelsIndex = false)
public class MyClass {
#SerializedName("validation")
public String myField;
}
Exception is thrown at the third line.
MyClass myClass = new MyClass();
myClass.myField = "bjbskas";
Parcelable parcelable =Parcels.wrap(myClass);
Exception reads as shown below
Unable to find generated Parcelable class for com.example.mylibrary.MyClass,
verify that your class is configured properly and that the Parcelable class
com.example.mylibrary.MyClass$$Parcelable is generated by Parceler.
If I try putting the parceler library in my library module directly, it gives me another error called
Program type already present: org.parceler.Parceler$$Parcels$1

Changing the version of Parceler library from 1.0.4 to 1.1.10 solved the problem. I don't know what is the reason behind this but I guess it may be because of some transitive dependencies using version 1.1.10

Related

Android Studio dependencies of module not visible in other module

I have a module called "Common" as library, this module has few dependencies like: com.badlogicgames.gdx, com.squareup.wire etc. And it works fine, I use them inside of this module.
And I have another module called "Tracking", where in the gradle I have:
dependencies {
compile project(':Common')
}
And if I try there to import any public class of module "Common", it works fine, but if I try to import any class of library com.badlogicgames.gdxor com.squareup.wire, it says me "Cannot resolve symbol ..." and hightlight it red. And no code autocompleting for such classes.
However the project compiles and starts on the device without errors.
Has somebody any idea? I tried "clean and rebuild" for project, "invalidate cashes and restart" for Android Studio. Nothing helps.
in the module common you need to declare those transitive dependencies as api to expose them to other modules:
e.g. common/build.gradle:
dependencies {
implementation fileTree(dir: 'libs', include: ['*.jar'])
implementation 'com.android.support:appcompat-v7:28.0.0'
api 'com.squareup.wire'
}
https://jeroenmols.com/blog/2017/06/14/androidstudio3/
Solution
Change compile to api
dependencies {
api project(':Common')
}
Reason
Because compile is deprecated, so it is been treated as implementation.
FYI compile and api (new keyword for compile) are same in which all internal modules are visible.
But new gradle project having compile keyword are treated as implementation. and in implementation internal modules are not visible to main project.
Suggestion
You should declare dependency in your gradle because it is not good to make leak of internal modules.

Parceler - Unable to find generated Parcelable class

EDIT
After clean and rebuilt, classes are not generated
I got this error while trying to use Parcels.wrap()
Unable to find generated Parcelable class for xyz.xyz.models.reclamation.Reclamation, verify that your class is configured properly and that the Parcelable class xyz.xyz.models.reclamation.Reclamation$$Parcelable is generated by Parceler.
But Reclamation$$Parcelable class is created and I can see its content.
Thats my gradle:
compile 'org.parceler:parceler-api:1.1.6'
annotationProcessor 'org.parceler:parceler:1.1.6'
Trying to change annotationProcessor to apt causes build error.
Thats Reclamation class
#Parcel
public class Reclamation {
public Reclamation() {
}
private int reclamationProductID;
private Integer preference;
private String takingDate1;
private String takingDate2;
private int takingAddressID;
private String takingAddressStreet;
private String takingAddressCity;
private String takingAddressZipCode;
private int type;
private String takingAddressCompany;
// + getters setters
}
Thats the line where it crashes
ServiceStepFour_.builder().arg(Constants.ARG_RECLAMATION, Parcels.wrap(reclamation)).build();
I use it in combination with Android Annotations.
Does anybody know why this happens?
Although documentation says you have to put these lines to the gradle:
compile 'org.parceler:parceler-api:1.1.6'
annotationProcessor 'org.parceler:parceler:1.1.6'
change it to:
compile 'org.parceler:parceler-api:1.1.6'
apt 'org.parceler:parceler:1.1.6'
Make sure all files you want to use are annotated with #Parcel.
I have class A with class B variable and I forgot to annotate class B. That's why changing from annotationProcessor to apt gaves me an build error.
In my case, I have to remove this line when I move from apt to annotationProcessor
apply plugin: 'com.neenbedankt.android-apt'
I know this is a late answer but maybe someone else has this issue later,
If you are using Kotlin in your code you must use kapt instead of annotationProcessor to solve the issue
apply plugin: 'kotlin-kapt'
dependencies {
kapt 'org.parceler:parceler:1.1.12'
}

Android Studio Autovalue in java module and using in Android module

Using Android Studio I have an Android Module, and a Java module.
In the Java module, I want to use AutoValue to generate immutable classes.
All seems to work fine (files are generated in the Java module) but I'm unable to access those files in the Android project. Any suggestions?
app\build.gradle
apply plugin: 'com.android.application'
dependencies {
compile fileTree(include: ['*.jar'], dir: 'libs')
compile project(':domain')
}
domain\build.gradle
plugins {
id 'net.ltgt.apt' version '0.6'
}
apply plugin: 'java'
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.google.auto.value:auto-value:1.2'
apt 'com.google.auto.value:auto-value:1.2'
}
domain/MyLocation.java
import com.google.auto.value.AutoValue;
#AutoValue
abstract class MyLocation {
abstract String name();
#AutoValue.Builder
abstract static class Builder {
abstract Builder name(String _name);
abstract MyLocation build();
}
}
When I build the domain module (the java module), I see that the 'AutoValue_MyLocation' file is generated here:
\domain\build\generated\source\apt\main\my\package\domain\AutoValue_MyLocation.java
However, I am not able to use the generated class anywhere in my Android module.
Nevermind, by looking at the generated class I saw that it was not public, hence I could not access it in my Android Module.
To fix it, simple make the #AutoValue class public, like so
#AutoValue
public abstract class MyLocation {
//
}

Roboblender annotation processing not working

I try to make Roboblender work with Roboguice but the compile time processing doesn't seem to do anything, the AnnotationDatabaseImpl class is not generated. (Project builds without error.)
I even created a sample project, please see below. What do I miss?
(I know the gradle task and the second metadata would only be needed for multi module project, but it didn't work without them either).
build.gradle:
project.tasks.withType(JavaCompile) { task ->
options.compilerArgs << "-AguiceAnnotationDatabasePackageName=gk.com.roboguice_compile"
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:22.0.0'
compile 'org.roboguice:roboguice:3.+'
provided 'org.roboguice:roboblender:3.+'
}
manifest:
<meta-data
android:name="roboguice.modules"
android:value="gk.com.roboguice_compile.RoboguiceBindings" />
<meta-data
android:name="roboguice.annotations.packages"
android:value="gk.com.roboguice_compile" />
activity:
#ContentView(R.layout.activity_main)
public class MainActivity extends RoboActivity {
#Inject
private PresentMaker presentMaker;
bindings:
public class RoboguiceBindings extends AbstractModule {
#Override
protected void configure() {
bind(PresentMaker.class).to(BirthdayPresentMaker.class);
}
}
The AnnotationDatabaseImpl was there but only under the build directory not among the source files.
My bad, probably every annotation processor work like this.
(Although strangely this project has the AnnotationDatabaseImpl generated in the project root..).

Attempt to mockito mock any class generates ExceptionInInitializerError

When I run the following code:
public class ActivityTest extends ActivityInstrumentationTestCase2<MainActivity> {
....
public void testCanCreateMockito() {
List mockedList = Mockito.mock(List.class);
}
}
I get the following exceptions:
java.lang.ExceptionInInitializerError
at org.mockito.internal.creation.cglib.ClassImposterizer.createProxyClass(ClassImposterizer.java:95)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:57)
at org.mockito.internal.creation.cglib.ClassImposterizer.imposterise(ClassImposterizer.java:49)
at org.mockito.internal.creation.cglib.CglibMockMaker.createMock(CglibMockMaker.java:24)
at org.mockito.internal.util.MockUtil.createMock(MockUtil.java:33)
at org.mockito.internal.MockitoCore.mock(MockitoCore.java:59)
at org.mockito.Mockito.mock(Mockito.java:1285)
at org.mockito.Mockito.mock(Mockito.java:1163)
at com.acesounderglass.hungertracker.ActivityTest.testCanCreateMockito(ActivityTest.java:60)
at android.test.InstrumentationTestCase.runMethod(InstrumentationTestCase.java:214)
at android.test.InstrumentationTestCase.runTest(InstrumentationTestCase.java:199)
at android.test.ActivityInstrumentationTestCase2.runTest(ActivityInstrumentationTestCase2.java:192)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:191)
at android.test.AndroidTestRunner.runTest(AndroidTestRunner.java:176)
at android.test.InstrumentationTestRunner.onStart(InstrumentationTestRunner.java:555)
at android.app.Instrumentation$InstrumentationThread.run(Instrumentation.java:1837)
Caused by: org.mockito.cglib.core.CodeGenerationException: java.lang.reflect.InvocationTargetException-->null
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:238)
at org.mockito.cglib.core.KeyFactory$Generator.create(KeyFactory.java:145)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:117)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:109)
at org.mockito.cglib.core.KeyFactory.create(KeyFactory.java:105)
at org.mockito.cglib.proxy.Enhancer.<clinit>(Enhancer.java:70)
... 23 more
Caused by: java.lang.reflect.InvocationTargetException
at org.mockito.cglib.core.ReflectUtils.defineClass(ReflectUtils.java:385)
at org.mockito.cglib.core.AbstractClassGenerator.create(AbstractClassGenerator.java:220)
... 28 more
Caused by: java.lang.UnsupportedOperationException: can't load this type of class file
at java.lang.ClassLoader.defineClass(ClassLoader.java:300)
... 32 more
This occurs with any class, List was just an easy example. My gradle dependencies are:
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:21.0.0'
androidTestCompile "org.mockito:mockito-core:1.+"
androidTestCompile files('libs/dexmaker-mockito-1.0.jar')
androidTestCompile files('libs/dexmaker-1.0.jar')
}
I've upgraded gradle to 1.1, tried using the experimental unit test feature and not, nothing seems to make a difference. What's going on?
I received this error when I was missing the two dexmaker dependencies.
Adding these lines to the app/gradle.build file is working for me.
androidTestCompile 'org.mockito:mockito-core:1.10.19'
androidTestCompile 'com.google.dexmaker:dexmaker:1.2'
androidTestCompile 'com.google.dexmaker:dexmaker-mockito:1.2'
I am also using Android Studio and have found it to be a good idea to restart AS after altering the dependencies.
For me this eventually worked:
androidTestCompile "org.mockito:mockito-core:1.10.19"
androidTestCompile "com.crittercism.dexmaker:dexmaker:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-mockito:1.4"
androidTestCompile "com.crittercism.dexmaker:dexmaker-dx:1.4"
I was getting this because I was using proguard for my debug builds because of the 65K method limit (Yes, I need to cut down on the number of dependencies), and that was causing this error for me.
I added this in my (debug) proguard config to solve it:
### Keep Mockito
-keep class org.mockito.** { *; }
-keep interface org.mockito.** { *; }
-keep class com.google.dexmaker.** { *; }
-keep interface com.google.dexmaker.** { *; }
Not sure If I really need all four of those lines, but this did the trick.
LOOK HERE IF YOU DON'T BUILD YOUR APKS USING GRADLE!!!!
If you don't build your app using gradle (which, unfortunately, my team doesn't) then the above solutions may not work for you. Let me explain a little bit more about how dexmaker-mockito works before giving the solution to the issue.
Motivation
Mockito is a mocking framework for Java and comes packaged with cglib which creates Bytecode mocks, this is how Mockito/Junit outside of Instrumentation tests works. But if you're trying to run Mockito in Android instrumentation tests then Bytecode mocks are not sufficient and you need mocks that Mockito can load into the Dex classloader that ART/Dalvik can understand and that's where Dexmaker comes in. Dexmaker has a Mockito "plugin" that allows Mockito to dynamically switch to using it to create Dex mocks.
How does it know to switch?
The dexmaker-mockito jar has a top level folder named mockito-extensions/org.mockito.plugins.MockMaker containing a fully qualified name com.google.dexmaker.mockito.DexmakerMockMaker. When this jar is packaged with an APK, this top level folder can be included as a "class loader resource".
The class that Mockito uses to abstract the Mocking layer is called MockUtil and, statically, it determines which MockMaker subclass it should use by checking for these resources in the classloader that it is launched from via its PluginLoader. If the resource from dexmaker-mockito can be found, then com.google.dexmaker.mockito.DexmakerMockMaker is instantiated and used as the MockMaker but, if it's not, Mockito defaults to using CGLib which is incompatible within Android's DVM.
Problem
Depending on how you build your APK, you can potentially strip that class loader resource and cause Mockito to not dynamically switch to using Dexmaker.
Fix
First, include the jars that dexmaker requires: mockito 1.9.5+, junit, dexmaker-mockito 1.0+ and dexmaker 1.0+ and then simply reflectively switch which MockMaker Mockito will use manually. This is safe, given the fact that if this is running in the DVM, using the default CGLib MockMaker won't ever work since it produces Bytecode mocks.
static {
try {
ClassLoader loader = Thread.currentThread().getContextClassLoader();
if (loader == null) {
loader = ClassLoader.getSystemClassLoader();
}
Enumeration<URL> resources = loader.getResources("mockito-extensions/org.mockito.plugins.MockMaker");
if (resources == null || !resources.hasMoreElements()) {
LOGGER.info("Replacing Mockito mockMaker because the classloader resources were not present.");
Field field = MockUtil.class.getDeclaredField("mockMaker");
Class<?> pluginClass = loader.loadClass("com.google.dexmaker.mockito.DexmakerMockMaker");
Object plugin = pluginClass.newInstance();
field.setAccessible(true);
field.set(null, plugin);
} else {
LOGGER.info("Mockito class loader resources present");
}
} catch (Throwable e) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
throw new AssertionError("Unable to replace mockMaker to be the DexmakerMockMaker", e);
} else {
e.printStackTrace();
throw new AssertionError("Unable to replace mockMaker to be the DexmakerMockMaker");
}
}
}
and be sure to add this as well because dexmaker will need to know where to output its Dex mocks.
System.setProperty("dexmaker.dexcache", "/sdcard/");
I stumbled upon the same error and could make it work by using
androidTestImplementation 'org.mockito:mockito-android:2.18.3'
in my build.gradle.
I previously made the mistake to only import 'org.mockito:mockito-core:2.18.3'.
I encountered the same error with EasyMock and eventually traced it to an absence of dexmaker. I solved it with the following dependency:
androidTestCompile "com.google.dexmaker:dexmaker:1.2"
That might work for mockito as well
User23's answer is close to the solution that worked for me.
According to the official documentation you have to do the following things to activate Mockito in your Android app:
Download dexmaker-1.4.jar and dexmaker-mockito-1.4.jar and put them into your libs folder.
Add the following dependencies into your build.gradle:
androidTestCompile "org.mockito:mockito-core:1.10.19"
androidTestCompile fileTree(dir: 'libs', include: ['dexmaker-1.4.jar'])
androidTestCompile fileTree(dir: 'libs', include: ['dexmaker-mockito-1.4.jar'])

Categories

Resources