java.lang.NoSuchMethodError for method on the build path - android

I have a basic Android project created in Eclipse Indigo. I have a third-party library on my build path, and it is called is used when I instantiate a class from that library in my initial activity.
Although the app build just fine, I encounter the following error:
10-02 19:51:17.311: ERROR/AndroidRuntime(314): java.lang.NoSuchMethodError: org.apache.http.conn.scheme.Scheme.<init>
Earlier in logcat, I do observe the following error message:
10-02 19:50:48.670: DEBUG/dalvikvm(295): DexOpt: not verifying 'Lorg/apache/http/conn/scheme/Scheme;': multiple definitions
This class is included in the third-party JAR; is it used by Android somehow/somewhere to suggest a conflict or other source of "multiple definitions?"
Thanks!

How does one reconcile the conflict - do I have crack open the third-party JAR and exclude the conflicting files?
My guess is that this would not help, though you can certainly try it. Somebody would appear to be trying to call a method on Scheme that perhaps exists in the JAR's own private copy of that class but is not in the Android SDK.
If the third-party JAR in question is Apache HttpClient, simply don't put that JAR in your build path, as HttpClient is already part of Android, and stick to methods that are in the SDK. If the third-party JAR is not Apache HttpClient, I suspect that once you remove their duplicate org.apache.http classes, that something else will break that depended on their own private version of those classes. If that is the case, you should probably take it up with the third-party developer directly, to work with them on Android support for their JAR. You might be able to use tools like jarjar to get past this, but I would not count on it.

You can try something like jarjar, it can break open the jars and rename the packages to a different path at build time. This avoids conflicts like the ones you're having. I'm just not sure it will work with Android.

Related

Developing Android 9.0 eSIM LPA (system app)

Trying to develop android LPA system app for eSIM with the new Pie API.
The doc says to extend the abstract EuiccService class. But this class is not in the official SDK, and the link in the docs just leads to corresponding file in the android source repo.
I tried using this file/class as a dependency, but it references other internal android classes/annotations and causes build/IDE errors.
Does anyone have an idea how to use this?
Do I really have to pull android src code and somehow reference required class from it?
EDIT: I think I've solved it, found couple of potential solutions, but they were a bit cumbersome. Used the android.jar from here: https://github.com/anggrayudi/android-hidden-api (contains modified android.jar with hidden APIs and internal resources). It didn't work when i replaced the whole file and resulted strange build errors, but i manually transferred the android\service\euicc\ folder to original android.jar of android-28 sdk and it works perfectly (class is available and apk builds without issues). And no need to waste time pulling and building AOSP.
EDIT #2: apparently not fully fixable atm. There's issue with android gradle plugins (at least 3.2.x-3.3.x) where during full sync some build task generates mock classes from android.jar and process fails if it's modified (discussion is here: https://github.com/anggrayudi/android-hidden-api/issues/46). Error looks like this:
Failed to transform file 'android.jar' to match attributes {artifactType=android-mockable-jar, returnDefaultValues=false} using transform MockableJarTransform
There's a workaround for that, though inconvenient:
when you need a full sync for the project, replace the android.jar with original, run sync, restore modified android.jar, the IDE now will run indexing and classes will be available again with build working until next full sync.
Will update this post if/when it's fixed or new solution is found.
EDIT#3: here's probably a final solution for EuiccService case (turned out pretty obvious):
Instead of adding 'android/service/euicc' folder to android.jar, just put it in a separate library and add it as a compileOnly dependency. Since the classes were not in the SDK, the lib should not cause conflict (would be the case if you need to use modified framework or access hidden APIs in already existing classes).
If you are going to create a System APP, you will do it in several ways:
You could call a part of the SystemAPI (a method for example) by reference.
You could make the aplication as a part of the AOSP Project (Downloading the AOSP code, and introducing your app as part of packages/apps/)
You will be able to access system APIs on a rooted device or if you have system permissions (this happens when you flash your app into the device as part of the system image).
However, if you want to be able to call the EuiccService class from Android Studio (for coding purposes), you'll need to add the Android framework jar to your project.
The steps are provided below:
First, you will have to download and build AOSP and generate a framework jar for your target Android version. Check the documentation here to get an idea of how to download and build AOSP.
After a successful build all framework classes are compiled into a jar called classes.jar which can be found at the location out/target/common/obj/JAVA_LIBRARIES/framework_intermediates.
Get this classes.jar and add it to your Android project as a jar file.
Gradle sync the project and start coding.
Please beware that you WILL NOT BE ABLE TO run this app on an Adnroid device where you do not have system permission for this app.

