android jni方式调用c++代码并在其它app中使用生成的.so文件
2016-10-18 21:46
806 查看
搞了一下午终于明白了一点机制,网上的代码太乱了,很多不经过验证就转载的,强烈谴责这种行为。以下所写都是android studio测试运行过的,欢迎交流指正。运行前提是在project structure中配置好ndk路径,并且配置好ndk环境变量。想看入门demo的童鞋不要再到处下载了,ndk文件目录下有一个samples,里面都是官方demo,例如hello-jni,不过是eclipse的项目。如果能帮到你,记得点个赞。
概括一下主要步骤:下载并配置ndk环境变量,并在studio中指明一致的ndk路径——>编写native方法名,根据生成的对应.h文件,用c或者cpp实现对应方法,并将.h和.cpp或者.c文件放到jni目录下——>在build.gradle文件中添加ndk属性,在jni目录下创建Android.mk和Application.mk文件,rebuild。
注意:.c和.cpp的格式的一模一样功能的函数有可能是不同的写法,并且.cpp一定要加extern “C” { } ,一定要注意,否则可能No implement了就。
具体可以参考这篇文章:http://blog.csdn.net/fengbingchun/article/details/11580983
一、使用android jni调用c++代码
①.在java代码中声明native方法
②.打开view->tool windows->terminal,cd到app项目的java目录下,cd app/src/main/java。然后进行如下操作,也就是包名+native方法声明的class名,稍后会生成一个.h文件:
.h文件内容如下,机器生成的文件不需要修改:
③.在和app模型java目录并列创建jni文件夹,将生成的com_lbb_hellojnitest_NdkJniUtils.h文件剪切进去。然后创建main.c文件,文件名字是任意的。内容如下,主要是实现机器生成的头文件的声明的方法:
④.在app的build.gradle文件的defaultConfig下添加ndk属性,定义生成的.so文件的名称,文件名如果是以lib开头则不添加lib,否则添加lib字段,例如以下配置将在app-libs目录下生成libnativeTest.so。我的文件内容如下:
⑤.clean project->rebuild project,切换回project视图下在/app/build/intermediates/ndk/debug/lib目录下应该已经生成了.so文件了。此时可以在activity中调用了:
二、生成.so库文件供其它app调用。
完成上述步骤已经可以调用c++实现的方法了,如果想要进一步控制生成.so库文件供其它应用使用,则需要在jni目录下创建Android.mk和Application.mk,分别用于控制.so本身属性以及生成哪些cpu平台下的.so文件。关于具体介绍可以查看ndk路径下的docs->Start_Here.html官方文档。我的Android.mk和Application.mk是复制的官方demo也就是hello-jni项目下的,然后修改的。
Android.mk内容如下:
Application.mk文件内容如下:
两个文件都整理好之后,在终端或者在view-Tool Windows-Terminal
终端窗口下,cd到jni目录下,执行ndk-build命令。前提是已经配置好系统ndk环境变量,如何配置请百度。执行完之后再app模型下会自动创建一个libs目录并且包含了生成的.so文件,至此.so库文件生成完毕
三、android studio其它项目中导入刚才生成的.so文件并使用
①.创建一个新的android studio 项目,将刚才生成的libs目录下的文件夹全部复制到新项目的app模型下的libs目录,然后配置app的build-cradle指定jniLibs.srcDirs目录为libs文件。我的app的build-gradle文件内容如下:
②.成功引入.so库文件之后要考虑调用了,我简单的认为.so文件是需要特定的包名和类名以及方法名的,所以我在此创建了和之前一样包名和类名以及方法名的类。(后来发现百度地图的.so文件也是通过引入其jar包中定义的固定包名类名的类来调用.so文件中的native方法的,所以应该是木错的)
我在此demo中我创建的是com.lbb.hellojnitest.NdkJniUtils类,类的内容如下,就是和之前项目中保持一致:
③.定义好之后就可以使用了,和之前的使用时一样一样的,稍微需要注意的是.so文件是以lib开头的,因为生成时系统自己添加lib,但System.loadLibrary()的时候是不用加前面的lib的。:
我的两个demo下载链接:
http://download.csdn.net/detail/lishaobo211985/9657737
概括一下主要步骤:下载并配置ndk环境变量,并在studio中指明一致的ndk路径——>编写native方法名,根据生成的对应.h文件,用c或者cpp实现对应方法,并将.h和.cpp或者.c文件放到jni目录下——>在build.gradle文件中添加ndk属性,在jni目录下创建Android.mk和Application.mk文件,rebuild。
注意:.c和.cpp的格式的一模一样功能的函数有可能是不同的写法,并且.cpp一定要加extern “C” { } ,一定要注意,否则可能No implement了就。
具体可以参考这篇文章:http://blog.csdn.net/fengbingchun/article/details/11580983
一、使用android jni调用c++代码
①.在java代码中声明native方法
public class NdkJniUtils { public static native String getCLanguageString(); }
②.打开view->tool windows->terminal,cd到app项目的java目录下,cd app/src/main/java。然后进行如下操作,也就是包名+native方法声明的class名,稍后会生成一个.h文件:
javah -jni com.lbb.hellojnitest.NdkJniUtils
.h文件内容如下,机器生成的文件不需要修改:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_lbb_hellojnitest_NdkJniUtils */ #ifndef _Included_com_lbb_hellojnitest_NdkJniUtils #define _Included_com_lbb_hellojnitest_NdkJniUtils #ifdef __cplusplus extern "C" { #endif /* * Class: com_lbb_hellojnitest_NdkJniUtils * Method: getCLanguageString * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_lbb_hellojnitest_NdkJniUtils_getCLanguageString (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
③.在和app模型java目录并列创建jni文件夹,将生成的com_lbb_hellojnitest_NdkJniUtils.h文件剪切进去。然后创建main.c文件,文件名字是任意的。内容如下,主要是实现机器生成的头文件的声明的方法:
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <com_lbb_hellojnitest_NdkJniUtils.h> JNIEXPORT jstring JNICALL Java_com_lbb_hellojnitest_NdkJniUtils_getCLanguageString(JNIEnv *env, jobject jObj){ //return env->NewStringUTF("Hello from JNI!"); return (*env)->NewStringUTF(env, "Hello From JNI!"); }
④.在app的build.gradle文件的defaultConfig下添加ndk属性,定义生成的.so文件的名称,文件名如果是以lib开头则不添加lib,否则添加lib字段,例如以下配置将在app-libs目录下生成libnativeTest.so。我的文件内容如下:
apply plugin: 'com.android.application' android { compileSdkVersion 24 buildToolsVersion "24.0.1" defaultConfig { applicationId "com.lbb.hellojnitest" minSdkVersion 15 targetSdkVersion 24 versionCode 1 versionName "1.0" ndk { moduleName "nativeTest" } } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.2.1' }
⑤.clean project->rebuild project,切换回project视图下在/app/build/intermediates/ndk/debug/lib目录下应该已经生成了.so文件了。此时可以在activity中调用了:
public class MainActivity extends Activity { protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); // NdkJniUtils jni = new NdkJniUtils(); Toast.makeText(this,NdkJniUtils.getCLanguageString(),Toast.LENGTH_SHORT).show(); } static { System.loadLibrary("nativeTest"); } }
二、生成.so库文件供其它app调用。
完成上述步骤已经可以调用c++实现的方法了,如果想要进一步控制生成.so库文件供其它应用使用,则需要在jni目录下创建Android.mk和Application.mk,分别用于控制.so本身属性以及生成哪些cpu平台下的.so文件。关于具体介绍可以查看ndk路径下的docs->Start_Here.html官方文档。我的Android.mk和Application.mk是复制的官方demo也就是hello-jni项目下的,然后修改的。
Android.mk内容如下:
# Copyright (C) 2010 The Android Open Source Project # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. # You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := nativeTest LOCAL_SRC_FILES := main.c include $(BUILD_SHARED_LIBRARY)
Application.mk文件内容如下:
APP_ABI := all APP_PLATFORM := android-10
两个文件都整理好之后,在终端或者在view-Tool Windows-Terminal
终端窗口下,cd到jni目录下,执行ndk-build命令。前提是已经配置好系统ndk环境变量,如何配置请百度。执行完之后再app模型下会自动创建一个libs目录并且包含了生成的.so文件,至此.so库文件生成完毕
三、android studio其它项目中导入刚才生成的.so文件并使用
①.创建一个新的android studio 项目,将刚才生成的libs目录下的文件夹全部复制到新项目的app模型下的libs目录,然后配置app的build-cradle指定jniLibs.srcDirs目录为libs文件。我的app的build-gradle文件内容如下:
apply plugin: 'com.android.application' android { compileSdkVersion 24 buildToolsVersion "24.0.1" defaultConfig { applicationId "com.lbb.solibtest" minSdkVersion 15 targetSdkVersion 24 versionCode 1 versionName "1.0" } buildTypes { release { minifyEnabled false proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' } } sourceSets { main { jniLibs.srcDirs = ['libs'] } } } dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) testCompile 'junit:junit:4.12' compile 'com.android.support:appcompat-v7:24.2.1' }
②.成功引入.so库文件之后要考虑调用了,我简单的认为.so文件是需要特定的包名和类名以及方法名的,所以我在此创建了和之前一样包名和类名以及方法名的类。(后来发现百度地图的.so文件也是通过引入其jar包中定义的固定包名类名的类来调用.so文件中的native方法的,所以应该是木错的)
我在此demo中我创建的是com.lbb.hellojnitest.NdkJniUtils类,类的内容如下,就是和之前项目中保持一致:
package com.lbb.hellojnitest;
/**
* 作者:李少波
* 邮箱:lishaobo@seengene.com
* 日期:16/10/18
*/
public class NdkJniUtils { public static native String getCLanguageString(); }
③.定义好之后就可以使用了,和之前的使用时一样一样的,稍微需要注意的是.so文件是以lib开头的,因为生成时系统自己添加lib,但System.loadLibrary()的时候是不用加前面的lib的。:
package com.lbb.solibtest; import android.support.v7.app.AppCompatActivity; import android.os.Bundle; import android.widget.Toast; import com.lbb.hellojnitest.NdkJniUtils; public class MainActivity extends AppCompatActivity { static { System.loadLibrary("nativeTest"); } @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toast.makeText(this, NdkJniUtils.getCLanguageString(),Toast.LENGTH_SHORT).show(); } }
我的两个demo下载链接:
http://download.csdn.net/detail/lishaobo211985/9657737
相关文章推荐
- android studio中使用ndk编译.so文件,调用C/C++代码(jni编程)
- Android使用JNI生成.so文件并调用(使用传统生成.h的方法)
- Android使用JNI生成.so文件并调用(使用CMake的方法)
- Android中JNI使用详解(1)---Eclipse中NDK配置So文件生成
- android jni开发 把一段java代码转换成c++方式调用
- 在Android中使用JNI调用Opencv本地代码 配置方式 边缘检测 范例代码
- Android中JNI使用详解(3)---Android Studio中SO文件生成
- 如何调用已有的SO文件来生成供Android使用的SO文件
- Mac下使用Android的Jni生成动态库so文件,并打包到APK包说明
- [转]Android通过NDK调用JNI,使用opencv做本地c++代码开发配置方法
- Android App中通过JNI调用C/C++代码(二)
- java使用JNI调用C++代码(vs2010生成dll文件)
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法 边缘检测 范例代码
- java使用JNI调用C++代码(vs2010生成dll文件)
- android jni开发 把一段java代码转换成c++方式调用
- 【Android】Android中使用JNI调用底层C++代码
- Android App中通过JNI调用C/C++代码
- 编译代码在Android中使用JNI调用Opencv本地代码 配置方式 边缘检测 范例代码
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法实现边缘检测代码(2)
- Android(安卓)开发通过NDK调用JNI,使用opencv做本地c++代码开发配置方法 边缘检测 范例代码