Android Studio开发jni实例详解 (调用C代码实例)
来源:互联网 发布:js查找字符串出现次数 编辑:程序博客网 时间:2024/06/08 22:43
一、配置NDK环境
第一步:在AndroidStudio中配置ndk环境
需要下载ndk包,在AndroidStudio中File-->ProjectStructure-->SDK Location中配置"Android NDK Location",如下:
下载安装完成后build工程;
第二步:配置环境变量
在计算机属性里面配置环境变量,变量地址是Android NDK Location里面的路径:(我这里是:C:\studio\android-sdk-windows\ndk-bundle)
第三步:测试环境变量是否配置成功
在CMD里面输入ndk-build,如果未提示"ndk-build不是系统命令"就表示NDK环境配置完成了!二、编译JNI生成So包并调用
第一步:生成调用方demo
java代码MainActivity.java:
public class MainActivity extends Activity { static { System.loadLibrary("JniTest"); } public native String getStringFromNative(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); TextView txt = (TextView) findViewById(R.id.main_txt_msg); txt.setText(getStringFromNative()); }}
xml代码"activity_main.xml":
<?xml version="1.0" encoding="utf-8"?><RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android" xmlns:tools="http://schemas.android.com/tools" android:layout_width="match_parent" android:layout_height="match_parent" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.jni.jnitest.MainActivity"> <TextView android:id="@+id/main_txt_tips" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="下面是来自JNI里面C代码返回的信息"/> <TextView android:id="@+id/main_txt_msg" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_below="@id/main_txt_tips" android:textColor="#f00"/></RelativeLayout>
第二步:配置build.gradle
在app文件夹下的build.gradle文件里面配置Ndk相关信息
ndk { moduleName "JniTest" ldLibs "log", "z", "m" abiFilters "armeabi", "armeabi-v7a", "x86" }
sourceSets{ main{ jniLibs.srcDirs = ['libs'] } }
第三步:生成与调用方有关的.h文件(C头文件)
在Android Studio下方的Terminal命令行里面执行生成命令,如果没有Terminal,到"View->Tool Windows->Terminal"里面打开该面板
操作命令:
javah -d jni -classpath <SDK_android.jar>;<dir path> 加载So所在的class包名+class名
后面的"<dir path> 加载So所在的class包名+class名"是相对于你当前所在目录的路径;
参考命令:
C:\git_source\demo\JniTest>javah -d jni -classpath C:\studio\android-sdk-windows\platforms\android-23\android.jar;app\src\main\java com.example.jni.jnitest.MainActivity这里的后面一部分是相对于"C:\git_source\demo\JniTest"目录的路径
命令执行成功会自动生成一个jni文件夹和对应的"包名.h"文件,这里的文件名是:com_example_jni_jnitest_MainActivity.h
第四步:编写C代码
C代码"main.c":
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> #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 com_example_jni_jnitest_MainActivity */ #ifndef _Included_com_example_jni_jnitest_MainActivity#define _Included_com_example_jni_jnitest_MainActivity#ifdef __cplusplus extern "C" { #endif /* * Class: com_example_jni_jnitest_MainActivity * Method: getStringFromNative * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_example_jni_jnitest_MainActivity_getStringFromNative(JNIEnv * env, jobject jObj){ return (*env)->NewStringUTF(env,"Hello From JNI!"); } #ifdef __cplusplus } #endif #endif
注意,你需要将com_example_jni_jnitest_MainActivity_getStringFromNative替换成你工程里面对应的方法路径
第五步:编写Android.mk文件和Application.mk文件
前面第一步的图里面可以看到jni包里面多了一个Android.mk文件和Application.mk文件,还有一个main.c文件是上一步我们生成的
Android.mk文件和Application.mk文件是用来控制编译So文件的, Android.mk文件控制So文件如何编译, Application.mk文件控制支持的架构平台.
Android.mk文件:
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)#bzlib模块bzlib_files := \main.cLOCAL_MODULE := libbzLOCAL_SRC_FILES := $(bzlib_files)include $(BUILD_STATIC_LIBRARY)#bspath模块include $(CLEAR_VARS)LOCAL_MODULE := mainLOCAL_SRC_FILES := main.cLOCAL_STATIC_LIBRARIES := libbz #引入libbz库include $(BUILD_STATIC_LIBRARY)include $(CLEAR_VARS)LOCAL_MODULE := JniTestLOCAL_SRC_FILES := main.cLOCAL_STATIC_LIBRARIES := mainLOCAL_LDLIBS := -llog#加入loginclude $(BUILD_SHARED_LIBRARY)
"bzlib_files :"里面放的是所有的c源文件;"LOCAL_MODULE := JniTest"表示生成的So库名,因为我加载So库的名字是"JniTest"所以这里需要同名;
static { System.loadLibrary("JniTest"); }
APP_CFLAGS += -Wno-error=format-securityAPP_ABI := armeabiAPP_ABI := armeabi 表示只支持armeabi架构的Jni,如需添加其他架构可在后面追加
第六步:编译So文件
在CMD命令行里面cd到项目的目录下, 输入"ndk-build"生成So包
命令执行成功后在工程的libs文件夹下面生成一个So文件,如下:
如果不添加Application.mk文件,会生成所有架构的So文件,如下:
编译出来的So默认是放在工程里面的libs文件夹下的,需要将它移到app文件夹下的libs里面!
第七步:打包运行
运行代码,查看结果:
这里打印出了C代码返回的值,Jni的调用就成功了!
三、遇到的问题与解决
问题一:找不到mk文件
原因是JniTest项目里面的jni目录下没有Android.mk文件
问题二:couldn't find "libJniTest.so"说找不到so文件(这里是libJniTest.so)
FATAL EXCEPTION: mainProcess: com.example.jni.jnitest, PID: 30152java.lang.UnsatisfiedLinkError: com.android.tools.fd.runtime.IncrementalClassLoader$DelegateClassLoader[DexPathList[[dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-support-annotations-23.4.0_d560f708638dfceb3917510f1cc1dc667f754e94-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_9-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_8-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_7-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_6-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_5-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_4-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_3-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_2-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_1-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-slice_0-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-internal_impl-23.4.0_00c09662b55d223b900e647a021f5f9dd9b4b6e9-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-com.android.support-support-vector-drawable-23.4.0_8b8204428df1954e75ed14d23129e230d51e4401-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-com.android.support-support-v4-23.4.0_ab900e8ce412421b38e4e809122c4e820ea3b15b-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-com.android.support-appcompat-v7-23.4.0_60d063a4fe66aa6d98c8e4fbd0183a230d80c604-classes.dex", dex file "/data/data/com.example.jni.jnitest/files/instant-run/dex/slice-com.android.support-animated-vector-drawable-23.4.0_7565542ff4cab32ab703cc056ccf47fe61af9054-classes.dex"],nativeLibraryDirectories=[/vendor/lib64, /system/lib64, /vendor/lib64, /system/lib64]]] couldn't find "libJniTest.so" at java.lang.Runtime.loadLibrary(Runtime.java:378) at java.lang.System.loadLibrary(System.java:998) at com.example.jni.jnitest.MainActivity.<clinit>(MainActivity.java:11) at java.lang.reflect.Constructor.newInstance(Native Method) at java.lang.Class.newInstance(Class.java:1572) at android.app.Instrumentation.newActivity(Instrumentation.java:1068) at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2303) at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2466) at android.app.ActivityThread.access$1200(ActivityThread.java:152) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1341) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5538) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:958)第一步:需要在app的build.gradle里面的Android{}里面添加如下代码,指定jni放置目录:
sourceSets{ main{ jniLibs.srcDirs = ['libs'] } }
第二步:然后将so文件放在app文件夹下的libs里面
第三步:编译运行
源代码:http://download.csdn.net/detail/u013210543/9594032
参考文章:http://blog.csdn.net/sodino/article/details/41946607
0 0
- Android Studio开发jni实例详解 (调用C代码实例)
- Android Studio Jni 开发实例
- Android Studio JNI开发实例
- Android studio使用JNI调用C语言实例详细解析
- Android JNI简单实例(android 调用C/C++代码)
- Android JNI简单实例(android 调用C/C++代码)
- Android JNI简单实例(android 调用C/C++代码)
- Android JNI简单实例(android 调用C/C++代码)
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- android JNI 实例代码
- Android NDK开发 Java与C互相调用实例详解
- Android NDK开发----- Java与C互相调用实例详解
- Android NDK开发----- Java与C互相调用实例详解
- Android JNI简单实例(Android java调用C/C++代码)
- Android studio使用JNI实例
- Android Studio JNI使用实例
- 关于Raphael.js 的画圆弧
- 牛顿迭代法求解方程
- HttpURLConnection加载图片存在本地
- 实现Parcelable的bean中有数组对象
- DispatcherServlet简介
- Android Studio开发jni实例详解 (调用C代码实例)
- 记录通过Map将list中包含相同字段的对象存放到一起,不同对象的分开
- Mybatis分页插件 - PageHelper
- HDU-5791-TWO-DP
- Candies-差分约束系统
- JVM之永久区Permanent区参数设置分析
- McBSP
- 欢迎使用CSDN-markdown编辑器
- visualizing higher-layer featrues of a deep network