Jar referenced from android library project not referenced by App. NoClassDefFoundError - java

I have searched SO and tried all the solutions I came across but nothing seems to work. The things I tried are the solutions given here, here, here, here and here but nothing seems to work.
As described in some of those question I have a java library (lets say J) included in a android library (AL) that is included in a android app (AA). I have added the library to the libs of both (have also tried with adding it to just AA and including in AL, and vice-versa and just in AL and expecting android dependencies to take care of it) but that or anything else did not work.
I am using the latest tools(version 20.0.3).
The build android version for the android library and the app is 2.2 and min SDK is 5.
I can see the the java library in the android dependencies of the app but am getting a NoClassDefFoundException and run time.
How can I get this to work?
The android library must reference a jar, since that contains some encryption logic that I need to hide. The library is being created for distribution, the app is just something quite simple for testing the library.

There were 2 different but related problems causing this issue.
The Java library, J was compiled with compliance level 1.7 (default for my system). This needs to be at 1.5, the compliance level of Android. (compliance level may change in the future).
The J library was also compiling using the J2SE library. I had to replace that with the anroid.jar of the same api level as my app.
Then also things didn't work and for some reason it started working after I deleted the project and recreated in new directories.(IMP: take a code backup first).

Related

Which Java version should I use to create a library usable with Android

I'm maintainer of an Open Source Java library.
I have no experience at all in Android development but I would like that my library could be used in an Android app as dependency. (at least I would avoid the main blocker issue)
It's not crystal clear to me but I understand there is several kind of Java Compatibility with Android :
API level
byte code compatibility
source code compatibility.
(Please to not hesitate to better explain this ☝ or correct me if I'm wrong)
I guess in my case I'm mainly concerned by the 2 first points.
Currently :
we check API level with animal-sniffer-maven-plugin. (api-level-19)
our releases are compiled against java7 with a openjdk7.
But I would like to upgrade to a more recent version of Java. (probably java8, but maybe java11)
Can I use those jdk versions (openjdk8, openjdk11) to compile a library which could be used in android project ?
My current research about this, but still not clear to me :
https://developer.android.com/studio/write/java8-support
https://jakewharton.com/androids-java-9-10-11-and-12-support/
https://developer.android.com/studio/releases/gradle-plugin?utm_source=android-studio-2020-3-1&utm_medium=studio-assistant-stable#java-11

Create Android library jar to work with non-Android project

I am working on a library that ideally will have a strictly-Java component and added functionality for Android-specific projects, with the intent to be most useful for Android apps, but also work with other Java apps.
But my question is: how should this be designed? I do not plan on needing resources, so I want to compile it into a JAR, but would I need to make two JARs, one of the Java stuff and another for the Android stuff? Or would a Java-only application be able to use a single JAR so long as it does not use the Android components?
If you make a library that uses pure java and does not use any android apis. It will work on both standard java and android java. However if the library uses any android apis it can't be used in a standard java project.
As far as I know, the JAR would be good for both types of aplications. It seems to mee that both JARs (just Java and android) are totally identical and thus equally compatible. If you don't use any of the android components, including Resources there should not be a problem at all.
You should still check whether you depend on libraries which are available on android and any normal Java distribution or -if not- either tell the user to preinstall the depending libraries or ship them whitin your JAR package and build path. Be carefull not to use libraries which are not available on android because the user has no or really few options to install them on himself.
What I don't understand is why you think your library is more usefull to android developers. I can not think of any example where this could happen. If the problem is really specific for android, you should consider developing the library android-only. If the problem is more general the lib will be usefull to all developers that might come to this problem, not just android.

Use preprocessor in Android project in Eclipse

I am trying to use preprocessor like #ifdef in my Android project in Eclipse. I did some research on this topic and found this link: Java Preprocessing Using Eclipse, which could potentially let me use preprocessor in Android project.
However, after I tried to build the project, it claimed something like package android.* does not exist. So, none of the android APIs could be found.
So, how should I add those libraries in the build path? Actually, android.jar file is under the Java Build Path already. Why does Eclipse still claims that?
Is there any other way to let me use the preprocessor in Android Project built in Eclipse?
You are programming in Java, not C/C++. Android development does not require the use of a preprocessor.
Edit:
My problem is we developed an Android app with USB functionality which is supported only by Android 3.1+. So, some of the USB libraries are imported, what I want is those imported libraries could be commented out using #ifdef, if we could, when we build the project for Android 2.2 or 2.3, etc. Is there any other workaround for this?
To make use of the classes/methods you mentioned, you'll have to build your application against the Android SDK version 3.1 or higher. However, you must also ensure that devices running version 3.0 or lower don't make use of these classes/methods during runtime, since doing so will result in a ClassNotFound exception.
The key take-away here is that you need to perform these checks at run-time. Since your application is compiled only once for all devices, a preprocessor could do nothing to prevent such an event from occurring. Instead, you need to explicitly protect against this in your code. This is usually done with a basic if-else statement. For example,
if (Build.VERSION_CODES.HONEYCOMB_MR1 >= Build.VERSION.SDK_INT) {
// then you are on a device running android 3.1+ and it is
// safe to make use of the new classes/methods
} else {
// otherwise, you are running on a device running android 3.0
// or lower. you should not make use of the new classes/methods.
}
Edit #2:
In response to bill's comment, which read:
Thank you, Alex. I built my project agaist 3.1, deployed it on 2.2 and run it. One last thing I am not quite sure I understand is I could debug the part of the code referred by the Android 3.1 on the Android 2.2 OS. Here is my explanation: after being built against 3.1, Java code is converted to machine code and HONEYCOMB_MR1 is just an integer although HONEYCOMB_MR1 is not present in 2.2, when I debugged it, the debugger goes to the line of HONEYCOMB_MR1, fetches that integer and compares with SDK_INT. In this way, the code could still be debugged although HONEYCOMB_MR1 is only in 3.1 SDK. Is that correct? Thanks.
I think you are understanding correctly. The more exact reasoning is that HONEYCOMB_MR1 is marked static final. Since the variable is an immutable constant (i.e. its value will never change), the integer is hard-coded into the bytecode when you compile the .apk. In So when your 2.2 device reaches the if statement, it checks to see if 12 > 8, thus avoiding a (failed) runtime search for HONEYCOMB_MR1.
This sort of thing actually happens quite frequently when you develop your Android application. For instance, this behavior also explains why you can use MATCH_PARENT (introduced in 2.2) on devices that should "technically" only support FILL_PARENT. Both constants have value -1; thus, when you run an app that uses MATCH_PARENT on a pre-Froyo device, all works as expected.

Building multi-SDK Android apps in Eclipse without losing compile-time checks

I am developing an Android app in Eclipse. I would like to target a wide variety of devices and SDK versions (for example, I can optionally support multi-touch). I understand the recommended approach of isolating all the new functionality to a separate class and leveraging lazy loading to only load that class at run-time if the host device actually supports the feature.
The downside of this approach is that I have to compile all of my code with the SDK of the newest feature I want to use. Which means if some new feature leaks into my "version neutral" code, the compiler can no longer catch it.
I would like the ability, within Eclipse, to compile my project against an older Android SDK to make sure my "version neutral" code is fine. I'd like to avoid moving my build system out of Eclipse, if possible. I'm okay with this old-SDK build being a bit awkward to run.
I think this boils down to doing some conditional compliation (or conditional "linking") inside Eclipse? For example, in my project when building against SDK-1.6 I'd like to leave the "MultiTouchHandler.java" source out of the build. I'm not sure if its possible to express "build types" like this in Eclipse, though.
The hacky solution seem to be just manually changing the project's SDK version, rebuilding, and looking through the errors, and ignore 'expected' errors. The overkill solution seems to be writing my own ant/maven/make build scripts.
Related Questions
This question:
Versioning and common code-bases with Eclipse
covers similar ground, but would involve moving all of the version-specific classes into separate "libraries". (And I would still have the problem of multiple build types in Eclipse, I think.)
This question:
Build multiple project configurations with eclipse implies that I should move to an external build system (like ant or maven), but that's a lot more work than just trying a build with an old SDK from time to time.
The February 2012 (v17) updates to the Lint Tool in the ADT should help address this without requiring multiple builds. When an app targets an old minimum SDK, but is compiled against the newest SDK (as is the recommended practice), the lint tool will notice if calls to the newer SDK are invoked. If you're confident the call is okay (Because you've hidden it behind a run-time SDK_INT check, or whatever), you can Quick-Fix an annotation to prevent the warning.
For example, in my code I have a call to View.setSystemUiVisibility, which was introduced in API 11, but I'm targetting API 8. Running Lint shows:
Call requires API level 11 (current min is 8): android.view.View#setSystemuiVisibility
The QuickFix suggests two kinds of fixes, either adding an annotation that suppresses the warning or adding an annotation that declares a chunk of code as working at API 11.
More details here: http://tools.android.com/recent/lintapicheck
A somewhat less clean/less performant method would be to use reflection to access the newer apis that you need, rather than trying to reference them directly with lazy loading. This should allow you to compile against a lower sdk level.

