환경 설정 및 NDK 설치는  http://kylblog.tistory.com/14  여기서 확인 하시고 이 포스트를 보시면 됩니다.



1. JNI 폴더 생성 및 JNI 샘플 코드 작성


  프로젝트명 - app - src - main - jni 폴더 생성


안드로이드 스튜디오에서 바로 생성하셔도 되고 폴더에 들어가서 새폴더로 생성하셔도 무관합니다.





C 파일 생성 후 샘플코드를 작성 해 보겠습니다



// 헤더파일은 생성 후 추후에 넣도록 합니다


//JNIEXPORT jstring JNICALL Java_ < 자신의 프로젝트명, 클래스명 입력>_<원하는 함수명 입력>


JNIEXPORT jstring JNICALL Java_com_example_user_myapplication_MainActivity_getJNI(JNIEnv *env, jobject obj) {

return env->NewStringUTF("Message from jniMain);

} 





2. java 소스 코드 작성 ( JNI 호출)


java 소스 코드에서 JNI 코딩한 것을 호출하는 코드를 입력해 보겠습니다.


호출 된 텍스트 문은 TextView에 뿌려주도록 합니다.


 

public class MainActivity extends AppCompatActivity {

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);


TextView jniText = (TextView)findViewById(R.id.Text);
jniText.setText(getJNI());


}

static {
System.loadLibrary("FirstJNI"); // 원하는 라이브러리 명 입력, Android.mk 파일에서 입력할 LOCAL_MODULE 명과 맞추면 됩니다.

}
public native String getJNI();

}






3. 헤더 파일 생성


헤더 파일을 가지고 있어서 JNI 코드가 오류 없이 실행 할 수 있습니다.


헤더 파일을 간편하게 실행하기 위해서 만들어준 Tool 은 이전 포스트에서 확인 할 수 있습니다.  http://kylblog.tistory.com/14


java 코드 오른쪽 클릭 후 External Tool 클릭 ( 저는 Group을 ndk 로 적었기에 ndk 이며 기본은 Externel Tool 입니다.)






Externel Tools 실행 후 제대로 실행이 되었다면 jni 폴더에 cpp 폴더 외에 .h 파일이 생성되었을 것 입니다.


.h 생성 후 cpp 파일에 헤더 파일 추가



 #include <com_example_user_myapplication_MainActivity.h>   // 자신의 프로젝트 명과 클래스명 입력해주시면 됩니다.

JNIEXPORT jstring JNICALL Java_com_example_user_myapplication_MainActivity_getJNI(JNIEnv *env, jobject obj) {

return env->NewStringUTF("hello jni");
}





3. Android.mk 파일 생성


프로젝트명 - app - src - main - jni 폴더 에서 Android.mk 파일을 생성하여 입력합니다.


LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := FirstJNI
LOCAL_SRC_FILES := <자신의cpp파일명>.cpp
LOCAL_LDLIBS := -llog

include $(BUILD_SHARED_LIBRARY) 




4. build.gradle(app) 수정 

   

   추가할 부분만 추가해주시면 됩니다.


 import org.apache.tools.ant.taskdefs.condition.Os

apply plugin: 'com.android.application'


///////////////////////////////////////////////////////////////////////////////////////////추가
// Project Structure에서 설정한 NDK 경로를 읽어들여 Return합니다.
def getNdkBuildPath() {
Properties properties = new Properties()
properties.load(project.rootProject.file('local.properties').newDataInputStream())

def command = properties.getProperty('ndk.dir')
if (Os.isFamily(Os.FAMILY_WINDOWS)) {
command += "\\ndk-build.cmd"
} else {
command += "/ndk-build"
}

return command
}


//////////////////////////////////////////////////////////////////////////////////////////////
android {
compileSdkVersion 23
buildToolsVersion "23.0.3"

defaultConfig {
applicationId "com.example.user.myapplication"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"

ndk {
abiFilters "armeabi","armeabi-v7a"
}
}
/////////////////////////////////////////////////////////////////////////////////////////////추가


sourceSets.main {
// Compile된 Native Library가 위치하는 경로를 설정합니다.
jniLibs.srcDir 'src/main/libs'

// 여기에 JNI Source 경로를 설정하면 Android Studio에서 기본적으로 지원하는 Native
// Library Build가 이루어집니다. 이 경우에 Android.mk와 Application.mk를
// 자동으로 생성하기 때문에 편리하지만, 세부 설정이 어렵기 때문에 JNI Source의
// 경로를 지정하지 않습니다.
jni.srcDirs = []
}

ext {
// 아직은 Task 내에서 Build Type을 구분할 방법이 없기 때문에 이 Property를
// 이용해 Native Library를 Debugging 가능하도록 Build할 지 결정합니다.
nativeDebuggable = true
}

// NDK의 ndk-build 명령을 이용하여 Native Library를 Build하기 위한 Task를 정의합니다.
//noinspection GroovyAssignabilityCheck
task buildNative(type: Exec, description: 'Compile JNI source via NDK') {
if (nativeDebuggable) {
commandLine getNdkBuildPath(), 'NDK_DEBUG=1', '-C', file('src/main').absolutePath
} else {
commandLine getNdkBuildPath(), '-C', file('src/main').absolutePath
}
}

// App의 Java Code를 Compile할 때 buildNative Task를 실행하여 Native Library도 같이
// Build되도록 설정합니다.
tasks.withType(JavaCompile) {
compileTask -> compileTask.dependsOn buildNative
}

// NDK로 생성된 Native Library와 Object를 삭제하기 위한 Task를 정의합니다.
//noinspection GroovyAssignabilityCheck
task cleanNative(type: Exec, description: 'Clean native objs and lib') {
commandLine getNdkBuildPath(), '-C', file('src/main').absolutePath, 'clean'
}

// Gradle의 clean Task를 실행할 떄, cleanNative Task를 실행하도록 설정합니다.
clean.dependsOn 'cleanNative'

//////////////////////////////////////////////////////////////////////////////////////////////


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:23.4.0'
}




5. gradle.properties 수정


  위의 작업을 마무리 하시고 build 작업을 하시면 gradle.properties 오류가 발생 합니다.


   android.useDeprecatedNdk=true   


  추가 후 rebuild를 하시면 








C 로 작성한 것을 불러 오는 걸 확인 하실 수 있습니다.


만약 실행이 안되신다면 .so 파일이 생성되었는지 확인하거나 Crean Project 후에 build 해보세요!







+ Recent posts