Android studio 下JNI编程实例并生成so库的实现代码

最近需要使用JNI编程,学了下JNI,并且在Android Studio下实现了一个小demo。这期间有一些坑,还好都解决了,想分享出来,希望大家少走弯路。本文中采用的平台是Windows,NDK环境已经搭建好,这方面资料很多,大家可以自行百度。

本文分为两个部分:

1.如何通过编写Jni实现native方法的调用。

2.怎样生成.so动态库提供给第三方使用。

以下是正文:

一,编写jni文件,实现本地方法

1,建立一个新工程,只有一个MainActivity,里面加载库文件并且调用若干本地方法,然后通过Android Studio里的build-makeProject生成class文件。

public class MainActivity extends Activity { private final String TAG = "JNITEST" @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); String s=returnString(); Log.d(TAG,s); int a=1000; Log.d(TAG,sayhello(a)); }   //加载jni static { System.loadLibrary("nativeTest"); }   //声明native方法 private native int sayhello(int t); private native String returnString(); }

2,生成.h头文件,里面有Android工程里本地方法的声明。这个文件可以自己写,但是推荐用javah自动生成。生成方法为:在控制台或者Android studio自带的控制台使用javah命令将上一步make之后生成的class文件生成.h头文件,这里在用javah的时候有可能会出问题,比如我第一次就出现了找不到app.activity ,即找不到类文件,这种问题一般是没有理解javah的用法造成的。我当时采用以下两种方法:

方法1: cd到 E:\shijue\JniHello\app\src\main

然后输入 javah -d jni -classpath I:\Andriod\AndroidSDK\platforms\android-15\android.jar;
E:\shijue\JniHello\app\build\intermediates\classes\debug com.example.machenike_pc.jnihello.MainActivity

说明:javah是生成头文件的命令,深绿色为生成文件夹jni,紫红色为android.jar所在的位置,浅绿色为class文件的路径+类全名(路径最后一个文件夹是debug之后空格+类全名)

(这里补充下-classpath的含义:javah操作是针对类文件,-bootclasspath和-classpath就是指定在哪里进行类文件搜索。JDK搜索类文件先后顺序如下:Bootstrap classes,User classes。Bootstrap默认的是JDK自带的jar或zip文件,它包括jre\lib下rt.jar等文件,JDK首先搜索这些文件.可以通过-bootclasspath来设置它。文件之间用分号";"进行分割。User classes搜索顺序为当前目录、环境变量 CLASSPATH、-classpath。它们用于告知JDK搜索类文件根目录名、jar文档名、zip文档名,用分号";"进行分隔。)

方法2: cd到E:\shijue\JniHello\app\build\intermediates\classes\debug目录下,直接javah -d jni com.example.machnike_pc.jnihello.MainActivity 即可

3,在生成的jni目录下写一个c或者c++文件,文件名随意,实现本地方法 ,之后需要在该路径下再加一个空的cpp或c文件(估计是软件的bug,不加的话很可能出ndk错误),比如我加了个util.cpp的文件,里面什么都不写。

下面是我的c++代码

#include<jni.h> #include<stdio.h> #include<com_example_machenike_pc_jnitest2_MainActivity.h> #ifdef __cplusplus extern "C" { #endif JNIEXPORT jint JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_sayhello (JNIEnv *, jobject, jint); JNIEXPORT jstring JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_returnString (JNIEnv *, jobject); #ifdef __cplusplus } #endif JNIEXPORT jint JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_sayhello (JNIEnv * env, jobject jobj, jint jnumber) { int modify=jnumber+1; return modify; } JNIEXPORT jstring JNICALL Java_com_example_machenike_1pc_jnitest2_MainActivity_returnString (JNIEnv *env, jobject jobj) { return env->NewStringUTF("I'm comes from to Native Function!");    }

4,如果ndk版本不是最新的,需要在gradle.properties文件下加入:

android.useDeprecatedNdk=true

5,配置ndk路径,这里也可以在AS的设置里面配置。我采用的方法是在local.properties文件最后一行加入:

ndk.dir=I\:\\Andriod\\NDK\\android-ndk-r10b

6,build.gradle(app下):文件下加入:(defaultconfig里面)

ndk{
moduleName "nativeTest"
}

此时运行程序已经可以实现本地方法了,之后可以再生成so库文件,方便使用。

二,生成.so动态库

(这里说一下,貌似Android studio已经写好了.mk文件,上面的步骤完成后,直接rebuild一下就自动生成为了.so动态库,下面的方法也能生成,可以看一下,很有用)

1,在jni文件夹下新建Android.mk文件,写入以下内容:

LOCAL_PATH := $(call my-dir)           //固定写法,把路径赋给LOCAL_PATH变量
include $(CLEAR_VARS)                  //清除其他LOCAL变量
LOCAL_MODULE := nativeTest             //这个模块的名字,最后生成的.so的名字就是它,要跟java里面的loadLibray的名字一样。
LOCAL_SRC_FILES := nativeTest.cpp\     //这里是要编译的文件,\ 符号是换行
            util.cpp
include $(BUILD_SHARED_LIBRARY)        //SHARED_LIBRARY就是动态库,即.so文件

这里的写法是最简单的一个例子,用的时候把注释去掉。每一行都是很关键,不能省略。至于makefile怎么编写内容比较多,此处不赘述。

2,在工程根目录下新建application.make文件,写入以下内容:

APP_PROJECT_PATH := $(call my-dir)
APP_MODULES := nativeTest
3,在命令行下,cd到jni目录(就是之前javah -d jni生成的那个文件夹)下,输入指令: ndk-build,等一会即可生成.so文件。位于lib目录下,将其放到app/src/main/jniLibs目录下就能用了。

FAQ:

1,生成的so文件在使用时需要注意:包名不能变,拿上文举例,本地方法位于com_example_machenike_pc_jnitest2_MainActivity这个类下,如果在别的地方用,需要完整的建立这个包名和类。
2,c和cpp文件均可以用来写jni,写法上略有不同。
3,需要注意java里面成员方法和静态方法通过javah生成的头文件略有不同,一个参数是jclass,另一个是jobject。
4,不用javah生成头文件也行,推荐第一次写的时候用javah生成,后面修改的时候(比如参数改变)可以直接在c文件里手动修改。

补充:

SourcePath: D:\work\androidstudio\VisualRecognition\app\src\main\java (绝对路径)

TargetPath: D:\work\androidstudio\VisualRecognition\visual\src\main\jni (绝对路径)

TargetClassName: com.yf.visualrecognition.UnityPlayerActivity (你的包名+类名)

格式: javah -d ${SourceFile} -classpath ${TargetPath} ${TargetClassName}

生成.h文件:javah -d E:\AndroidProject\GitHubProject\OpenCV\OpenCV\app\src\main\jni -classpath E:\AndroidProject\GitHubProject\OpenCV\OpenCV\app\src\main\java com.cosco.opencv.OpenCVHelper

时间: 2024-11-02 10:37:59

Android studio 下JNI编程实例并生成so库的实现代码的相关文章

嵌入式-android studio下的编程问题

问题描述 android studio下的编程问题 在android studio下 res目录下建立xml在其中建立settings.xml文件为什么不行 求具体解决办法 急需 解决方案 Android Studio问题收集Android Studio编码问题Android Studio 常见问题集锦 解决方案二: 没太清楚 不过你可以试下拖拽 或者newXML 那里可以选择几种XMl 的 解决方案三: 直接放在values目录下面,不要新建目录.

Android Studio的JNI开发快餐教程

Android Studio的JNI开发快餐教程 从eclipse换到Android Studio之后,原来的NDK集成已经不能用了.同时,AndroidStudio也是在快速迭代进步中,不仅支持内置的ndk支持插件,还有支持外部编译系统的plugin. 而且这还是在实验中的结果,在不久的将来,还可能有更新的变化.不过,万变不离其宗,我们打好基础,形式上的东西跟着Android Studio变就好. 旧式的NDK支持 首先说明,既然是Android Studio认为它已经过时了,所以我们需要在g

Android Studio使用jni、so库

Android Studio使用jni.so库 在Android Studio1.1之后,AS就已经支持jni和so库了,马上发布的1.3正式版,更是可以在clion环境下编译c.c++,更加方便的使用NDK进行开发,网上有很多讲在Android Studio中使用jni的方法,但大多都是在1.1之前的,那时候还没有直接支持jni,所以需要通过给gradle增加task的方式来添加支持.而现在,这一切都不是事!!! 添加lib库 切换到project标签,直接将jar包复制到libs目录下,在添

android studio-求助:Android studio下使用shareSDK一直出现这个问题

问题描述 求助:Android studio下使用shareSDK一直出现这个问题 首先我使用的是Android studio去写一个点击按钮使用mob提供的一键分享功能,demo中只包括新浪微博的分享. 参考的是官方文档和论坛说明,这里给出链接Android studio下集成ShareSDK 这个是项目的工程目录.(对android studio的使用不够熟悉,不知道这里是不是就出现问题了) 项目一直报错的问题(bug). 关于图片上面的问题,查阅过网上的资料 ,发现他说的问题,有第三方类库

Android Studio下执行单元测试

今天在Android Studio下学习怎么执行单元测试,现总结如下: 1. https://coderwall.com/p/ybds4w http://blog.futurice.com/android_unit_testing_in_ides_and_ci_environments 2. 出现问题如下: Exception in thread "main" java.lang.NoClassDefFoundError: junit/textui/ResultPrinter at j

myeclipse-Java——AES在Android studio下加解密问题

问题描述 Java--AES在Android studio下加解密问题 我在myeclipse下使用AES加解密算法,可以运行并没有正确加解密,可是同样的代码放到Android studio下却只能加密,解密出来都是空值,请问有人知道为什么吗? 解决方案 不会吧!同一段加密代码应该没问题,毕竟运行环境对这没那么大影响

Android自定义控件下拉刷新实例代码_Android

实现效果: 图片素材: --> 首先, 写先下拉刷新时的刷新布局 pull_to_refresh.xml: <resources> <string name="app_name">PullToRefreshTest</string> <string name="pull_to_refresh">下拉可以刷新</string> <string name="release_to_refre

Android studio 配置JNI环境

Android studio配置jni开发环境,主要配置是两个build文件,以及新建一个jni文件,放c代码.   代码如下1: apply plugin: 'com.android.model.application' model { android { compileSdkVersion = 23 buildToolsVersion = "23.0.2" defaultConfig.with { applicationId = "me.chunsheng.jni&quo

Android Studio下添加assets目录的实现方法

有时候需要放置一些文件而且不被proguard压缩,可以放到assets目录中. 但是工程默认并未创建assets目录,那么如何在android studio中创建assets目录呢? 目录位置为:XXX\src\main\assets XXX代表你的项目的路径,assets放在src\main目录下. 以上这篇Android Studio下添加assets目录的实现方法就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家.