如何用android studio搭建JNI(調用C/C++代碼)
剛學習了在android studio中調用C/C++代碼,現在做如下筆記
注:
-閱讀這篇文章大約需要:10分鐘
-這是我第一篇博客,有寫的不對的地方歡迎大家留言指正
-本篇文章適於 初學者
-我大部分是跟着http://blog.csdn.net/u013210543/article/details/52103015這篇文章學習的
前言:
爲何要調用C/C++代碼:
程序執行效率高
C效率>C++效率>JAVA效率
C與C++效率差的小些,C與JAVA效率差很多代碼安全性
Java代碼容易被反編譯出來
因此在android開發中會經常用到C/C++
在很多企業的圖片處理,視頻處理這種要求性能的功能中經常會用到(比如照片美顏,語音變聲大部分都是用C/C++完成),
或者一些保密性要求較高的例如通信協議,數據加密
看看效果
廢話少說
一,先新建一個工程
- 這裏不細說了,相信各位都能搞定
我這裏工程名叫 JniDemo
包名 com.gym.jnidemo
(那個Include C++ Support不知道是什麼,反正勾選後 他會在main文件夾下生成一個cpp文件夾 裏面給了一個c++的hello world,求大神給講解一下)
二,配置NDK以及環境變量
(1)studio內配置
(2)配置環境變量
此電腦,右鍵,屬性 然後看圖
在系統變量(也可以在上面的用戶變量)中添加了一個D:\assdk\ndk-build(D:\assdk 這個地方填你剛纔studio中所用到的sdk的路徑) 保存一下就配置完了
檢驗變量是否配置成功:
cmd命令中鍵入nk-build出現如圖就成功了
三,在項目中調用
(1)加載庫,定義函數
public class MainActivity extends AppCompatActivity {
//靜態代碼塊
static{
//加載C/C++類庫 這個hi_jni的名字是我們自己起的
System.loadLibrary("hi_jni");
}
//在這定義一個jni函數接口,跟C的頭文件以及C文件有對應關係
public native String getStringFromC();
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activi
ty_main);
}
(2)在app的build.gradle中配置ndk
android {
compileSdkVersion 25
buildToolsVersion "25.0.2"
defaultConfig {
applicationId "com.gym.jnidemo"
minSdkVersion 15
targetSdkVersion 25
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
//在defaultConfig 中配置ndk信息
ndk{
moduleName "hi_jni"
ldLibs "Log","z","m"
abiFilters "armeabi","armeabi-v7a","x86"
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
//在android 中配置.so文件存放位置
sourcesets{
main{
jniLibs.dir['lib']
}
}
}
(3)生成.h頭文件
用命令行(建議用Android studio的Terminal因爲它直接指向當前工程目錄中)
javah -d jni -classpath 這個地方寫sdk的platforms的任意一個版本文件夾的絕對路徑;app\src\main\java com.gym.jnidemo.MainActivity
我的效果如下:
完成後會在工程目錄下生成一個jni文件夾裏面帶一個頭文件
(4)寫一個.c文件
在jni文件夾中新建一個c文件
內容如下 我起的文件名main_activity.c
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_gym_jnidemo_MainActivity */
#ifndef _Included_com_gym_jnidemo_MainActivity
#define _Included_com_gym_jnidemo_MainActivity
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_gym_jnidemo_MainActivity
* Method: getStringFromC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_gym_jnidemo_MainActivity_getStringFromC
(JNIEnv * env, jobject jobj){
return (*env)->NewStringUTF(env,"從C返回的數據")
}
#ifdef __cplusplus
}
#endif
#endif
在jni文件夾中新建一個文件Application.mk內容如下
APP_CFLAGS += -Wno-error=format-security
APP_ABI := armeabi
在jni文件夾中新建一個文件Android.mk內容如下
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
#bzlib模塊
bzlib_files := \
main_activity.c
LOCAL_MODULE := libbz
LOCAL_SRC_FILES := $(bzlib_files)
include $(BUILD_STATIC_LIBRARY)
#bspath模塊
include $(CLEAR_VARS)
LOCAL_MODULE := main_activity
LOCAL_SRC_FILES := main_activity.c
LOCAL_STATIC_LIBRARIES := libbz #引入libbz庫
include $(BUILD_STATIC_LIBRARY)
include $(CLEAR_VARS)
LOCAL_MODULE := hi_jni
LOCAL_SRC_FILES := main_activity.c
LOCAL_STATIC_LIBRARIES := main_activity
LOCAL_LDLIBS := -llog#加入log
include $(BUILD_SHARED_LIBRARY)
四,生成so文件
(1)項目目錄下用ndk-build
(2)再把如圖所示的紅色文件夾裏生成的文件移動到藍綠色文件夾內就可以了
五,調用
在MainActivity中
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
//顯示
((TextView)findViewById(R.id.tv)).setText(getStringFromC());
}
大功告成!