qt android ClassNotFoundException - android

I'm using Qt (qml) to make an android app but I'm getting errors trying to register native methods to be called from java. In one section on my native code I'm calling java static functions with no problems:
void NotificationClient::powerOff() {
QAndroidJniObject::callStaticMethod<void>("com/my_app/Utils",
"powerOff",
"()V"
);
}
Now I'm trying to add some calls from java back to my native code (based on this example) but it fails
QAndroidJniEnvironment env;
jclass objectClass = env->FindClass("com/my_app/Utils");
Results in:
Pending exception java.lang.ClassNotFoundException: Didn't find class "com.my_app.Utils" on path: DexPathList[[directory "."],nativeLibraryDirectories=[/system/lib, /vendor/lib, /system/lib, /vendor/lib]]
I've checked the dexdump from classes.dex and the class string matches. All paths in my AndroidManifest.xml are absolute. I've cleaned and rebuilt. Nothing is getting around that problem and I can't figure out why the static method call works but the object one does not.
(Yes, yet another ClassNotFoundException post but I really have searched for answers already).
edit The original failed method based on creating an object threw a different error so I switched back to use FindClass which gives the ClassNotFound error
UPDATE
OK, so I think I've figured out why FindClass is failing: according to this FindClass will search the callstack to figure out which ClassLoader to use. Normally this is fine but I believe Qt for android loads under a different thread so the wrong ClassLoader is getting called.
The link recommends caching the classes in JNI_onLoad but with Qt that's behind the scenes. Is there some other place where I could cache class id's on the main thread instead of the qt thread?

To answer my own question for completeness ...
The reason it failed to find the classes was Qt runs on a different thread than the main java thread, which caused the java classloader to fail in the lookup (see link in question update).
As a solution I added a JNI_onLoad function in one of my cpp files, which is called on the main java thread so the class lookup works correctly.

Related

C++ Exception in 'nativeRequireModuleConfig', What is Landroid?

C++ Exception in 'nativeRequireModuleConfig':
java.lang.NoSuchMethodError: No static method getNoBackupFilesDir(Landroid/content/Context;)Ljava/io/File; in class Lcom/google/android/gms/common/util/zzx; or its super classes (decleration of 'com.google.android.gms.common.util.zzx' appears in /data/app/com.kotac-2/base.apk)
To avoid this error you can modify the project into a working state, for example if your project is on git and versioned, reset it into an older commit which it is working well.
I was able to get over this issue by getting the app working however and updating the code again.

ServiceLoader.load is not finding the META-INF/services

So I want to build an extensible android application where developers can add 'CustomDevice' classes and the main program will run them automatically without editing existing code.
I've read about Service Provider interface and thought that would be a nice way to go about it.
So I tested it and created an interface called 'ICustomDevice' which custom device classes are expected to implement.
I've created a class called 'DummyDevice' that implements ICustomDevice.
Both DummyDevice and ICustomDevice are in the same package "CustomDevicePackage".
So in my main program I run the following.
ServiceLoader<ICustomDevice> loader = ServiceLoader.load(ICustomDevice.class);
Iterator<ICustomDevice> devices = loader.iterator();
System.out.println("Does it have devices? " + devices.hasNext());
It always returns false, which means it's not finding the 'DummyDevice'
In my eclipse project I created a folder at 'src' called META-INF and under it, a subfolder called 'services'.
'Services' has a file named 'CustomDevicePackage.ICustomDevice' with a line of content 'CustomDevicePackage.DummyDevice'.
Am I doing it right? Every example I see about SPI is about loading JARS.
I'm not loading a JAR, I'm trying to run a class in the same Project. Does this method only works for loading JARs? I want my program to support loading local subclasses and external JARs alike.
I am adding this as an answer but leaving the prior "answer" to provide extended code detail for this workaround. I am working on reporting the prior answer results as a bug to Google.
Because the Android implementation of java.util.ServiceLoader is broken (always populating internal java.security.AccessControlContext field with AccessController.getContext() even if System.getSecurityManager() == null), the workaround is to create your own ServiceLoader class by copying the code found at OpenJDK for Java 8 into your class, add specific imports required from java.util without using import java.util.*;, and call that ServiceLoader in your code (you will have to fully reference the ServiceLoader you created to over ambiguity).
This isn't elegant but it is a functional workaround that works! Also, you will need to use a ClassLoader in your ServiceLoader.load() call. That ClassLoader will either have to be YourClass.class.getClassLoader() or a child ClassLoader of the class' ClassLoader.
Though it's an old post, This may be still be of some help to others:
When I was running or debugging a project that contained a ServiceLoader Class, I had to put the META-INF/services folder into the src/ folder in Eclipse.
If I tried to export the project as Runnable jar and tried to use the class with the service loader, it never worked.
When I checked the jar, unzipping it, I found the folder under src/META-INF/services though.
Only when I also added the META-INF folder directly in the root directory of the jar, it started to work.
I haven't found a fix though inside Eclipse, that makes sure it gets exported right...maybe an ANT script can solve this issue, but so far no attempts made...
This is an answer:
At some point, Android removed the AccessControlContext field in ServiceLoader and ServiceLoader now works. As my comments indicate, this was reproduceable using the "out-of-the-box" OREO (API 26) Intel Atom x86 emulator with Android Studio (also fresh download). 24 hours later, ServiceLoader no longer contained the acc field (as shown in the Android Studio debugger with the same emulator). The Android SDKs dating back to API 24 do not show the acc field.
Per the Android developer currently maintaining the ServiceLoader code:
He is not aware of ServiceLoader ever having the acc field in Android (it did as we were able to reproduce) and thought the debugger/emulator might have been using JDK code (but I showed the OpenJDK code works correctly). Somewhere along the way, the errant code was updated and I am no longer able to reproduce.
Be sure your OS is up-to-date and you should no longer see this phenomena.

