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.
Related
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.
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());
}
I had created the sample project(HellWorldJNI) that runs with Android Ndk and prints "Hello world from Jni" message from the native C.
And then i extract the HelloWorldJNI.apk file of the sample from the Output/apk directory of the project.
So i got the all the .so files from different devices(like arm64-v8a,armeabi,x86..etc)
Now i created a new project (CallJNIFromSoFile) and created jniLibs folder inside main folder , and copied the all .so files of HelloWorldJNI app into this new project.
After that i load the library and the function name of the HelloWorldJNI App like this
static {
System.loadLibrary("hello-android-jni");
}
public native static String getMsgFromJni();
Here i got strucked, i am able load the "hello-android-jni" library without any problem. But the native method getMsgFromJni() from the above is showing in RED color and not able call that method.
Not at all receiving the message "Hello world from Jni"
This is my Logcat Output:
java.lang.UnsatisfiedLinkError: No implementation found for java.lang.String
at com.example.hari.myopencvvsample.MainActivity.getMsgFromJni(Native Method)
Please suggest am i missing anything other than the above steps. I tried many ways like regenerating the .so files and then put it again,but didn't worked . Sorry for my english.
Thanks in advance.
You need to provide a JNI implementation of the method getMsgFromJni(). The .so files are shared libraries, which you can link to and use from C or C++ code, but you need to provide an interface for any C or C++ methods you plan to call from Java, hence Java Native Interface.
If you look at the src/main/jni folder in your HelloWorldJNI project, you will see a C or C++ file which implements any native methods called from Java in that project. You can also refer to the NDK samples for more help. The hello-libs example is a good place to start for your question.
This is completely bad idea to copy *so files between Android projects.
JNI will find your function by the name which depends from the name of your Android application java-class hierarchy.
Accordingly your description you compiled HelloWorldJni apk first and you have symbols there something like:
T Java_com_example_helloworldjni_MainActivity_getMsgFromJni
As you see there is your java-class hierarchy included in name of this function.
And then, you are creating your own application with different class-names and your program looks for something like:
Java_com_example_hari_myopencvvsample_MainActivity_getMsgFromJni
inside your library, but as you know - it is not there.
I'd suggest you to read the article https://developer.android.com/ndk/samples/sample_hellojni.html
with its part about c implementation carefully, and repeat all the steps for your new CallJNIFromSoFile project.
Use targetSdkVersion less than 23 it will be working fine..
defaultConfig {
versionCode 1
versionName "1.0.0"
minSdkVersion 15
targetSdkVersion 22
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.
I am working with a library as a JAR where i have added strings and sending the context of main Application to fetch string to register GCM.
This is my method in the JAR file:-
void registerGCM(Context context){
GCMLibrary.register(context, context.getString(R.string.c2dm_sender));
}
I have declared c2dm_sender in library and in my Application in Strings.
But i am getting this error:
android.content.res.Resources$NotFoundException
I have seen this Using R resources from an android jar file as a reference but not getting it resolved.
I am looking for the solution that R file of my Application is used and c2dm_sender to be used from there.
you can try this code for that......
context.getResources().getString(R.string.c2dm_sender);