android studio ndk 開發以及問題
阿新 • • 發佈:2019-01-25
1,環境準備下載的ndk
2,android studio 配置ndk
第一種方式配置
local.properties
sdk.dir=D\:\\installtool\\sdk\\sdk
ndk.dir=D\:\\tools\\android\\android-ndk-r10d-windows\\android-ndk-r10d
第二種方式配置
快捷鍵F4 彈出專案結構對話方塊,選擇ndk目錄
3,在專案的src/main建立jni目錄
jni 目錄裡面建立Android.mk和後面這個檔案不要Application.mk也是可以
Android.mk 裡面有需要編譯的c/c++原始檔,模組的名字要正確,這裡的模組名字就是在java。loadLibrary時候需要的
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := JniTest
LOCAL_SRC_FILES := math.cpp
include $(BUILD_SHARED_LIBRARY) //表明是動態庫
配置專案裡的build.gradle
關鍵的有ndk和sourceSets 設定jni載入檔案目錄
ndk 是在defaultConfig 裡面配置
moduleName第一個模組名字
ldLibs 在jni裡面列印android log 日誌
abiFilters 編譯生成的平臺型別
這裡配置了,所以在Android.mk裡面就不用配置載入日誌,還有Application.mk 配置編譯生成平臺,如果配置了,build.gradle 的優先順序也是最高的
4,建立jni的java的類
這裡有2個native 方法,通過靜態塊載入動態so檔案
package com.framework.ui.activity;
public class MathJNI {
static {
System.loadLibrary("JniTest");
}
public native String get();
public native void set(String name);
}
5,通過javah 生成c/c++的頭部檔案
javah在jdk的bin目錄下面
這裡的目錄只能到debug下面,如果在其他目錄會生成標頭檔案失敗
生成的標頭檔案
com_framework_ui_activity_MathJNI.h 包名+類名
第二種方式
在app/src/main/java 通過命令生成 目錄也只能到這裡 ,目錄在包裡面就不行了
標頭檔案生成了,就是為了實現標頭檔案的方法,相當與java裡面額介面定義了,要實現介面
6,在jni建立.c/.cpp檔名字隨便
生成的頭部檔案
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_framework_ui_activity_MathJNI */
#ifndef _Included_com_framework_ui_activity_MathJNI
#define _Included_com_framework_ui_activity_MathJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_framework_ui_activity_MathJNI
* Method: get
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_framework_ui_activity_MathJNI_get
(JNIEnv *, jobject);
/*
* Class: com_framework_ui_activity_MathJNI
* Method: set
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_framework_ui_activity_MathJNI_set
(JNIEnv *, jobject, jstring);
#ifdef __cplusplus
}
#endif
#endif
把生成的頭部檔案內容複製到,.c/.cpp的檔案裡面
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
#include <stdio.h> //匯入檔案
/* Header for class com_framework_ui_activity_MathJNI */
#include <android/log.h>//匯入android日
#define TAG "my-jni" // 這個是自定義的LOG的標識
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定義LOGD型別
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定義LOGI型別
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定義LOGW型別
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定義LOGE型別
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定義LOGF型別
#ifndef _Included_com_framework_ui_activity_MathJNI
#define _Included_com_framework_ui_activity_MathJNI
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_framework_ui_activity_MathJNI
* Method: get
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_framework_ui_activity_MathJNI_get
(JNIEnv *env, jobject jObj){
return env->NewStringUTF("Hello From JNI!");
}
/*
* Class: com_framework_ui_activity_MathJNI
* Method: set
* Signature: (Ljava/lang/String;)V
*/
JNIEXPORT void JNICALL Java_com_framework_ui_activity_MathJNI_set
(JNIEnv *env, jobject jObj, jstring jstr) {
char *str = (char*)env->GetStringUTFChars(jstr,NULL);
LOGD("########## i = %s", str);
}
#ifdef __cplusplus
}
#endif
#endif
拷貝過來的時候需要修改的 方法加上{}括號,把引數改了正確,應為頭部裡面的定義的方法只有型別,沒有型別的名字,在實現裡面全部不全。
android 執行呼叫的結果
@Override
protected void initViewAndEvent() {
TLog.d(TAG_LOG, new MathJNI().get());
new MathJNI().set("test");
}
07-05 05:07:16.126 17678-17678/com.framework D/com.framework.ui.activity.FirstActivity: FirstActivity.java (31) initViewAndEvent: Hello From JNI!
07-05 05:07:16.126 17678-17678/com.framework D/my-jni: ########## i = test
在windows 上面會出現這個錯誤
Error:Execution failed for task ‘:app:compileDebugNdk’.
通過在jni目錄建立一個空的utils.c或者utils.cpp都可以,編譯就能通過了
jni的java對應的資料型別表 圖來自android開發藝術探索