Native application crashes on Android L

I have a native application that always worked on Android KitKat with both Dalivik and ART runtimes, but it now crashes on Android L with the following trace:
E/art(12810): dlopen("/data/app-lib/com.mylib.example", RTLD_LAZY) failed: dlopen failed: cannot locate symbol "issetugid" referenced by "mylib.so"...
D/AndroidRuntime(12810): Shutting down VM
E/AndroidRuntime(12810): FATAL EXCEPTION: main
E/AndroidRuntime(12810): Process: com.mylib.example, PID: 12810
E/AndroidRuntime(12810): java.lang.UnsatisfiedLinkError: dlopen failed: cannot locate symbol "issetugid" referenced by "mylib.so"...
E/AndroidRuntime(12810): at java.lang.Runtime.loadLibrary(Runtime.java:364)
E/AndroidRuntime(12810): at java.lang.System.loadLibrary(System.java:610)
Is ART runtime in Android L different from KitKat? There is no new NDK available yet, therefore, how to avoid this crash, because it seems that the function issetugid is no longer supported.
The issue has been fixed in the final Android 5.0 release. There is no need to re-compile existing binaries.
However, if the native lib is compiled with target android-21, it fails on previous Android versions (< 5.0)
I think i may have the answer, please correct me if iam wrong.I had faced similar issue and now its fixed (or i have found a workaround rather)
while registering native method to JNI, there are two ways of doing it.
1) Implement JNI_OnLoad() method in your .cpp file and register your native methods with the
appropriate classes.
Check- http://developer.android.com/training/articles/perf-jni.html#native_libraries
example - https://android.googlesource.com/platform/development/+/master/samples/SimpleJNI/jni/native.cpp
2) there is a particular naming convention to follow for the native methods, where the class path (including package) have to be added.
Check - http://docs.oracle.com/javase/6/docs/technotes/guides/jni/spec/design.html#wp615
Here we need not implement any method. The JVM discovers the native method from the symbol names it self from the binary.
The first method doesn't seem to work in Android ART runtime (ART is Optional in kitkat and it will be the only runtime in Lolipop).I am not not sure why it doesnt work. but i think the reason is because the way ART performs.(The bytecodes are converted and cached during install time itself instead of runtime, so that app runs faster). So since the native libs are not loaded (on_load is not called) the conversion to machine code fails at some point
Use the second method to register natives. it should work.
Only disadvantage is now your function names will be and long and will look horrible (i bet none of the function will fit in 100char limit).bye bye function name readability.
Hope this helps
Cheers,
Shrish

Android NoClassDefFound when referencing class from external libraries (IntelliJ IDEA 12)

