android cannot find corresponding jni function - android

I've followed here and I've added the .so files to my android project. Loaded the library and the project runs.
Now I want to use a function of the library. I tried like this in my MainActivity:
public final static native int crypto_aead_chacha20poly1305_encrypt(byte[] jarg1, int[] jarg2, byte[] jarg3, int jarg4, byte[] jarg5, int jarg6, byte[] jarg7, byte[] jarg8, byte[] jarg9);
Android gives me that he cannot find the corresponding JNI function.
The so files are in jniLibs in the right architecture map.
Has this something to do with my packagename that he tries to find it in my package instead of in the so library?
When I run this I get:
java.lang.UnsatisfiedLinkError: No implementation found for int be.example.libtest.MainActivity.crypto_aead_chacha20poly1305_encrypt(byte[], int[], byte[], int, byte[], int, byte[], byte[], byte[]) (tried Java_be_example_libtest_MainActivity_crypto_1aead_1chacha20poly1305_1encrypt and Java_be_example_libtest_MainActivity_crypto_1aead_1chacha20poly1305_1encrypt___3B_3I_3BI_3BI_3B_3B_3B)

I see that Robosodium uses Swig to generate wrapper. In this case there should be also some automatically generated Java files in src/main/java/org/abstractj/kalium that need to be added to your project as well. All native calls should be made using methods provided in that classes.

Create folders with names of "armeabi" and "armeabi-v7a" in libs folder of your project and place your ".so" file into that both folders and clean the project and run it.

Related

How can i reach files from Android NDK?

I never make a android project and i don't know java. I am trying to port my c++ sdl opengl project to android. I am using android studio. I opened sdl sample android project and now i can manage project from main.cpp . How do i know this because I changed the color of the window and it worked. But when i try to load shader.text file with ifstream program crashed. I understand that this will not happen. After this i searched but I couldn't find a complete code or an example.
When i put files in assets folder and build apk. apk size grows as files. Therefore I need to kepth files in assets folder ?
I think i need to use asset manager but of course i don't know.
What files should I write what code? I mean what i need to add main.cpp and I need to add code java side also ?
main.cpp :
int main()
{
//lets say i have filePath like these
char file_vert[100];
snprintf(file_vert,100,"shaders/vertexShader.text");
char file_Texture[100];
snprintf(file_Texture,100,"textures/image.jpg");
//i am using them in cpp project
//shader text file like this
std::ifstream vShaderFile;
vShaderFile.open(file_vert);
//and i am loading texture file with "stbi" library
unsigned char *data = stbi_load(file_Texture, &width, &height, &nrComponents, 0);
}

How to use .so file of another android project to another project

I have decompiled an android signed apk and it has a .so file...
when i am copy paste that .so file in my project's jniLibs/(abi)/*.so
The library load successfully, but it gives following error,
java.lang.UnsatisfiedLinkError: Native method not found: com.***.***.****.****.Decode:([BI[B)I
Here decode is native mathod.In singed apk also the are using same signature for native method...and i am also using the same method signature, then also i am getting the error like this...
please help me
thanks in advance
Let your method com.***.***.****.****.Decode be the com.aaa.bbb.ccc.Ddd.Decode. Then you should create package com.aaa.bbb.ccc, create Ddd Java class in this package, define native method
public native int Decode(byte[] in, int length, byte[] out);
in this class and add a static *.so library by means of:
static {
System.loadLibrary("Ddd");
}
to this class. Make sure if your *.so file has name libDdd.so than you have to write just a Ddd in System.loadLibrary.

Is it necessary to follow same package name as it was for so file while using .so file in new Android project

I had created one project using native c++ support. In this project I am passing int value from activity to c++ code and native code returns whether this is prime number or not. This works perfectly, Now I want to create .so file to use in another project. I had google many post but not got answer how to get different .so file for all devices. So I had rename .apk file to .zip and extract it. After that I got one .so file.
Now I want to use this .so file in another project. therefore I had created new project with different name but package name is same. I had created one directory inside src/main and named it as jniLib in this lib I had copied my .so file directory. In my MainActivity I load so file as static {
System.loadLibrary("native-lib");
}
and call my native method private native String isPrimeNumber(int number);. Here everything is perfect. Now I can get result without having actual c++ code.
Now Again I created new project and follow above steps which was followed by creating second project, but difference is that now I had changed package name of my application. when I run application my application got crashed with error as
FATAL EXCEPTION: main
Process: com.app.androidkt.differentpackage, PID: 16970
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String com.app.androidkt.differentpackage.MainActivity.isPrimeNumber(int) (tried Java_com_app_androidkt_differentpackage_MainActivity_isPrimeNumber and Java_com_app_androidkt_differentpackage_MainActivity_isPrimeNumber__I)
at com.app.androidkt.differentpackage.MainActivity.isPrimeNumber(Native Method)
at com.app.androidkt.differentpackage.MainActivity.access$000(MainActivity.java:10)
at com.app.androidkt.differentpackage.MainActivity$1.onClick(MainActivity.java:38)
at android.view.View.performClick(View.java:5268)
at android.view.View$PerformClick.run(View.java:21550)
at android.os.Handler.handleCallback(Handler.java:822)
at android.os.Handler.dispatchMessage(Handler.java:104)
at android.os.Looper.loop(Looper.java:207)
at android.app.ActivityThread.main(ActivityThread.java:5811)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:791)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:681)
So my question are - 1) Is it necessary to use same package name to use .so file in our application as that of .so file.
2) How I can get different .so file directory - currently for time being I had extracted it from apk.
3) To use of .so file is to hide the native code only or there is any other purpose also there?
Thanks in advance.
Your application package name may be anything, but the Java class that consumes native methods implemented in libnative-lib.so must be exactly the same as intended by the authors of this libnative-lib.so file.
The easiest workaround for your setup is to move your com.app.androidkt.differentpackage.MainActivity class to the com.app.androidkt.samplendk package. Android Studio will help you with this refactoring. Note that now you must declare the full path for MainActivity in your AndroidManifest.xml.
Alternatively, you can create a small com.app.androidkt.samplendk.MainActivity
class:
package com.app.androidkt.oldpackage;
public class MainActivity {
static {
System.loadLibrary("native-lib");
}
public native String isPrimeNumber(int number);
}
and add few lines to your MainActivity.java:
package com.app.androidkt.differentpackage;
public class MainActivity extends AppCompatActivity {
private com.app.androidkt.oldpackage.MainActivity pmSolver;
private String isPrimeNumber(int number) {
return pmSolver.isPrimeNumber(number);
}
…
}
If you don't know the exact package name used for this libnative-lib.so, you can find it by parsing its ELF headers: you will see an exported function named similar to Java_com_app_androidkt_ samplendk_MainActivity_isPrimeNumber.
Nitpicker's corner: it is possible to build a JNI library that will hide its designated class name(s), but it is hard to reliably prevent reverse engineering these names; it is also possible to build a JNI library that will seamlessly connect to different packages.
1) Is it necessary to use same package name to use .so file in our
application as that of .so file
No, you can use any package name you desire
2) How I can get different .so file directory - currently for time
being I had extracted it from apk
Copy all .so files to your new project folder: src/main/jniLibs/armeabi
3) To use of .so file is to hide the native code only or there is any
other purpose also there?
.so file is a library. Hence the purpose is to be convenient in reusing implemented features in multiple projects.