How to develop using android libraries in a simple java project (without using dalvik and such)

As I am very pissed off of using the emulator to develop any Java class, I thought of setting up a project in Eclipse and instead of the usual JRE I linked to the Android.jar (version 2.1) that usually the Android projects link to. I don't mean to use this to develop Layouts or other specific platform things, I was just trying to create a class that uses HttpClient. It miserably crashes like this.
Exception in thread "main"
java.lang.RuntimeException: Stub! at
org.apache.http.impl.client.AbstractHttpClient.(AbstractHttpClient.java:5)
at
org.apache.http.impl.client.DefaultHttpClient.(DefaultHttpClient.java:7)
at
AdsCatcher.(AdsCatcher.java:26)
at TestAll.main(TestAll.java:10)
Stub! I mean I'd like to develop libraries (and test them) so that when I go to the emulator I don't have to deal with them. Is there a good way to do this? This seems not to work for some reason.
This will not work, sorry. The android.jar file, as the error message indicates, contains only stubs of the Android API. This makes sense, since that API cannot work outside of Android -- the android.jar file is just there for compilation.
For class libraries you are working on that have no dependencies on Android, you are welcome to create a standard JRE Eclipse project that generates a JAR that you then use in your Android project.
In your case, you may be able to create a class library using the JRE that uses HttpClient. The latest version from Apache may differ slightly from the version in Android, though, so while probably you will be OK, there's a chance you will run into runtime errors due to changes in method signatures and such (VerifyError).

Categories