创建so文件并加载

来源:互联网 发布:我的世界,java.net 编辑:程序博客网 时间:2024/05/16 15:53

       简单介绍一下步骤:首先加载本地方法,然后通过Javah 一系列命令生成C语言的 头文件 .h 文件   ;然后编写C 文件 ,在c中用到定义的本地方法 ;然后写 Android .mk  文件  控制 so文件的编译 ;编译so文件

1.创建本地方法 ,加载 so文件

   public class SecretKey{

         static{

            System.loadLibrary(" key");// 加载动态类库 ,这里的 key 是so文件的名字

     }

        public static native String getKey(Object   contextobject); 本地方法用 native 标识

  }

      这里需要 Build - > Make Project 生成class文件


2.生成 .h 文件(使用Javah命令 将上一步生成的 .class 文件生成.h 头文件)

其中.h 文件,存在 main文件夹下 jni文件夹中,如下:

                



在当前项目的main文件夹路径下     javah  -d  jni  -classpath  <sdk.......  android.jar> ;  <App_class>


App_class: 指  so 所在的 class类的文件夹 在 build\intermediates\classes\debug   包名.类名

sdk....android.jar : E:\Androidstudio\asdk\platforms\android-16\android.jar

包名类名:com.alldk.testdz.Api.SecretKey

例如:

E:\...... testDz\app\src\main>javah -d jni -classpath E:\Androidstudio\asdk\platforms\android-16\android.jar;E:\testDZ\testDz\ap
p\build\intermediates\classes\debug com.alldk.testdz.Api.SecretKey

第二步这里,尤其注意,sdk中 android.jar的路径 ,还要在<project>\app\src\main 路径下


3.对应 的 .C文件,这里以 testDz中的c文件为例子


/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
com_alldk_testdz_Api_SecretKey_getSecretKey  引用本地的方法名 

#include <android/log.h>

#ifndef LOG_TAG
#define LOG_TAG "ANDROID_LAB"
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#endif

/* Header for class lab_sodino_jnitest_MainActivity */

#ifndef _Included_com_alldk_testdz_Api_SecretKey 这两个地方引入的是.h文件名
#define _Included_com_alldk_testdz_Api_SecretKey
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class:
com_alldk_testdz_Api_SecretKey_

* Method:
getSecretKey

* Signature: ()Ljava/lang/String;

这里的参数 (JNIEnv * env jobject jObj
  com_alldk_testdz_Api_SecretKey_getSecretKey  这个是方法名的引用
 JNIEnv * env  不用管;jobject jObj  是传递的数据
 */
JNIEXPORT jstring JNICALL Java_com_alldk_testdz_Api_SecretKey_getSecretKey
(JNIEnv * env, jobject jObj){
LOGE("log string from ndk.");
return (*env)->NewStringUTF(env,"这里是你想传递的数据");
}

#ifdef __cplusplus
}
#endif
#endif

4.创建 android.mk 文件,该文件控制so文件如何编译

LOCAL_PATH :=$(call my-dir)include $(CLEAR_VARS)#bzlib 模块bzlib_files:=\one.cLOCAL_MODULE := libbzLOCAL_SRC_FILES := $(bzlib_files)include $(BUILD_STATIC_LIBRARY)#bspath模块include $(CLEAR_VARS)LOCAL_MODULE    := oneLOCAL_SRC_FILES := one.cLOCAL_STATIC_LIBRARIES := libbz #引入libbzinclude $(BUILD_STATIC_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE    := key  这里是 加载的so文件的名字LOCAL_SRC_FILES := one.c  这里是c文件名字LOCAL_STATIC_LIBRARIES := oneLOCAL_LDLIBS := -llog#加入loginclude $(BUILD_SHARED_LIBRARY)

5.在控制台 main文件夹路径下   ndk-build  生成so文件 

6.配置 build.gradle(这一步应该在前面配置)

  android下 defaultConfig 下  配置ndk信息

  ndk {

    moduleName ' 这里的名字是 so文件的名字'

    abiFilters  "arm64-v8a","armeabi","armeabi-v7a","mips" ,"x86","x86_64"

  }

  在 android下 (这个配置是在 main下面 创建 libs文件夹,通过 ndk-build后 生成的so文件在  libs文件夹下)

     sourceSets{

        main{

     jniLibs.srcDirs=['libs']

             jni.srcDirs=[ ]

         }

    }

  as中 android视图下,在 build.gradle中配置如下代码,会生成文件夹 jniLibs目录,不需要自己去创建, 之后把生成的so文件拷贝一份放到这里。

          sourceSets{

                  main{

              jniLibs.srcDirs=['libs']

                      jni.srcDirs=[ ]

                  }

         }

其中 ,在所有的步骤中 ,有三个地方都引用 so文件的名字

     1.  加载so文件时

     static{

          System.loadLibrary("key")

     }

     2.在build文件中ndk的设置

       ndk{

          moduleName 'key'

     .......

       }

     3.编写Android.mk文件时

      LOCAL_MODULE= ' key'   与 so 文件名保持一致

最后总结生成so文件的步骤如下:

1.声明加载so文件的接口和本地方法     
2.生成.h文件遇到问题, 编译时要在项目的..\app\src\main路径下编译+sdk的路径+加载so文件的类的class文件所在位置        
3.编写C文件,在C 文件中实现本地方法    
4.编写mk文件,定义so 文件如何编译,例如so文件的名称等 
5.com中在项目的..\app\src\main 路径下 ndk-build 生成so 文件
6.如果报找不到so文件的错,在Android 视图下创建文件夹,文件夹在build.gradle 中设置生成

参考文章 :http://blog.csdn.net/sodino/article/details/41946607  

                    http://www.2cto.com/kf/201608/533816.html   主要是这一篇