Load external classes in Android

I'm trying to load dynamically external classes using DexClassLoader, like #Shlublu proposes here
When I execute my application and the DexClassLoader object try to find the class, it throws a ClassNotFound exception. I have added read and write permissions in the manifest.xml, so it is not the mistake.
I think the problem is the method that I use to make the .jar that I want to load on my application. So I have some questions...
What is the correct method to convert a .java file to .jar using dx
tool?
It is necessary that the package where the external class is loaded be the same that the package of my .jar file? (I think no)
I'm using an Android emulator API 19 (kit-kat)
Since APK is the standard Android package, my suggestion is that you use an APK instead of a JAR. Build an application APK linking the needed JAR (let the Android build tools "dex" the JAR) but without any activity, then install the APK as if it was a normal app. You can then access the APK file itself using the PackageManager to get its path and load it using DexClassLoader.
public static ClassLoader loadAPK(final Context context, final String appName) throws PackageManager.NameNotFoundException {
final String apkPath = context.getPackageManager().getApplicationInfo(appName, 0).sourceDir;
final File tmpDir = context.getDir("tmp", 0);
return new DexClassLoader(apkPath, tmpDir.getAbsolutePath(), null, context.getClassLoader());
}

Android Studio JNI: Loop of ClassNotFoundException

I'm creating a C++ Android APP based of the book Pro Android NDK and this tutorial (http://www.swig.org/Doc2.0/Android.html#Android_example_class)
I created a C++ class called Http that creates sockets to perform simple HTTP requests (mostly for learning purposes). The C++ app works on its own.
I compiled it to JNI (using Swig) and generated the appropriate JNI code and the Java "proxy" files which I can use to call the code.
My original C++ constructor has this signature:
Http::Http(const char * ip_address, int port)
1) In my AndroidStudio app I have an Activity called MainActivity. The Package containing the MainActivity and the generated JNI Java classes is com.zuzile. My default constructor looks like this SWIGEXPORT jlong JNICALL Java_com_zuzile_exampleJNI_new_1Http(JNIEnv *jenv, jclass jcls, jstring jarg1, jint jarg2) where "exampleJNI" is my Java class that contains the native method public final static native long new_Http(String jarg1, int jarg2);
2) After generating the appropriate JNI and corresponding Java classes I successfully compiled the JNI code into a .so file using NDK. I was able to load the .so file by calling System.loadLibrary("httpreq") httpreq is the name of my compiled module.
3) When I try to use my Module by calling Http("some IP address", "a port") I get the following error: java.lang.ClassNotFoundException: com.zuzile.MainActivity (as output by the Debugger).
If I remove the Http(...) declaration from my MainActivity.java my APP loads perfectly without crashing. But as soon as I use the Native code I generated it states it can't find com.zuzile.MainActivity.
I appreciate any help in advance as I've been stuck on this for 3 days now.
JNI is just an interface between JAVA and C/C++, you can't map directly c++ class to Jave class. you can just call mapped methods.
In your case, Http("some IP address", "a port") means java constructor, but you don't have a java class named "Http", right?

Categories

Resources