I found some similar questions, but their answers didn't help me. I went through this tutorial http://mindtherobot.com/blog/452/android-beginners-ndk-setup-step-by-step/ and get some problems with it.
My Android.mk file :
LOCAL_PATH := $(call my-dir)
MY_PATH := $(LOCAL_PATH)
include $(call all-subdir-makefiles)
include $(CLEAR_VARS)
LOCAL_PATH := $(MY_PATH)
LOCAL_LDLIBS := -llog -ldl
LOCAL_MODULE := ndkfoo
LOCAL_SRC_FILES := ndkfoo.c
include $(BUILD_SHARED_LIBRARY)
And my c-class ndkfoo.c :
#include <jni.h>
#include <string.h>
#include <android/log.h>
#include <string.h>
#include <jni.h>
jstring Java_com_example_ocrrecognise_ndkfoo_MainActivity_invokeNativeFunction(JNIEnv* env, jobject javaThis) {
return (*env)->NewStringUTF(env, "Hello from native code!");
}
and MainActivity:
public class MainActivity extends Activity {
static {
System.loadLibrary("ndkfoo");
}
private native String invokeNativeFunction();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
final Button button = (Button) findViewById(R.id.button_id);
button.setOnClickListener(new View.OnClickListener() {
public void onClick(View v)
{
try{
String hello = invokeNativeFunction();
Log.i("string func", hello);
}catch (UnsatisfiedLinkError e)
{
e.printStackTrace();
}
//new AlertDialog.Builder(MainActivity.this).setMessage(hello).show();
}
});
}
But I've got
No implementation found for native Lcom/example/ocrrecognise/MainActivity;.invokeNativeFunction ()Ljava/lang/String;
java.lang.UnsatisfiedLinkError: invokeNativeFunction
at com.example.ocrrecognise.MainActivity.invokeNativeFunction(Native Method)
at com.example.ocrrecognise.MainActivity.access$0(MainActivity.java:14)
at com.example.ocrrecognise.MainActivity$1.onClick(MainActivity.java:24)
at android.view.View.performClick(View.java:2485)
at android.view.View$PerformClick.run(View.java:9080)
at android.os.Handler.handleCallback(Handler.java:587)
at android.os.Handler.dispatchMessage(Handler.java:92)
at android.os.Looper.loop(Looper.java:123)
at android.app.ActivityThread.main(ActivityThread.java:3687)
at java.lang.reflect.Method.invokeNative(Native Method)
at java.lang.reflect.Method.invoke(Method.java:507)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:867)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:625)
My in the ndkfoo.c I put right package name. Help with it please.
In what package your Activity is in?
Please mind that is should be under com.example.ocrrecognise.ndkfoo.
How did you compile your c code?
Did you put the compile .so file under /libs/armeabi in your project?
From the error
No implementation found for native Lcom/example/ocrrecognise/MainActivity;.invokeNativeFunction
it appears that your main activity is in the package com.example.ocrrecognise. If you place it in package com_example_ocrrecognise_ndkfoo, it should work, since that is the prefix that you are using in declaring the function in your native code.
Related
It gives an error and couldn't load .so files. I searched it on the internet and read many things but didn't find an answer. I tried to use System.loadLibrary("jni_latinime") but it failed again. Please give me any advice. Thanks.
java.lang.UnsatisfiedLinkError: dalvik.system.PathClassLoader[DexPathList[[zip file "/data/app/com.android.inputmethod.latin-1/base.apk"],nativeLibraryDirectories=[/data/app/com.android.inputmethod.latin-1/lib/arm, /vendor/lib, /system/lib]]] couldn't find "libjni_latinime.so"
at java.lang.Runtime.loadLibrary(Runtime.java:367)
at java.lang.System.loadLibrary(System.java:1076)
at com.android.inputmethod.latin.utils.JniUtils.<clinit>(JniUtils.java:33)
at com.android.inputmethod.latin.utils.JniUtils.loadNativeLibrary(JniUtils.java:46)
at com.android.inputmethod.latin.LatinIME.<clinit>(LatinIME.java:599)
at java.lang.Class.newInstance(Native Method)
at android.app.ActivityThread.handleCreateService(ActivityThread.java:2877)
at android.app.ActivityThread.-wrap4(ActivityThread.java)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1437)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:148)
at android.app.ActivityThread.main(ActivityThread.java:5443)
at java.lang.reflect.Method.invoke(Native Method)
at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:728)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:618)
1.Set NDK PATH
2.add this in build.gradle
sourceSets.main {
jni.srcDirs = []
jniLibs.srcDir 'src/main/libs'
}
3.Create a Jni folder inside SRC direactory
4.Create- Android.mk--inside jni folder-
5.add in Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := "module name"//added inside system.load(); ** i used addjni**
LOCAL_SRC_FILES := Native.c //create a native.c class
LOCAL_LDLIBS := -llog -ljnigraphics
include $(BUILD_SHARED_LIBRARY)
6.Create a file Application.mk---inside jni folder----------------
and write this
APP_ABI := all
7.add inside MainActivity
public class MainActivity extends AppCompatActivity {
static {
System.loadLibrary("addjni");
}
TextView sum;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
sum=(TextView)findViewById(R.id.sum);
int as=Native.sumoftwo(210,15);
Log.e("sum",as+"");
sum.setText(as+"");
}
}
8.create a new NativeNDK.c
//inside jni folder and add this
//jave_packageName_Native(Classname)_(methodname) replace(. with -)
include<string.h>
include<jni.h>
jint JNICALL Java_droider_Native_sumoftwo(JNIEnv* env , jclass obj,jint a,jint b)
{
jint total=(a+b);
return total;
}
9. go to studio terminal and inside type command
cd app\src\main>D:\android-ndk-r10d\android-ndk-r10d\ndk-build APP_PLATFORM=android-8 enter
10. Native.c inside main/src
public class Native {
public native static int sumoftwo(int a,int b);
static {
System.loadLibrary("addjni");
}
}
11.copy all .so from libs and paste into jinLibs if exist else create and paste
Go to LatinIME/native/jni and build it with ndk-build..
(if it contains errors just open Android.mk and comment this line :
# LOCAL_CFLAGS += -Werror -Wall -Wextra -Weffc++ -Wformat=2 -Wcast-qual -Wcast-align \
# -Wwrite-strings -Wfloat-equal -Wpointer-arith -Winit-self -Wredundant-decls \
# -Woverloaded-virtual -Wsign-promo -Wno-system-headers
This will build jni_latinime.so file...
You can add it to your build.gradle by giving this code:
sourceSets {
main {
jniLibs.srcDirs = ['LOCATION OF .so File']
}
}
I'm new to NDK and JNI and not sure how to fix this error. I manually copy libMathFuncLib.so, mathFuncsLibs.cpp and MathFuncLibs.h files to Eclipse project. When I run this command 'ndk-build' and I get back 'workspace/test/jni/TestMath.cpp: error: 'Add' was not declared in this scope.'
Here is my folder structure:
-test
|__src
|__ExecuteTest.java
|__MainActivity.java
|__jni
|__Android.mk
|__Application.mk
|__TestMath.cpp
|__libs
|__armeabi
|__myLibs
|__armeabi
|__libMathFuncLib.so
|__myNatives
|__MathFuncLibs.cpp
|__MathFuncLib.h
Here is MathFuncLib.h file:
//This is static library example
#ifndef MathFuncLib_INCLUDED
#define MathFuncLib_INCLUDED
#ifdef __cplusplus
extern "C" {
#endif
class MyMathFunc
{
public:
static int Add(int a, int b);
static int Subtract(int a, int b);
static int Multiply(int a, int b);
static double Divide(int a, int b);
};
#ifdef __cplusplus
} // extern "C"
#endif
#endif
Here is MathFuncLib.cpp file:
#include "MathFuncLib.h"
int MyMathFunc::Add(int a, int b)
{
return a + b;
}
int MyMathFunc::Subtract(int a, int b)
{
return a - b;
}
int MyMathFunc::Multiply(int a, int b)
{
return a * b;
}
double MyMathFunc::Divide(int a, int b)
{
return a / b;
}
Here is MainActivity.java file:
package com.example.test;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.widget.TextView;//to use TextView
import android.widget.GridLayout.LayoutParams;//to use LayoutParams
public class MainActivity extends AppCompatActivity {
#Override
protected void onDestroy() {
// TODO Auto-generated method stub
super.onDestroy();
}
#Override
protected void onStop() {
// TODO Auto-generated method stub
super.onStop();
}
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
int retVal = 0;
ExecuteTest et = new ExecuteTest();
retVal = et.TestAdd();
TextView tv = new TextView(this);
LayoutParams lp = new LayoutParams();
lp.setMargins(150, 50, 200, 0);
tv.setLayoutParams(lp);
tv.setText(String.valueOf(retVal));
setContentView(tv);
}
#Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
#Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle action bar item clicks here. The action bar will
// automatically handle clicks on the Home/Up button, so long
// as you specify a parent activity in AndroidManifest.xml.
int id = item.getItemId();
if (id == R.id.action_settings) {
return true;
}
return super.onOptionsItemSelected(item);
}
}
Here is ExecuteTest.java file:
package com.example.test;
import android.util.Log;
public class ExecuteTest {
public int ReturnValue(){
return 50;
}
public native int TestAdd();
static
{
System.loadLibrary("MathFuncLib");
System.loadLibrary("Arithmetic");
Log.i ("ExecuteTest", "Shared Libs loaded");
}
}
Here is TestMath.cpp file:
#include <jni.h>
#include <string.h>
#include <android/log.h>
#include "../myNatives/MathFuncLib.h"
extern "C"
{
JNIEXPORT int JNICALL Java_com_example_test_ExecuteTest_TestAdd(JNIEnv *env, jobject obj)
{
__android_log_print(ANDROID_LOG_INFO, "Test", "Inside TestAdd()");
int retVal= Add(50,50);//Add(,) is a method inside MathFuncLib.so file
return retVal;
}
}
Here us my Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MathFuncLib-prebuilt
LOCAL_SRC_FILES := ../myLibs/armeabi/libMathFuncLib.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := Arithmetic
LOCAL_SRC_FILES := TestMath.cpp
LOCAL_LDLIBS := -llog -lz
include $(BUILD_SHARED_LIBRARY)
Here is Application.mk file:
APP_STL := gnustl_shared
Thanks.
This is the correct form for
Application.mk
APP_ABI := x86 ## -- set to whatever platform you need
APP_PLATFORM := android-9
APP_STL := stlport_static ## -- USE IT
.
As for Android.mk you will need 2, because I see you want to build a solution using two projects --
a native (non-JNI) library
2nd native (JNI) library, that loads the first and makes it available to JAVA through JNI
Application.mk should be duplicated.
.
Android.mk (the native part)
include $(CLEAR_VARS)
#
# --------------- C / C++ Project settings ---------------
#
LOCAL_PATH := _path_to__myNatives
# Application/Library Name
LOCAL_MODULE := MathFunc
# Project Source files
LOCAL_SRC_FILES := MathFuncLibs.cpp
# Compiler Flags
LOCAL_CFLAGS := -mfpu=neon
### THIS BIT BELOW IS IMPORTANT -- used so that projects that include this build output will find the correct headers ###
# Location of headers
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/.
#
# ------------------------- .. ----------------------------
#
include $(BUILD_STATIC_LIBRARY)
.
You would be using Eclipse, so you can then find the output in _path_to__myNatives/obj/local/$(TARGET_ARCH_ABI)/libMathFunc.a. $(TARGET_ARCH_ABI) evaluates to x86 in this example.
Need to build once for your platform (specified in Application.mk).
.
Android.mk (the native JNI part )
replace "Static" with "Shared" (no quotes ofc)
#
# -------------- Dependant Static Libraries Linkage ---------------
#
include $(CLEAR_VARS)
LOCAL_PATH := _path_to__myNatives
LOCAL_MODULE := MathFuncLib ## can be different from the previous module name definition in Android.mk or can be the same
LOCAL_SRC_FILES := $(LOCAL_PATH)/obj/local/$(TARGET_ARCH_ABI)/libMathFunc.a
include $(PREBUILT_STATIC_LIBRARY)
#
# ------------------------- .. ----------------------------
#
#
# --------------- C / C++ Project settings ----------------
#
include $(CLEAR_VARS)
LOCAL_PATH := _path_to___jni
# Application/Library Name
LOCAL_MODULE := Arithmetic
# Project Source files
LOCAL_SRC_FILES := TestMath.cpp
# Compiler Flags
LOCAL_CFLAGS := -mfpu=neon
LOCAL_LDLIBS := -llog -lz
# Static Libraries
LOCAL_STATIC_LIBRARIES := MathFuncLib # must be exactly the same as in THIS .mk file
# Shared Libraries
#LOCAL_SHARED_LIBRARIES := MathFuncLib # must be exactly the same as in THIS .mk file
#
# ------------------------- .. ----------------------------
#
include $(BUILD_SHARED_LIBRARY)
Just want to share my fixed.
1) in my MyMathFunc.h file, I shouldn't use "extern C" because C does not support class. If wanting to use "extern C" then I have to remove class declaration.
2) need to change Android.mk and Application.mk files.
Android.mk file:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := MathFuncLib
LOCAL_SRC_FILES := ../myLibs/armeabi/libMathFuncLib.so
include $(PREBUILT_SHARED_LIBRARY)
include $(CLEAR_VARS)
LOCAL_SHARED_LIBRARIES := MathFuncLib
LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/../myNatives/
LOCAL_MODULE := Arithmetic
LOCAL_SRC_FILES := TestMath.cpp
LOCAL_LDLIBS := -llog -lz
#Tell it to build an APK
include $(BUILD_SHARED_LIBRARY)
Application.mk file:
APP_STL := gnustl_shared
I'm developing an image processing application using Opencv and android Ndk.
First I wrote my code in visual studio and there was no problem.
I have header roi.hpp and roi.cpp :
roi.hpp:
#ifndef ROI
#define ROI
#include <..\..\imgproc.hpp>
#include <..\..\opencv.hpp>
using namespace cv;
class My_ROI{
public:
My_ROI();
My_ROI(const My_ROI &my_roi);
My_ROI(Point upper_corner, Point lower_corner,Mat src);
Point upper_corner, lower_corner;
Mat roi_ptr;
Scalar color;
int border_thickness;
void draw_rectangle(Mat src);
};
#endif
roi.cpp:
#include "myImage.hpp"
#include <..\..\imgproc.hpp>
#include <..\..\opencv.hpp>
#include <..\..\highgui.hpp>
#include <stdio.h>
#include <stdlib.h>
#include <string>
#include "roi.hpp"
using namespace cv;
using namespace std;
My_ROI::My_ROI(const My_ROI &my_roi)
{
int i;
// allocate variables
My_ROI();
// copy values
operator = (my_roi);
}
My_ROI::My_ROI(){
upper_corner=Point(0,0);
lower_corner=Point(0,0);
}
My_ROI::My_ROI(Point u_corner, Point l_corner, Mat src){
upper_corner=u_corner;
lower_corner=l_corner;
color=Scalar(0,255,0);
border_thickness=2;
roi_ptr=src(Rect(u_corner.x, u_corner.y, l_corner.x- u_corner.x,l_corner.y- u_corner.y));
}
void My_ROI::draw_rectangle(Mat src){
rectangle(src,upper_corner,lower_corner,color,border_thickness);
}
and in another class I made a vector of My_ROI and use it with no problem, Like this:
vector <My_ROI> roi;
for (int j = 0; j<NSAMPLES; j++){
roi[j].draw_rectangle(m->src);
}
Then I ported my project to android I use roi.hpp and roi.cpp as external c++ files ,this is my android.mk:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
OPENCV_CAMERA_MODULES := on
OPENCV_INSTALL_MODULES := on
OPENCV_LIB_TYPE:=STATIC
include ../../jni/OpenCV.mk
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.cpp
LOCAL_SRC_FILES += ../../external_cpp/makegray.cpp
LOCAL_SRC_FILES += ../../external_cpp/roi.cpp
LOCAL_C_INCLUDES += $(LOCAL_PATH)/../../external_cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
application.mk:
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
APP_ABI := armeabi-v7a
APP_PLATFORM := android-8
And finally in hello-jni.cpp file I want to use vector of roi:
#include <jni.h>
#include <opencv2/highgui/highgui.hpp>
#include <opencv2/imgproc/imgproc.hpp>
#include <android/log.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <string>
#include <vector>
#include <cmath>
#include <opencv2/opencv.hpp>
#include "../../external_cpp/roi.hpp"
vector <My_ROI> roi;
void fillROIArray(MyImage *m,Mat& mRgb,Mat& mGray)
{
m->src=mRgb;
flip(m->src,m->src,1);//reverse the order of rows or cols in a matrix
// My_ROI *f1 = new My_ROI;
// roi.push_back(*f1);
roi.push_back(My_ROI(Point(m->src.cols/3, m->src.rows/6),Point(m->src.cols/3+square_len,m->src.rows/6+square_len),m->src));
roi.push_back(My_ROI(Point(m->src.cols/4, m->src.rows/2),Point(m->src.cols/4+square_len,m->src.rows/2+square_len),m->src));
roi.push_back(My_ROI(Point(m->src.cols/3, m->src.rows/1.5),Point(m->src.cols/3+square_len,m->src.rows/1.5+square_len),m->src));
roi.push_back(My_ROI(Point(m->src.cols/2, m->src.rows/2),Point(m->src.cols/2+square_len,m->src.rows/2+square_len),m->src));
roi.push_back(My_ROI(Point(m->src.cols/2.5, m->src.rows/2.5),Point(m->src.cols/2.5+square_len,m->src.rows/2.5+square_len),m->src));
roi.push_back(My_ROI(Point(m->src.cols/2, m->src.rows/1.5),Point(m- >src.cols/2+square_len,m->src.rows/1.5+square_len),m->src));
roi.push_back(My_ROI(Point(m->src.cols/2.5, m->src.rows/1.8),Point(m->src.cols/2.5+square_len,m->src.rows/1.8+square_len),m->src));
mGray=m->src;
}
void myMethod(Image &m)
{
for (int j = 0; j<NSAMPLES; j++){
roi[j].draw_rectangle(m->src);
}
}
but it makes error :
method draw_rectangle(...) couldn't be resolved!
I can access my roi object all members but when I make vector of this class I don't have access to its members!
I searched a lot about making vectors of custom class and It's several days I'm working to solve this problem but I couldn't.
any help really appreciate.
regards.
Finally I found solution ... maybe it's usefull for others .
I can access to vector's members like this :
for (int j = 0; j<NSAMPLES; j++){
((My_ROI)roi[j]).draw_rectangle(m->src);
}
I can access any vector's objects from any custom classes now ! :)
I'm trying simple addition program in android ndk. But I'm getting the following exception -
java.lang.exceptionininitializererror
Java File-
public class MainActivity extends Activity {
private native void MyMethod(int a,int b);
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
MyMethod(4,5);
}
static {
System.loadLibrary("native"); // here i'm getting exception
}
}
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_LDLIBS := -llog
LOCAL_MODULE := native
LOCAL_SRC_FILES := native.c
include $(BUILD_STATIC_LIBRARY)
native.c
#include <jni.h>
#include <string.h>
#include <android/log.h>
#define DEBUG_TAG "NDKSetupActivity"
void Java_com_example_additionndk_MainActivity_MyMethod(JNIEnv * env, jobject this, jint a,jint b)
{
jint c=a+b;
__android_log_print(ANDROID_LOG_DEBUG, DEBUG_TAG, "addition: %d", c);
}
I ran into this error once when running the sample ndk (hello-jni). It's because the android sdk version is not compatible (default of the example is 1.5). Try to switch the compatible sdk and modifiy manifest .
Another case is you haven't build the .c to .so. Use ndk-build from cygwin64.
I'm working with android and trying to use some native code in my app.
Here is a skeleton of the application code:
package A.B;
/*
import statements
*/
public class C extends Activity{
public void onCreate(...){
....
foo();
....
}
public int foo(){
.....
data(a, b);
.....
}
public int data(a, b){
GetValues(a, b);
}
static{
System.loadLibrary("baz");
}
public native int GetValues(int[] a, int b);
}
the native method signature goes like this:
JNIEXPORT jint JNICALL
Java_A_B_C_GetValues(JNIEnv *env, jobject obj, jintArray arr, jint b){
....
....
}
while running the logcat shows up:
W/dalvikvm(799): No implementation found for native LA/B/C;.GetValues ([IJ)I
the ndk documentation doesnt strictly mention creating a header file, so i dont have one
the android.mk file's contents:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := baz
LOCAL_SRC_FILES := baz.cpp
include $(BUILD_SHARED_LIBRARY)
Thanks in advance.
Since your native file is a .cpp file, I am guessing that you will need to use extern "C". Why and Why