Generate MainDexList.txt for Pre-5.0 Multidex app with reflection support

We are using android-maven-plugin to build a multidex application targeting Jelly Bean (4.3.x) with greater than 65k methods. The approach described here helps create a MainDexList.txt file, but does not automatically include classes that will be loaded by reflection.
Are any tools or processes available that can create a MainDexList.txt file with reflection support? [The majority of the classes we are loading via reflection are named via String constants...]
We are attempting to avoid manually running the app and dealing with NoClassDefFoundError messages one at a time.
To deal with the NoClassDefFoundError, you just need to add the MainDexList.txt to each of your projects. This should solve your initial errors right away. However, since your MainDexList.txt will still be empty, you will run into further issues.
To load the MainDexList.txt with a script instead of doing it manually, you can use this open source script by Google which will generate the exact class names that should be included in MainDexList.txt. Here is a link to the actual commit by Google:
https://android.googlesource.com/platform/dalvik/+/2bb6fe45bf620525ba34bd7303d7ecb597aa0689
To learn more (and also my source of information):
http://blog.osom.info/2014/10/generating-main-dex-list-file.html
Notes: This unfortunately does not support reflection however, DexClassLoader loads classes from .jar and .apk files containing a classes.dex entry. This may be worth looking at as well.
Hope this helps!

java.lang.NoSuchMethodError: org.json.JSONObject.getNames on Android due to conflicting libraries

I am creating a cross platform application in java using libgdx. I am using Json in the core project and was trying to deploy on Android when I received this error:
E/AndroidRuntime(2030): java.lang.NoSuchMethodError: org.json.JSONObject.getNames
I read around and I found out that Android has a built in Json library that uses that same package name as the Json library I added to my core project. The library I use has the getName() method and the Android library has a name() method. Is there a way for me to specify the library I want to use? Alternatively, is there a way for me to ignore the Android library?
Update: I tested accessing the JSON method in my android project using
JSONObject.getNames(TEST);
which should have given me null, but instead gave me the same error.
if you happen to use a lib, that uses the same namespace/package name as another, you are at the mercy of the classloader, which usually picks the first place, where it can find the class by name.
so the easiest way to circumvent this is either to use the same library and version as used on android or move your library in another package.
if the library in question allows it (licence etc) and is reasonable small, you might be easier off just pulling in the source files in your project and let the IDE do the refactoring magic. Also there are tools like jarjar.
There are some question on SO (Calling same Method having same packageName From Different JARs, Java, Classpath, Classloading => Multiple Versions of the same jar/project). So you might be able to circumvent this problem, but my gut feeling is, that you will end up in big mess.

Using cwac-camera via JARs

I'm using the commonsguy cwac-camera library, as per the demo-layout example, documented in "Working directlly with cameraview".
All is fine referencing camera/ and camera-v9/ as Android library projects in source form (I need Android 2.3 compatibility, that's what camera-v9 is for).
When I switch to using the library via JARs:
- cwac-camera-v9-0.6.8.jar only includes CameraFragment and BuildConfig classes, so I need also cwac-camera-0.6.8.jar with the other classes.
- including both JARs causes the following self-explaining error when running the project (not at compile time) Conversion to Dalvik format failed: Unable to execute dex: Multiple dex files define Lcom/commonsware/cwac/camera/BuildConfig;
I could just use the source as library project, or use Gradle, but I want to know if this is a bug to open an issue on Github, or if I'm doing something wrong.
To replicate the error, just clone the demo-layout example add both .jar files to libs folder, and run the project.
No, this appears to be my fault. They must have changed something in the Gradle build process that I am using to create the JARs. I will try to fix this tomorrow. In the meantime, you could go into the cwac-camera-v9 JAR and try removing the classes in com.commonsware.cwac.camera, leaving only those classes incom.commonsware.cwac.camera.acl.
My apologies for this, and thanks for pointing it out!

NoClassDefException for Java third-party libraries under Android

I found this Adding a library/JAR to an Eclipse Android project and followed the directions there, but I still seem to be getting a NoClassDefException on my class derived from the third party library.
I downloaded the third party library and imported according to the answer above. According to this, it will convert the code automatically to dalvik. Then, when I run on my phone, it tells me it cannot instantiate the sub-class of the third party library. Other messages say it is because it cannot find the superclass.
Am I missing something obvious?
It appears that the "libs" directory is a magic name. I renamed my directory to libs and re-ran the app and it appears to be working.

Categories

Resources