I'm having an issue with IntelliJ's dependency handling in regards to external modules. Here's some context:
I'm writing an Android app which implements Google Maps. For my current feature set, I require two external libraries-- Google's Play Services Library and mapex (A third party google map extension library located here https://code.google.com/p/mapex/). I actually built most of this project in Android Studio before I was recommended to move to IntelliJ due to the easier dependency handling. But now I'm here and still having problems.
My Error
When trying to build an object from a class located in the mapex package (com.androidnatic.maps), I get this error when starting the activity the view is contained in (object has not been created yet):
07-03 11:40:35.837: ERROR/dalvikvm(3585): Could not find class 'com.androidnatic.maps.SimpleMapView', referenced from method com.example.myproject.MapActivity.showHeatMap
And then, upon creation, my app force closes and leaves this behind in logcat:
7-03 11:40:45.467: ERROR/AndroidRuntime(3585): FATAL EXCEPTION: main
java.lang.NoClassDefFoundError: com.androidnatic.maps.SimpleMapView
at com.example.myproject.MapActivity.showHeatMap(MapActivity.java:492)
Yet I'm completely stumped because my IDE gives me no sign that anything is wrong! Classes are auto-filled in when trying to access them from MyProject.
ide-fill-in http://www.tonyandrys.com/img/fillin.jpg
No build errors about missing classes, missing modules, class definitions, or anything related.
I get the same results if I try to access the class via its full package name as well.
// No dice.
final SimpleMapView mapView = new SimpleMapView(this, "apikey");
final com.androidnatic.maps.SimpleMapView mapView = new com.androidnatic.maps.SimpleMapView(this, "apikey");
It seems that there's only an issue when the application is running on my phone, as far as my IDE is concerned.
Here's the structure of MyProject:
main-project-structure http://www.tonyandrys.com/img/mainstructure.jpg
Here's my main project's dependency settings (where I assume I screwed up somewhere):
project-structure http://www.tonyandrys.com/img/projectstructure.jpg
And here is the structure of the mapex library module:
mapex-lib http://www.tonyandrys.com/img/mapexstructure.jpg
The class files that I'm trying to access live in MapExLib/gen and MapExLib/src, which are currently marked as source directories (blue).
Does anyone have any ideas on how to proceed from here?
Try to do this :
Android, IntelliJ Idea, changing module type
I had the same error "Could not find class XXX from referenced method XXX" with Intellij, involving an Android Test Module and a test which could not find the Activity class anywhere.
I set inside the Project Structure the main Module's Facet Android to Library Module (checkbox) and it worked...
Let us know

android mupdf libmupdf.so runtime error "No implementation found for native openFile"

I just finished compiling mupdf from mupdf.com on my mac. Took some time to figure it out but now I have a libmupdf.so in my libs/armeabi folder.
They provide an example of this class called MuPDFCore.java which is viewable here:
http://mupdf.com/repos/mupdf/android/src/com/artifex/mupdf/MuPDFCore.java
I used this class in my project and it says the following in LogCat:
Trying to load lib
/data/data/com.myapp.android/lib/libmupdf.so
0x4070e050
Added shared lib
/data/data/com.myapp.android/lib/libmupdf.so
0x4070e050
No JNI_OnLoad found in
/data/data/com.myapp.android/lib/libmupdf.so
0x4070e050, skipping init
No implementation found for native
Lcom/myapp/android/viewer/MuPDFCore;.openFile
(Ljava/lang/String;)I
DEBUG/AndroidRuntime(27523): Shutting
down VM
WARN/dalvikvm(27523): threadid=1:
thread exiting with uncaught exception
(group=0x400ee760)
ERROR/AndroidRuntime(27523): FATAL
EXCEPTION: main
ERROR/AndroidRuntime(27523):
java.lang.UnsatisfiedLinkError:
openFile
As far as I know the library is loading, before I figured out how to compile the library it kept crashing and saying the "mupdf" is a null link.
Their example pretty much says that openFile is a native function ... Just when I thought I figured this out another problem pops up. Ive been working on it all day. Any input would be great!
Is it a bad compile? I didn't get any errors in the terminal.
when you try to use it on your project with sample project's so files, it will throw "UnsatisfiedLinkError: Native method not found" exception. The cause is your app package name different from sample app package name("com.artifex.mupdf") because of jni binding system. You can solve this problem with below approaches:
1) long way: change mudef lib source code according to your package name, generate binaries(.so files) from it then use it in your project like #KuoCH said
2) short way: create "com.artifex.mupdf" package in your root source directory(beside project source folder, "src/main/java"), copy all classes from sample project to in it
At file mupdf.c L18-19:
#define JNI_FN(A) Java_com_artifex_mupdfdemo_ ## A
#define PACKAGENAME "com/artifex/mupdfdemo"
Change both to your package name.
I think you didn't change the your function names in mupdf.c to your corresponding java package name, that means, you should change the function Java_com_artifex_mupdf_MuPDFCore_openFile in your mupdf.c to Java_com_myapp_android_viewer_openFile.

Categories

Resources