I am trying to import an android project to my Eclipse.
When i run this project, i got an error, "library is null".
I figured out that this project was different, it contain a file named "jni". My library is in that file.
I guess the library in this file was never compiled (i don't know why)
I have seen in some topic that i need to use NDK?
Did any one have a clear answer about this?
Refer the below links. link to download ndk sample 1 sample 2
Step1: First create a project then create a folder named jni in your project directory
Step2: Create addition.c file in jni folder and add the below lines.
#include "com_ndkadd_Addition.h"
JNIEXPORT jint JNICALL Java_com_ndkadd_Addition_messageFromNativeCode
(JNIEnv * env, jobject jObj,jint value1, jint value2)
{
return (value1 + value2);
}
Step3: Create Android.mk file in jni folder and the below code
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := Addition
LOCAL_SRC_FILES := addition.c
include $(BUILD_SHARED_LIBRARY)
Step4: navigate to bin folder of your project from command prompt. type the below line and press enter.
javah -jni com.ndkadd.Addition
Step5: Move the created com_ndkadd_Addition.h file to jni folder.
Step6: Now Compiling the Native Code as below from command prompt.
location_of_ndk\project_name> location_of_ndk\ndk-build
Step7: below the code code for your activity and usage of created .so file in your libs folder.
public class Addition extends Activity {
TextView txtHello;
static
{
System.loadLibrary("Addition");
}
public native int messageFromNativeCode(int v1,int v2);
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
TextView txtHello = new TextView(this);
txtHello.setText(""+messageFromNativeCode(5,5));
setContentView(txtHello);
}
}
Note:: Better to have NDK in the place where you have SDK and the project containing JNI in android-ndk-r8 folder.
Related
I'm trying to use the NDK, and I've been working with official samples to get started. I've managed to get the "Hello JNI" sample working :
https://github.com/googlesamples/android-ndk/tree/master/hello-jni
(I work with Android Studio)
But I don't know how to add source files to the project. So, for example, the JNI function provided is (I removed macros that aren't useful for this) :
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, "Hello from JNI !");
}
Let's say I want to get the string from a C function "getString()", defined as below:
const char* getString()
{
return "Hello from getString()";
}
//Then, JNI function becomes
jstring Java_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env,
jobject thiz )
{
return (*env)->NewStringUTF(env, getString());
}
If I create a getString.h where I declare the function, and put the implementation in my current and only one source file, everything works like a charm. So, headers do work.
However, If I create a GetString.c file where I put the implementation, my code stops compiling. I do understand it's because GetString.o doesn't get linked (or even compiled ? I don't know), but I have no idea about how to tell Android Studio to compile both hello-jni.c (sample's source fil) and GetString.c
Should I get my hands dirty and modify gradle files ?
I also heard about a file called Android.mk which acts like a makefile, but I haven't found it in the project. If it's mandatory, should I create it, and what to put in it ? If it's not, how does the IDE knows he must build hello-jni.c ? (AKA "how did the project get configured before I modified it")
If you need any information about java-side things or gradle scripts, just have a look on the github link :)
Well, a bit of testing was enough to confirm what I thought. I just had to create Android.mk :
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES := hello-jni.c, GetString.cpp
LOCAL_MODULE := hello-jni
include $(BUILD_SHARED_LIBRARY)
I wanna realize this idea. I spent several days searching for information, but could not find anything. All tutorials say how to write my own library with JNI, but how to wrap already existing? I need just simple tutorial step by step (and why? if it possible). So I wanna start create native android application.
What I have :
I create C++ library in QTCreator by tutorial from youtube: simple library on C++ (.so) with headers (.h) which do simple cout in console:
Not compiled code mylib.cpp:
#include "mylib.h"
MyLib::MyLib() { }
void MyLib::Test() {
qDebug() << "Hello from our DLL";
// .so
}
Header mylib.h:
#ifndef MYLIB_H
#define MYLIB_H
#include "mylib_global.h"
#include <QDebug>
class MYLIBSHARED_EXPORT MyLib
{
public:
MyLib();
void Test();
};
#endif // MYLIB_H
and mylib_global.h (I think it does't matter)
So after build I have myLib.so.
And now I need wrap it in my android app. So I don't understand what I need to do for it.
I'm develop in Android Studio. And what I know:
Create in java package LibWrappClass with native method - something like "simplePrint()":
public native void simplePrint();
I need to create in /src/main folder "jni". Create Android.mk, myLibWrapper.h and myLibWrapper.cpp. But I don't understand what I need to write in Android.mk for connect my myLib.so to "myLibWrapper.h", and where should I put my library with headers. Can anyone help?
After adding the native method in your java code, You simply build the project. Now you need to move to the location where the class files are written by your IDE. Since you use Android Studio, it must be somewhere your project folder with path
out/production/YourModuleName
Open the location in commandline and run the javah command to generate the header file for your native function
javah -d <your jni folder path> <com.YourPackage.YourClass>
The class YourClass should be where you have declared the native method. This command will create a header file with name something like com_YourPackage_YourClass.h with a function declaration looks like
JNIEXPORT void JNICALL Java_com_YourPackage_YourClass_simplePrint
(JNIEnv *, jobject);
Implement this function in a C/C++ file with whatever operations you have to perform on jni side.
Then, Define the Android.mk file, In this case it will be something like
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := lib
LOCAL_SRC_FILES := lib.c
include $(BUILD_SHARED_LIBRARY)
If you have multiple source files add them in LOCAL_SRC_FILES separated by space.
Next, go to your jni folder and build the project using command ndk-build. This will place the .so file inside the android folder libs/armeabi
Finally rebuild the Android project from Android studio and run.
For detailed instructions and complete source checkout this gist
I am working setting up the NDK for my android project.
I have an android project with a textview that outputs to the emulator
"Output="
I have a native function called somefunc() that i add to this string and it throws an error stating.
E/AndroidRuntime(2242): java.lang.UnsatisfiedLinkError: Native method not found: com.ndktest.MainActivity.somefunc:()I
I have three files that I believe are needed. MainActivity.java , test.c, and Android.mk.
In test.c I have
#include <string.h>
#include <jni.h>
JNIEXPORT int JNICALL
Java_com_ndktest_MainActivity_somefunc(JNIEnv * env, jobject obj)
{
return 2;
}
And Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := test
LOCAL_SRC_FILE := test.c
include $(BUILD_SHARED_LIBRARY)
And MainActivity.java
package com.ndktest;
import com.ndktest.R;
import android.os.Bundle;
import android.app.Activity;
import android.util.Log;
import android.widget.TextView;
public class MainActivity extends Activity {
static
{
System.loadLibrary("test");
}
public native int somefunc();
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = new TextView(getBaseContext());
tv.setTextSize(30);
String s = "Ouput="+somefunc();
tv.setText(s);
this.setContentView(tv);
}
}
I understand from the various guides online that spelling mistakes are the most common cause of this error. I have tried my best to check for a spelling mistake in the package and in the c function code and so far I don't see it. I also am able to run "ndk-build" on the makefile and it compiles without errors. It produces libtest and i load the library. I have tried a try catch around it and the try passes for the system load library. So i assume there is a spelling mistake or an error in how i named my c function. I have read that the c function should be called in Java_[package with underscores instead dots][java class][function name]. I think i am abiding by this. I apologize i the first half of question looks like a stereotypical "solve this for me" question. I just wanted the code there so it shows what the packages are called and what the make looks like.
Thank you
You can get the correct prototypes for your native functions by calling
javah -classpath bin/classes -d jni com.ndktest.MainActivity
from your source directory. This will create a header com_ndktest_MainActivity.h which can be included in your C file.
(BTW: if your native file is compiled as C++ you would need extern "C" {...})
Can you try changing from
JNIEXPORT int JNICALL
to
JNIEXPORT jint JNICALL
I have small C++ library project with one class.
class Test
{
public:
Test(){};
~Test(){};
int SomeFunc() { return 5; }
}
I can build this class via Android NDK. (Question 1).
I can use .so file into Java application. How I can call SomeFunc method from Java code (Question 2).
Here are the steps:
1.) Create Android.mk in the project's "jni" folder:
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main_jni
LOCAL_CFLAGS :=
LOCAL_SRC_FILES := main.cpp
LOCAL_LDLIBS :=
include $(BUILD_SHARED_LIBRARY)
2.) Create main.cpp in the "jni" folder:
#include <jni.h>
using namespace std;
#ifdef __cplusplus
extern "C" {
#endif
class Test {
public:
Test(){};
~Test(){};
int SomeFunc() { return 5; }
};
jint Java_com_example_activity_MainActivity_SomeFunc(JNIEnv *env, jobject thiz)
{
Test *test = new Test();
return test->SomeFunc();
}
#ifdef __cplusplus
}
#endif
3.) Add a call to load the library in your calling activity (MainActivity.java in this example):
static {
System.loadLibrary("main_jni");
}
4.) Define the native function in the calling activity:
native int SomeFunc();
5.) Call it from the activity:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView text = (TextView) this.findViewById(R.id.text);
text.setText(String.valueOf(SomeFunc()));
}
6.) Run the "ndk-build" command from the project's root folder (Note: refresh the project in Eclipse after this step)
7.) Re-build and run the application
I'm not sure I understand the questions correctly but this link could be useful to you.
I'm personally do not know much of C except for the very basics, but I look forward to getting to more C with the NDK.
Whatever code you write in c you need to define it like java_urpackagename_class_methodname then before using this code u need to first create a native method in java class like public native int ABC(); telling it that you are going to use this method.To use it do create an Android.mk or Application.mk as per your need. .so will help your java class know ,what your c code wants to do.
Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking us to recommend or find a tool, library or favorite off-site resource are off-topic for Stack Overflow as they tend to attract opinionated answers and spam. Instead, describe the problem and what has been done so far to solve it.
Closed 9 years ago.
Improve this question
Hi, can anyone suggest me some good resources to learn JNI for Android and some good JNI Tutorials?
Tutorial for ECLIPSE
Here is first and second small tutorials, but if you want to write a simple program that uses JNI , you may continue reading :)
Create Android application project , Once your project has been created, you’ll need to create a new folder inside the top level of the project. To do this right click on your project name → New → Folder. Name this folder jni. Than add class with name SquaredWrapper. add these code in it
package org.edwards_research.demo.jni;
public class SquaredWrapper {
// Declare native method (and make it public to expose it directly)
public static native int squared(int base);
// Provide additional functionality, that "extends" the native method
public static int to4(int base)
{
int sq = squared(base);
return squared(sq);
}
// Load library
static {
System.loadLibrary("square");
}
}
Open terminal. You must compile these code for getting header file. At first call this command.
cd src # change into the source directory
javac -d /tmp/ org/edwards_research/demo/jni/SquaredWrapper.java
Than
cd /tmp
javah -jni org.edwards_research.demo.jni.SquaredWrapper
SO you'll have header file named org.edwards_research.demo.jni.SquaredWrapper in your tmp directory.
it must be something like this
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class org_edwards_research_demo_jni_SquaredWrapper */
#ifndef _Included_org_edwards_research_demo_jni_SquaredWrapper
#define _Included_org_edwards_research_demo_jni_SquaredWrapper
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: org_edwards_research_demo_jni_SquaredWrapper
* Method: squared
* Signature: (I)I
*/
JNIEXPORT jint JNICALL Java_org_edwards_1research_demo_jni_SquaredWrapper_squared
(JNIEnv *, jclass, jint);
#ifdef __cplusplus
}
#endif
#endif
change these name for some short one for your comfort, for example square.h. Copy this header file in the jni folder of your app. Than create square.c file in same folder, copy this in it.
#include "square.h"
JNIEXPORT jint JNICALL Java_com_example_android_1jni_1second_1demo_SquaredWrapper_squared
(JNIEnv * je, jclass jc, jint base)
{
return (base*base);
}
Add this in your MainActivity.java
int x = SquaredWrapper.to4(2);
x = x*2;
Add Android.mk file in jni folder with this body
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := squared
LOCAL_SRC_FILES := square.c
include $(BUILD_SHARED_LIBRARY)
It must create library from header and cpp files.
So you have only to do some configurations by looking on my first link
Now you can compile it , be sure that your library has created and your lib directory consist it.
Tutorial for Android Studio
Let's consider you have simple android application opened by Android Studio
step 1: open Your application by Android Studio
step 2: Download NDK and set the path to NDK in local properties of your application(below/above of android sdk path) like this ndk.dir=C\:\\Android\\android-ndk-r10e
P.S. for windows double // , for linux one /
step3: Add JNI folder in the app (right click on the app -> new -> folder -> JNI Folder)
step 4 Set up the Gradle by this way:
Add this code in app/build.gradle for starting NDK
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
tasks.withType(NdkCompile) { // disable automatic ndk-build call
compileTask -> compileTask.enabled = false
}
task ndkBuild(type: Exec) { // call ndk-build(.cmd) script
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
commandLine 'cmd', '/c', 'ndk-build.cmd', '-C', file('src/main').absolutePath
} else {
commandLine 'ndk-build', '-C', file('src/main').absolutePath
}
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn ndkBuild
}
step 4:
Create files Android.mk and Application.mk in JNI folder of the app with this bodies:
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := main
LOCAL_SRC_FILES := main.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all
include $(BUILD_SHARED_LIBRARY)
In APP_ABI you choose which compilers to use. It
step 5:
We have to manually run NDK as we disable it from build.config. For creating com_example_nativedemo_app_MainActivit.h file in src\main\jn folder we have to run this command in terminal
javah -d .\jni -classpath C:\Intel\INDE\IDEintegration\android-sdk-windows\platforms\android-21\android.jar;..\..\build\intermediates\classes\debug com.example.mydemo.nativedemo.MainActivity
for windows cmd you have to give the full path of files.
For
step 6:
Add file main.cpp in JNI folder with this body:
#include <string.h>
#include <jni.h>
#include <vchat_cpptest_Hellojnicpp.h>
extern "C" {
JNIEXPORT jstring JNICALL
Java_vchat_cpptest_Hellojnicpp_stringFromJNI
(JNIEnv *env, jobject obj)
{
#ifdef __INTEL_COMPILER_UPDATE
return env->NewStringUTF("Hello from Intel C++ over JNI!");
#else
return env->NewStringUTF("Hello from default C++ over JNI!");
#endif
}
I would suggest downloading the ndk. Unzip it and browse the sample folder ndk codes. Start with the hello-jni and go further. It explains a lot with ease.
You can also browse these links and this while going through the code and keep coming back and forth.