使用ndk-build命令手動配置生成so共享庫
正確步驟:首先生成so共享庫,然后再配置到當(dāng)前工程模塊中進行引用
說明:Android Studio 2.2 CMake只支持64位系統(tǒng)(stackflow中詳細(xì)說明)捅位,所以只能使用ndk-build命令手動生成so共享庫(自己32位電腦zaza算途,沒辦法)离熏,CMake方式的可以查看文章后面提供的參考連接突想,同時也提供了谷歌官方的在線參考文檔欠啤。
1. 使用native
關(guān)鍵字來聲明本地方法
HelloJni.java
package com.shellever.hellojni;
public class HelloJni {
// A native method that is implemented by the 'hello-jni' native library (libhello-jni.so)
public native static String getStringFromJni();
}
2. 使用JDK工具javah
命令來自動創(chuàng)建頭文件(.h)
2.1 切換工程面板為Android界面,選擇app目錄右鍵選擇/NEW/Folder/JNI Folder
來創(chuàng)建一個jni目錄咽扇,此時會出現(xiàn)一個跟java同級的cpp
目錄
2.2 切換工程面板為Project界面邪财,則會出現(xiàn)一個跟java同級的jni
目錄
2.3 使用javah命令來生成頭文件的操作如下:
> cd ./app/src/main/java
> javah -d ../jni com.shellever.hellojni.HelloJni
命令終端Terminal中javah命令詳細(xì)執(zhí)行情況如下:
執(zhí)行完javah命令后會在jni目錄中生成.h頭文件(com_shellever_hellojni_HelloJni.h
):
頭文件內(nèi)容如下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_shellever_hellojni_HelloJni */
#ifndef _Included_com_shellever_hellojni_HelloJni
#define _Included_com_shellever_hellojni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_shellever_hellojni_HelloJni
* Method: getStringFromJni
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_shellever_hellojni_HelloJni_getStringFromJni
(JNIEnv *, jclass);
#ifdef __cplusplus
}
#endif
#endif
3. 創(chuàng)建源文件并實現(xiàn)頭文件中聲明的方法(.c/.cpp)
切換工程面板至Project界面,并選中/app/src/main/jni
目錄质欲,右鍵選擇/NEW/C/C++ Source File
來創(chuàng)建一個與頭文件同名的.c源文件(或者.cpp源文件)
完整的源文件實現(xiàn)代碼如下:
//
// Created by shellever on 12/16/2016.
//
#include "com_shellever_hellojni_HelloJni.h"
// D:\MySoftware\MyDevelopment\Android\Sdk\ndk-bundle\platforms\android-17\arch-arm\usr\include\jni.h
JNIEXPORT jstring JNICALL Java_com_shellever_hellojni_HelloJni_getStringFromJni
(JNIEnv *env, jclass clazz)
{
// In C code
return (*env)->NewStringUTF(env, "Hello from JNI!");
// In C++ code
// return env->NewStringUTF("Hello from JNI!");
}
4. 編寫mk編譯文件
4.1 Android.mk
切換工程面板至Project界面树埠,并選中/app/src/main/jni
目錄,右鍵選擇/NEW/File
來創(chuàng)建Android.mk
編譯文件嘶伟,配置內(nèi)容如下:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := hello-jni
LOCAL_SRC_FILES := com_shellever_hellojni_HelloJni.c
include $(BUILD_SHARED_LIBRARY)
4.2 Application.mk
切換工程面板至Project界面怎憋,并選中/app/src/main/jni
目錄,右鍵選擇/NEW/File
來創(chuàng)建Application.mk
編譯文件九昧,配置內(nèi)容如下:
# Define the target architecture to be ARM or other.
#APP_ABI := all
#APP_ABI := arm64-v8a armeabi armeabi-v7a mips mips64 x86 x86_64
APP_ABI := arm64-v8a armeabi armeabi-v7a
5. 使用NDK工具ndk-build
命令生成so共享庫
使用ndk-build命令來生成頭文件的操作如下:
> cd ../jni
> ndk-build
命令終端Terminal中ndk-build命令詳細(xì)執(zhí)行情況如下:
命令ndk-build執(zhí)行成功后會生成與jni同級的libs
和obj
兩個目錄(可以手動刪除掉obj目錄):
6. 將so共享庫配置到當(dāng)前工程模塊(app)中進行引用
在/app/build.gradle
配置文件中配置ndk-build命令所生成的so共享庫路徑绊袋,或者直接創(chuàng)建一個jniLibs目錄:/app/src/main/jniLibs/,然后將so庫拷貝到此目錄下即可铸鹰,這樣就不再需要指定libs路徑了癌别。詳細(xì)配置如下:
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"
defaultConfig {
applicationId "com.shellever.hellojni"
minSdkVersion 17
targetSdkVersion 23
versionCode 1
versionName "1.0"
testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
// Specify the shared library
sourceSets {
main {
// 1st step: MUST disable automatic ndk-build call
jni.srcDirs = []
// 2nd step: MUST specify the .so path (/app/src/main/libs)
jniLibs.srcDirs = ['src/main/libs'] // Default: /app/libs
}
}
}
buildTypes {
release {
minifyEnabled false
proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
}
}
}
另一種libs路徑配置方式:
// Config here
sourceSets.main {
jni.srcDirs = [] // MUST disable automatic ndk-build call firstly
jniLibs.srcDir "src/main/libs" // MUST specify the .so path secondly
}
7. 演示結(jié)果
Reference
Android Studio 2.2 更方便地創(chuàng)建JNI項目-CMake
Getting Started with the NDK (Google Official)
googlesamples/android-ndk