I am trying to encrypt a text file from android application using .so library.
I have created a c program (encprog.c) for it and converted it into (.so) file i.e library using gcc command.
C program to encrypt a text file is as follows:
encprog.c
#include<stdio.h>
#include<jni.h>
void encrypt(char *name)
{
FILE *fp,*fp1;
int choi;
char temp[20]={"Temp.txt"},c;
fp=fopen(name,"r+");
if(fp==NULL)
{
printf("The file %s can't be open",name);
}
fp1=fopen(temp,"w+");
if(fp1==NULL)
{
printf("The file Temp can't be open");
}
c=fgetc(fp);
while(c!=EOF)
{
fputc((c+name[0]),fp1);
c=fgetc(fp);
}
fclose(fp);
fclose(fp1);
remove(name);
rename(temp,name);
}
void main()
{
char name[20]={"hello.txt"};
JNIEXPORT jint JNICALL Java_com_example_soencryptiondemo_EncryptionSoClass_encrypt(JNIEnv * env, jobject obj, jint a, jint b)
{
return 1;
}
encrypt(name);
}
I have included .so file i.e libencprog.so in my android application in libs/armeabi-v7a folder.
Class that loads .so file is as follows
EncryptionSoClass.java
package com.example.soencryptiondemo;
public class EncryptionSoClass {
/* load our native library */
static {
System.loadLibrary("libencprog");
}
public static native String encrypt(String filename);
}
In my Android.mk file i have written code
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := encprog
LOCAL_SRC_FILES := encprog.c
include $(BUILD_SHARED_LIBRARY)
I am calling encryption function of .so library by writing
EncryptionSoClass.encrypt(Global.file_path + filename);
I am getting following error
Exception Ljava/lang/UnsatisfiedLinkError; thrown while initializing Lcom/example/soencryptiondemo/EncryptionSoClass;
Tell me if i am missing any step..
I have already added native support for c/c++ in eclipse and included android ndk also
Your local_module is "LOCAL_MODULE := encprog" , Pls de as below,
public class EncryptionSoClass {
/* load our native library */
static {
System.loadLibrary("encprog");
}
public static native String encrypt(String filename);
}
Related
It looks like it is the popular problem,
And I still not find out the solution.
package name : app.cloudstringers
Java file : Completed.java
static {
try {
System.loadLibrary("ffmpeg");
} catch (UnsatisfiedLinkError e) {
Log.d("", "Error : " + e.toString());
}
}
// Define native method
public native int getString();
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.page_completed);
// Call native method
Log.d("", "" + getString());
C++ file : ffmpeg.cpp
#include <jni.h>
#include <android/log.h>
#include <string.h>
#ifdef __cplusplus
extern "C" {
#endif
JNIEXPORT jstring JNICALL Java_app_cloudstringers_Completed_getString(JNIEnv* env, jobject thiz)
{
jstring strRet = env->NewStringUTF("HelloWorld from JNI !");
return strRet;
}
#ifdef __cplusplus
}
#endif
Android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := ffmpeg
LOCAL_SRC_FILES := ffmpeg.cpp
include $(BUILD_SHARED_LIBRARY)
I run application but still get the error exception UnsatisfiedLinkError : getString
People who know the how to fix this problem,
Please tell me,
Thanks
UPDATE
Follow #dextor answer. Sorry because I get the mistake. Only thing I need for this question is change from public native int getString() to public native String getString().
It works now.
Not sure (didn't actually try), but the only wrong thing I've noticed is the return type of your method declarations.
Java-side
public native int getString()
NDK-side
JNIEXPORT jstring JNICALL Java_app_cloudstringers_Completed_getString(JNIEnv* env, jobject thiz)
In Java, you have an int. On the C-side, you have a jstring.
I'm using Eclipse ADT with: CDT. Along with NDK interfacing with JNI, to c/c++, compiling c/c++ with Cygwin through Eclipse. Everything should be running the latest versions as this was just setup over the last two weeks.
When Building I get the following.
jni/testSocketClass.hpp:33:1: error: unknown type name 'class'
jni/testSocketClass.hpp:33:17: error: expected '=', ',', ';', 'asm' or '__attribute__' before '{' token
jni/ndkfoo.c:13:1: error: unknown type name 'mYNewClass'
JNI C file
#include <string.h>
#include <jni.h>
#include "testSocketClassWrapper.hpp"
void *m_GBLpmyCSocket;
ndkfoo.c
jstring Java_com_example_hydrobedcontrol1_MainActivity_inintNativeClass(JNIEnv * env, jobject object){
m_GBLpmyCSocket = MyClass_create();
MyClass_sendCommandToSerialDevice(m_GBLpmyCSocket, 0, 0, 0);
return (*env)->NewStringUTF(env, "started");
}
Class Wrapper .hpp
//file testSocketClassWrapper.hpp
#ifndef _MY_SOCKETCLASS_WRAPPER_H
#define _MY_SOCKETCLASS_WRAPPER_H
#include"testSocketClass.hpp"//<<<<<<<<<<<<<<<<<<<<<Wrong inclusion
#ifdef __cplusplus
extern "C" void* MyClass_create() {
return new mYNewClass;
}
extern "C" void MyClass_release(void* myclass) {
delete static_cast<mYNewClass*>(myclass);
}
extern "C" void MyClass_sendCommandToSerialDevice(void* myclass, int cmd, int params, int id) {
static_cast<mYNewClass*>(myclass)->sendCommandToSerialDevice(cmd,params,id);
}
#endif
#endif /* _MY_SOCKETCLASS_WRAPPER_H_INCLUDED */
Class wrapper .cpp
//file testSocketClassWrapper.cpp
#include "testSocketClassWrapper.hpp"
Class .h
// file testSocketClass.hpp
class mYNewClass{///////////////////////ERROR HERE////////////////////////////////
//public:
void sendCommandToSerialDevice(int Command, int Parameters, int DeviceID);
//int sockfd;
};
Class .cpp
// file testSocketClass.cpp
#include "testSocketClass.hpp"
void mYNewClass::sendCommandToSerialDevice(int Command, int Parameters, int DeviceID){
char testc[100];
sprintf(testc, "%d, %d, %d", Command, Parameters, DeviceID);
}
I've read countless questions on this topic and have had quite a few issues getting this far with Eclipse configurations too. But from what I've pulled together from other questions on this topic, I have hit a wall and do not know how to proceed at this point. Suggestions?
EDIT BELOW - ANSWER
After review with a colleague(sometimes a second pair of eyes helps bring things out), we located my error. See the line labeled improper inclusion in the Class wrapper .hpp. That header should be relocated as follows in the Class wrapper .cpp NOTE: the functions where also moved to the .cpp and the .hpp is now empty.
//file testSocketClassWrapper.cpp
#include "testSocketClassWrapper.hpp"
#include "testSocketClass.hpp"
extern "C" void* MyClass_create() {
return new mYNewClass;
}
extern "C" void MyClass_release(void* myclass) {
delete static_cast<mYNewClass*>(myclass);
}
extern "C" void MyClass_sendCommandToSerialDevice(void* myclass, int cmd, int params, int id) {
static_cast<mYNewClass*>(myclass)->sendCommandToSerialDevice(cmd,params,id);
}
Also for completeness as this has been no walk in the park, are the MK files.
Android.mk
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := ndkfoo
LOCAL_SRC_FILES := ndkfoo.c testSocketClassWrapper.cpp testSocketClass.cpp
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_STL:=stlport_static
Thank you for the prompt reply krsteeve. And yet another way to do this. Will keep it in mind.
testSockedClass.hpp is being included from a .c file, so it's being compiled with a C-compiler. class doesn't exist in C. Change ndkfoo.c to a .cpp file.
You will have to format things a bit differently in C++:
extern "C"
{
jstring Java_com_example_hydrobedcontrol1_MainActivity_inintNativeClass(JNIEnv * env, jobject object);
}
jstring Java_com_example_hydrobedcontrol1_MainActivity_inintNativeClass(JNIEnv * env, jobject object){
m_GBLpmyCSocket = MyClass_create();
MyClass_sendCommandToSerialDevice(m_GBLpmyCSocket, 0, 0, 0);
return env->NewStringUTF("started");
}
Note the form of the NewStringUTF call in C++ vs C.
I am trying to build android application using native code so i want to test if ndk runs successfully.When i try to run my first hello world project
log cat says,
01-21 23:30:06.780: E/AndroidRuntime(939): FATAL EXCEPTION: main
01-21 23:30:06.780: E/AndroidRuntime(939): java.lang.UnsatisfiedLinkError:
Native method not found: com.example.ndktesting.MainActivity.invokeNativeFunction:()Ljava/lang/String;
I checked some stackoverflow answers but could not find my answer.Here is my code for java and c.I am using android ndk r8d version.
//ndktest.c
#include <string.h>
#include <jni.h>
extern "C"{
JNIEXPORT jstring JNICALL Java_com_example_ndktesting_ndktest_MainActivity_invokeNativeFunction(JNIEnv* env, jobject thiz)
};
JNIEXPORT jstring JNICALL Java_com_example_ndktesting_ndktest_MainActivity_invokeNativeFunction(JNIEnv* env, jobject thiz){
return (*env)->NewStringUTF(env, "Hello from native code!");
}
Here is my MainActivity java code:
package com.example.ndktesting;
public class MainActivity extends Activity {
//declare the native code function - must match ndktest.c
private native String invokeNativeFunction();
public native String unimplementedinvokeNativeFunction();
// load the library - name matches jni/Android.mk
static {
System.loadLibrary("ndktest");
}
#Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// this is where we call the native code
String hello = invokeNativeFunction();
new AlertDialog.Builder(this).setMessage(hello).show();
}
}
Android make file code:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# Here we give our module name and source file(s)
LOCAL_MODULE := ndktest
LOCAL_SRC_FILES := ndktest.c
include $(BUILD_SHARED_LIBRARY)
Your package/class names do not match.
JNIEXPORT jstring JNICALL Java_com_example_ndktesting_ndktest_MainActivity_invokeNativeFunction(JNIEnv* env, jobject thiz)
Would be a method in the class
com.example.ndktesting.ndktest.MainActivity
However your actual code
package com.example.ndktesting;
public class MainActivity extends Activity
causes it to look for
com.example.ndktesting.MainActivity.invokeNativeFunction
without the "ndktest"
Once you make the names match it should either work, or expose the next issue.
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
I have tried writing a jni call for the simple c code. when i try to install this on the phone running 2.3.3 it doesnt install, sometimes even if it installs then it is being force closed.Please help me with this. the code details are as follows:
The java code of which i generate the header file.
package com.hosa;
public class edgejava
{
static{
System.loadLibrary("edgejava");
}
public native int main();
}
the generated header file is as below
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_hosa_edgejava */
#ifndef _Included_com_hosa_edgejava
#define _Included_com_hosa_edgejava
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_hosa_edgejava
* Method: main
* Signature: ()I
*/
JNIEXPORT jint JNICALL Java_com_hosa_edgejava_main
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif
the implementation of native function is as below
#include "com_hosa_edgejava.h"
#include <jni.h>
#include <cv.h>
#include <highgui.h>
using namespace cv;
JNIEXPORT jint JNICALL Java_com_pes_edgejava_main(JNIEnv *, jobject){
VideoCapture cap(0); // open the default camera
if(!cap.isOpened()) // check if we succeeded
return -1;
Mat edges;
namedWindow("edges",CV_WINDOW_AUTOSIZE);
for(;;)
{
Mat frame;
cap >> frame; // get a new frame from camera
cvtColor(frame, edges, CV_BGR2GRAY);
GaussianBlur(edges, edges, Size(7,7), 1.5, 1.5);
Canny(edges, edges, 0, 30, 3);
imshow("edges", edges);
if(waitKey(30) >= 0) break;
}
// the camera will be deinitialized automatically in VideoCapture destructor
return 0;
}
the android.mk file
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
include /home/srijith/android-opencv/OpenCV-2.3.1/share/OpenCV/OpenCV.mk
LOCAL_MODULE := edgejava
LOCAL_SRC_FILES := edgecpp.cpp
LOCAL_LDLIBS += -llog -ldl
include $(BUILD_SHARED_LIBRARY)
the application.mk
APP_MODULES := edgejava
APP_STL := gnustl_static
APP_CPPFLAGS := -frtti -fexceptions
the activity file is as follows
package com.hosa;
import android.app.Activity;
import android.os.Bundle;
public class Andedge2Activity extends Activity {
edgejava nativelib;
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
nativelib= new edgejava();
int i=nativelib.main();
System.out.println("value returned to andedgeactivity "+i);
}
}
All necessary changes to the manifest has been done like mention of use of camera and permissions has been set.
Edit:
I have changed the com_pes_edgejava to com_hosa_edgejava_main but still not working...
Any other solutions ??????
Problem is in you Packname change your application package com.hosa to com_pes_edgejava.
In your JNI file you will see function(main) declaration like JNIEXPORT jint JNICALL Java_com_pes_edgejava_main()
Java_com_pes_edgejava_main
That's your issue.
hotveryspicy points out the obvious issue (ie that you have com_pes when you should have com_hosa). As for the fact it doesn't work still, I would suspect this comes down to the "using namespace cv". As a result you are declaring your JNI function inside the cv namespace which is not correct. This is one of the reasons that the using keyword is something to be wary of.
whats wrong with just putting cv:: on front of the calls to functions and definitions of structs/classes that are in that namespace? Its far better at self documenting that way anyway.