大家好。被JNI折磨憔悴了。
Java环境下使用JNI调用本地 C/C++ 库我倒研究出了点眉目,就是先定义native,再javah,新建C++项目,拷贝jni.h、jni_md.h,再如此这般。
我C懂点、C++勉强算得上白痴水平。 现在我手头有个android项目,是个视频播放器,有个需求是要实现对指定加密的视频实现解密,解码模块的是C++的实现,代码已经在我手里,是一个".h"和".so"文件。
我已经试了一天,企图将这个C++在Android中使用起来。愣是没成,一直报“ERROR/AndroidRuntime(426): java.lang.UnsatisfiedLinkError: Library libdcry not found”
祈求各路菩萨大慈大悲救我一命。 就是怎样将现有的C++代码,在Android中跑起来
先感谢大伙了!!!
Java环境下使用JNI调用本地 C/C++ 库我倒研究出了点眉目,就是先定义native,再javah,新建C++项目,拷贝jni.h、jni_md.h,再如此这般。
我C懂点、C++勉强算得上白痴水平。 现在我手头有个android项目,是个视频播放器,有个需求是要实现对指定加密的视频实现解密,解码模块的是C++的实现,代码已经在我手里,是一个".h"和".so"文件。
我已经试了一天,企图将这个C++在Android中使用起来。愣是没成,一直报“ERROR/AndroidRuntime(426): java.lang.UnsatisfiedLinkError: Library libdcry not found”
祈求各路菩萨大慈大悲救我一命。 就是怎样将现有的C++代码,在Android中跑起来
先感谢大伙了!!!
解决方案 »
- setImageDrawable设置多张图片的问题
- (ubuntu android平台搭建)点击Window->Android SDK AND AVD Manager出错!
- 各位前辈,想实现这样的效果
- 通过名字查找联系人,应该如何实现
- 图片位置
- 怎么用代码关闭或者打开数据连接??求帮助
- 各位android师兄师姐,新手求助
- 网上很多人说都说:横屏切换到竖屏:(调用两次生命周期)。但是我自己写了一个demo,测试下了都是调用一次啊,为什么?
- 安卓TCP通讯客户端接受数据的问题。
- zxing问题
- JNI:对Android下Paint类中setStyle的封装方法
- C# 压缩,Android解压错误,求解决方法
如果是 在JNI里面要 extern "C"{jni c++代码}
重写jint JNI_OnLoad(JavaVM* vm, void* reserved)方法
放在路径 libs/armeabi/下,这样就可直接System.load("so文件名")
jint??是什么?
另外,C++代码是编译好的,我不可能改。就是一个so文件,然后有一个.h 文件
#include <string.h>
#include <stdio.h>
#include <unistd.h>
typedef enum {
// seek from start of file.
HL_FILE_SEEK_START,
// seek from current position in the file.
HL_FILE_SEEK_CURRENT,
// seek from end of file.
HL_FILE_SEEK_END,
} HLfileSeekmode;struct HLfile {
int fd;
void *extent;
};HLfile HLOpenFile(const char *name);
HLstatus HLCloseFile(HLfile f);
HLstatus HLReadFile (const HLfile f, unsigned char *pbuffer, unsigned int size,Unsigned int *preadSize);
HLstatus HLGetCurrentPositionOfFile (const HLfile f, long long *position);
HLstatus HLSeekFile (const HLfile f, long long offset, HLfileSeekmode mode);
bool HLEndOfFile(const HLfile f);
HLstatus HLSizeOfFile( const char *filename,long long *pSize);
static {
System.loadLibrary("libdcry");
}
public native String _readFile();
public void testJNI() {
_readFile();
}
}
但是我现在还是报 java.lang.UnsatisfiedLinkError: Library libdcry not found
1. System.loadLibrary(xxx);
上加try catch,看对不对。
注意System.loadLibrary 和System.load, 括号后面的参数是不一样的。2. 检查一下,C++中的函数和java中的native方法对应好了没有,有没有漏掉的什么的3. C++还是自己写Jni_onLoad,给你个例子:extern "C" jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
jint result = -1; if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("GetEnv failed!");
return result;
}
LOG_ASSERT(env, "Could not retrieve the env!"); if(jniRegisterNativeMethods(env, "com/xxx/xxx/xxx",
xxxMethods, NELEM(xxxMethods)) != 0){
LOGE("Register method to com/xxx/xxx/xxxf ailed!");
return -1;
}
return JNI_VERSION_1_4;
}打印足够的trace,看到底哪里出错了。
JNI实际上是很简单的,与C++关系也不算大。
看看源码包的这个目录
还有看看这个文档
http://www.360doc.com/content/10/1012/06/3822981_60261755.shtml
根据头文件重写jni
然后和已有的头文件and .so库
重新编译一个so库出来
所以还是重新封jni吧
你显然理解错了。人家给你的so并非你可以调用的JNI。 你必须重新封装别人给你的方法,然后提供本地java代码。因为他提供给你的不过是so,并没有本地方法,比如说liba.so。 你必须自己定义b.cpp和 c.java 在 b.cpp 中写你需要的方法, 然后在c.java 里面装载由b生成的so。并提供和b中对应的java方法。
不知道我这样说你明白没有,另外很久没有来CSDN混分数了。 LZ你懂得
android加载的本地库,一定是以lib开头,.so为后缀的,中间是你的库名
例如:
com.btrend.android.decdivx对应的c中是com_btrend_android_decdivx_DecDivx如果没有,调用成功的可能性几乎是0
java代码:System.loadLibrary("Jicmp");.so文件叫动态链接库文件, 其实相当于java里的jar文件的含义.
在linux底下可以放到 LD_LIBRARY_PATH环境变量对应的目录下 在android下不太清楚是哪个目录下报哪个错误的原因有两个:
1.你的文件没放对地方
2.地方放对了,但是还有一个原因, c/c++是不夸平台的,就是说 你的.so文件是不是在别的操作系统环境下编译的,就比如同样都是linux系统,在redhat下编译的.so文件放到其他linux下不一定能用。这种情况就需要你用源码重新编译后使用
JNIEXPORT jint JNICALL Java_com_xxx_socket_InitConnect
(JNIEnv *env, jobject obj, jint nClient, jint port, jstring strIP);对应的 Java 代码,必须是 src/com/xxx 目录下的 socket.java 文件中的public class socket 中的public native static int InitConnect(int nClient, int port, String strIP); 函数
jni我以前也写过一个例子,在学习core java的时候,楼主可以这么入手去解决这个问题:
1.写一个native方法类,用javah生成它的c存根,完成一个java到c调用的例子
2.实现c存根方法调用c++模块代码的的调用
以上两步分开来做会很简单,各个击破,不要一入手就想把它给搞定
要定义如下这个结构体。参考android_media_mediaPlayer.cpp
static JNINativeMethod gMethods[] = {
{"setDataSource", "(Ljava/lang/String;)V", (void *)android_media_MediaPlayer_setDataSource},
{"setDataSource", "(Ljava/lang/String;Ljava/util/Map;)V",(void *)android_media_MediaPlayer_setDataSourceAndHeaders},
{"setDataSource", "(Ljava/io/FileDescriptor;JJ)V", (void *)android_media_MediaPlayer_setDataSourceFD},
在c文件中定义的函数名字应该形如:
jint Java_com_test_hellojni_HelloJni_add(JNIEnv *evn, jobject this, jint a,
jint b) { return a + b;
}
项目组织结构:
HelloJni
/ | \
src jni AndroidManifest.xml
/ / \
com Androi.mk hello.c
/
test
/
hellojni
Android.mk文件内容如下:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := hello-jni.cinclude $(BUILD_SHARED_LIBRARY)------------------------------------
你需要进入jni源码所在目录*/HelloJni/jni 运行: $NDK/ndk-build产生lib文件
----------------------------------------
在java中load library
static {
System.loadLibrary("hello-jni");
}
static {
System.loadLibrary("libdcry");
}
public native String _readFile();
public void testJNI() {
_readFile();
}
}我是新手本来不想说的怕误导人。
但是一个帖子直到看了30楼觉得还是有跟我想法一样的人就呼应一下。
我记得昨天看google jni用法的时候里面有说 libXXXX.so文件 lib是生成.so文件的时候自己添加的。
在java里面System.loadLibrary的时候就不要加lib。System.loadLibrary("XXX");