I've checked here and it seems to be no answer for my particular question. I got to know that I one can use C .so library and refer the methods in it by somewhat overriding the library native methods like below:
#SuppressWarnings("JniMissingFunction")
public class MyNativeMethods {
static {
System.loadLibrary("libraryWithSoExtension");
}
public native boolean init();
}
My probelem is that I'd like to call the constructor in this lib. The lib contains only couple of classes, where each of them contains 1 or 2 methods. I see from here:
How to call methods on .so library in Android studio
that I do not need any h, c or jni (do I really?).
Questions:
Could you confirm that I do not need any JNI files to access native methods from .so file?
Can one actually access a constructor as described above and how does the importing work if it's possible
MAVEN/GRADLE - Is it correct that a will not work for .so file? And it's equivalent in gradle also?
Thank you in advance.
If you have a prebuilt .so file that implements some native methods, you don't need its sources to build your project in Android Studio.
The catch is that the names of native methods and classes that contain these methods are hardcoded, e.g. Java_com_example_test_MainActivity_stringFromJNI exported function in a shared library libmy.so is fit to
package com.example.test;
public class MainActivity extends Activity {
static {
System.loadLibrary("my");
}
public native String stringFromJNI();
}
and not some other Java class or method (there are tools to make such reverse engineering harder).
You can use the javah command to generate C declarations for your native methods, but it cannot reverse engineer the Java class that fits given library. But it will let you declare a native constructor, if you really want one.
Gradle plugin for Android Studio will pack the so files from src/main/jniLibs into your APK, unless you set a different jniLibs.srcDir directory in your build.gradle.
I am not sure whether this is what you are looking for, but take a look here:
https://github.com/mkowsiak/jnicookbook/tree/master/recipes/recipeNo025
you will find there super simple code with C++ being called via JNI wrapper from Java.
Related
Say an Android app uses a jar library and everything is working fine when the library is specified as a dependency:
dependencies {
...
...
compile 'org.example:example:1.1.1'
...
}
BUT : one of the classes in the org.example code needs to be tweaked.
One approach is to obtain the source code and put all of that in the java folder, and remove the module. When the tweak is made, that, and the entire library will be compiled.
Another approach is to make the tweak, compile, and replace the .class file within the .jar file.
Both of those methods have their drawbacks.
My question is: Is there an easier way to tweak code in a library?
When I tried just creating the package, placing the class that needed changing into the java folder, I got an error:
Error converting bytecode to dex:
Cause: com.android.dex.DexException: Multiple dex files define Lorg/example/ClassNeedingChange;
I just wondered if there was a trick to getting code in the Java folder to override whats in a library jar file.
Additional Info:
Although not stated specifically above, the class that needs tweaking is buried in the library and is referenced by the library's code; I don't call it directly. For the simple case where the class that needed tweaking is one that my code (and only my code) called directly, then it would be a simple matter of extending the class using the Java construct. But for this simple case, I would not need to post this question.
Extend the class that needs tweaked in your code, and override the appropriate method.
Class A extends TweakMe {
#Override
public void someTweakedMethod() {
//Do stuff
}
}
I need some help to use the method "callMethod()" inside ".so" (shared library) in android studio.
My android studio version is 2.1.3.
I created jniLibs folder in "src/main/".
Then I created three folders inside jniLibs folder: (armeabi, armeabi-v7a, x86).
Then I put the .so library inside every mentioned folder.
After that, I updated the build.gradle as follows:
compile fileTree(dir: 'libs', include: ['*.jar','.so'])
In the MainActivity java class I wrote this:
static {
System.loadLibrary("SharedLibAndroid");
}
After that I don't know what should I do.
How do I call the method callMethod() from the .so library?
I searched a lot but I did't see full example how to do that.
I've added to my project new class and native method like below:
#SuppressWarnings("JniMissingFunction")
public class Test1Cpp {
static {
System.loadLibrary("Cpp");
}
public native String callMethod();
}
Then I can call the method inside .so shared library.
I faced another problem, which is my .so library didn't work with all platform mobiles.
The error is:
java.lang.UnsatisfiedLinkError: dlopen failed:
"/data/app/com.mysecondtestapp-1/lib/arm/libCpp.so" has
unexpected e_machine: 3
So, how to convert my .so library to work on all platform mobiles?
I assume that the library does load, otherwise you would get an exception, and I guess you would have mentioned it. So you need to declare the native method you would like to use from the library, and then call it. You can see a simple example here: Sample: hello-jni
The sample source code may be found here: Hello JNI.
How can I create a library in Eclipse and then import it in Robot FrameWork?
I am searching a lot now and none of the guides out to help me out.
You need to do the following:
Create your java library
Add it to the classpath when running robot framework jython edition
Creating your java library:
Define a new java class. At this point try not to use a constructor yet (although it is possible to support constructors with fields)
Define the ROBOT_LIBRARY_SCOPE static String variable in the class.
public static final String ROBOT_LIBRARY_SCOPE = "GLOBAL";
Define public methods (not static) that will be used as the keywords
Adding your library to the class path
Compile your classes - ideally to a jar
Add the jar to the class path when running jython. The easiest way to do this is with the MVN Robot Framework plugin. Another option is to wrap the jybot run in a batch file and add CLASSPATH definition to it. There are other options as well (gradle or ant for example).
Using your library in your code
You need to import your library using the full package path
import library org.robot.sample.keywords.MyLibrary
https://blog.codecentric.de/en/2012/06/robot-framework-tutorial-writing-keyword-libraries-in-java/
You can see the full example of how to add a jar when using ride in this article
https://blog.codecentric.de/en/2012/04/robot-framework-tutorial-a-complete-example/
A Java class made for video coding loads a DLL including C++ code
Unpacking debugging symbols for VideoSource.dll to \path
Checking for VideoSource.pdb...
Checking for videosource.pdb...
and then tries to instantiate a native (C++) class from that DLL:
// VideoSource() is implemented in C++ and wrapped with JNI,
// wrapper files were generated with SWIG
_videoProvider = new generated.VideoSource();
That works when the Java class is executed as a JUnit test (video data is extracted).
Same thing does not work when I launch the Java class as an OSGi service.
Essentially, the same code is executed. The DLL is still loaded successfully but the instantiation of the native (C++) class shown above now throws an exception:
java.lang.UnsatisfiedLinkError: generated.VideoSourceSWIGJNI.new_VideoSource()J
What is different when I launch the Java class as an OSGi service instead of executing it as a JUnit test? What can I do to make it work?
BACKGROUND
generated.VideoSource() is
public VideoSource() {
this(VideoSourceSWIGJNI.new_VideoSource(), true);
}
VideoSourceSWIGJNI.new_VideoSource() is
public final static native long new_VideoSource();
C++ implementation is
VideoSource::VideoSource() {
// init frame count
m_frame_cnt = 0;
[..]
}
Thanks, Puce, for pushing me a bit. After asking "would I have to try anything at all"? I got the answer relative quickly:
In order to resume sources (1, 2, 3, 4) with my own words:
When native code, e.g. .so or .dll libraries, shall be used in an OSGi bundle, corresponding libraries have to be declared in the bundle's manifest.
The manifest file may either be edited explicitely, as stated in mentioned sources, or implicitely via an appropriate plugin, e.g. apache felix, when using maven. Used plugin is configured in the POM file and will modify the manifest automatically.
I have a directory full of hundreds of class files that have been constructed by a previous compilation. Let's say I have a class which only depends upon a small subset of those generated class files. Is it possible to create a JAR which only has the dependencies for the given class?
EDIT: Please note that I am not speaking of the library level dependencies (i.e. JARs). When I refer to dependencies above, I am referring to the sort of dependency that results from class A calling class B. Perhaps an example would be good. Imagine I have the following classes in my project.
public class A {
B bField;
}
public class B {
C cField;
}
public class C {
B bField;
}
Now imagine I want to build a JAR with class B, then the JAR would also need to include the class file for C because the one depends upon the other. If I wanted to build a JAR from class A, then all three classes would be included. Is there a way to examine this dependency chain and build a JAR with the result?
Several products can do this, including ProGuard.
The danger is that without exhaustive run-time analysis, or a good understanding of your code and any frameworks it uses, some classes may be missed if they've instantiated via reflection. Plugin systems, dependency injection, scripting, and so on can all interfere with the accuracy of static analysis.
Yes it is possible. you can create a file with the list of classes that you do want to include and pass that file into the jar command. The details are documented here.