大家好。被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中跑起来
     先感谢大伙了!!!

解决方案 »

  1.   

    jni部分是使用c++写的么?
    如果是 在JNI里面要 extern "C"{jni c++代码}
      

  2.   

    或者在jni里面模仿android的jni
    重写jint JNI_OnLoad(JavaVM* vm, void* reserved)方法
      

  3.   

    so文件已经生成好了吗,
    放在路径 libs/armeabi/下,这样就可直接System.load("so文件名")
      

  4.   

      我相信他是这么写的,因为当初写这个代码的人,知道我们是基于JNI的调用实现
      

  5.   

    提示“Library libdcry not found”  —— 找不到
      

  6.   

    上面某位应该说的是System.loadLibrary方法java的JNI怎么讲究android的同样也要怎么讲究
      

  7.   


    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);
      

  8.   

    我对JNI研究不深,昨晚上回去查了资料看了看,明白写了大体的流程。但是现在这个事把我流程截断了,因为C++  代码是编译好给我的。里面提供了些方法,我现在要调用他们,就是这样。
      

  9.   

    我的测试代码:     public class TestJNI extends AndroidTestCase {
    static { 
               System.loadLibrary("libdcry"); 
        } 

    public native String _readFile();
    public void testJNI() {
    _readFile();
    }
    }
      

  10.   

    java端定义好对应的native方法(和C++端一定严格对应), System.loadLibrary之后再java端用到什么就调用相应的native方法即可。
      

  11.   

    太感谢你了,你是说,C++端定义了什么方法,JAVA里面就定义方法名、参数名一致的 native 方法么?
    但是我现在还是报 java.lang.UnsatisfiedLinkError: Library libdcry not found
      

  12.   

    是不是你的那个.so还要依赖其他的.so,而你没有啊
      

  13.   

    ERROR/AndroidRuntime(426): java.lang.UnsatisfiedLinkError: Library libdcry not found这一句提示很明确了就是java在调用native的方法时,没有找到这个native方法。找原因:
    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++关系也不算大。
      

  14.   

    android-2.2\development\samples\SimpleJNI
    看看源码包的这个目录
    还有看看这个文档
    http://www.360doc.com/content/10/1012/06/3822981_60261755.shtml
      

  15.   

    SimpleJNI我这里没有、谁能发我一个示例程序好么?
      

  16.   

    换了我就只有一个笨方法,
    根据头文件重写jni 
    然后和已有的头文件and  .so库
    重新编译一个so库出来
      

  17.   

    Library libdcry not found还是库文件没有找到啊,更不要说里面的方法了~看看你把这个文件放的目录对不对,拷贝到其它目录下试试~
      

  18.   

    如果拿到的so库是封装好jni的,你看不到他jni封装的格式,你怎么建立对应的java  native方法包名,类名呢?同名的java方法对应的jni方法还有不同的签名,参数也不一定是完全对应。
    所以还是重新封jni吧
      

  19.   

    哥哥来了,
    你显然理解错了。人家给你的so并非你可以调用的JNI。 你必须重新封装别人给你的方法,然后提供本地java代码。因为他提供给你的不过是so,并没有本地方法,比如说liba.so。 你必须自己定义b.cpp和 c.java 在 b.cpp 中写你需要的方法, 然后在c.java 里面装载由b生成的so。并提供和b中对应的java方法。
    不知道我这样说你明白没有,另外很久没有来CSDN混分数了。 LZ你懂得
      

  20.   

    System.loadLibrary("lib" + 库名 + ".so");
    android加载的本地库,一定是以lib开头,.so为后缀的,中间是你的库名
      

  21.   

    你有没有c的代码,如果有,要按你的java工程修改c中的工程名,
    例如:
    com.btrend.android.decdivx对应的c中是com_btrend_android_decdivx_DecDivx如果没有,调用成功的可能性几乎是0
      

  22.   

    例子 so文件名称叫 libJicmp.so
    java代码:System.loadLibrary("Jicmp");.so文件叫动态链接库文件, 其实相当于java里的jar文件的含义.
    在linux底下可以放到 LD_LIBRARY_PATH环境变量对应的目录下 在android下不太清楚是哪个目录下报哪个错误的原因有两个:
    1.你的文件没放对地方
    2.地方放对了,但是还有一个原因, c/c++是不夸平台的,就是说 你的.so文件是不是在别的操作系统环境下编译的,就比如同样都是linux系统,在redhat下编译的.so文件放到其他linux下不一定能用。这种情况就需要你用源码重新编译后使用
      

  23.   

    #25 就是说得太简单了点,不过看起来楼主已经明白了(下面是一个满足 JNI 一个接口的例子)extern "C" // 假定 JNI 代码是 C++ ,需要这一行
    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); 函数
      

  24.   

    来混点分数:
    jni我以前也写过一个例子,在学习core java的时候,楼主可以这么入手去解决这个问题:
    1.写一个native方法类,用javah生成它的c存根,完成一个java到c调用的例子
    2.实现c存根方法调用c++模块代码的的调用
    以上两步分开来做会很简单,各个击破,不要一入手就想把它给搞定
      

  25.   

    先好好研究下jni如何实现。android和平常的有点点区别。
    要定义如下这个结构体。参考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},
      

  26.   

    上面的更加深入到jni了用了方法的隐射不用写难看的jni头了
      

  27.   

    没有源码 你只有第三方的so和h,怎么再生成so?要有源码
      

  28.   

    SO库必须是用NDK编译的,用GCC可不行,所以没有源代码就白扯
      

  29.   

    请在java中申明native函数public native int add(int a, int b);
    在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");
        }
      

  30.   

    报“Library libdcry not found”是连库都没找到,先不用分析函数名啊,编译环境之类的。如果是编译环境的问题,会报“wrong ELF”错误。所以先看System.loadLibrary的参数对不对吧。如果别人只提供一个so库而且这个库没有用符合JNI的标准来写的话,还需要自己再写一个so来调用这个库里面的函数,还有个前提是别人提供的so库用的编译器跟设备的环境相符合(应该是arm吧)。
      

  31.   

     public class TestJNI extends AndroidTestCase {
        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");
      

  32.   

    添加libs 文件夹 再在此文件夹下新建armeabi 文件夹 再将.so文件拷贝到此文件目录下。