레이블이 NDK인 게시물을 표시합니다. 모든 게시물 표시
레이블이 NDK인 게시물을 표시합니다. 모든 게시물 표시

2013년 3월 12일 화요일

[Android] Android NDK를 이용한 예제 작성

* 지난 번에 Android NDK의 빌드 환경을 설정했다. 그 때에는 빌드 환경을 설정하고, Android에서 제공하는 예제를 실행해 보는 것으로 끝났었다. 이제 Android NDK로 빌드하는 예제를 만들어 보고자 한다.

* Android NDK 예제를 찾다 보니, 잘 설명된 blog가 있어서, 그대로 따라하면서 Project를 생성해 본다.

1. 개발 환경

 * 개발 환경에 대해서는 지난 번 글([Android] Android NDK 빌드 환경 꾸미기)에서 했던 내용이다.

1-1. cygwin

Windows의 경우, cygwin 설치가 되어 있어야 한다. command창에서 javah나 ndk-build 명령을 실행한다.

2. Eclipse : Android Project 생성

 * Eclipse workspace에 새로운 프로젝트를 생성하자[File -> New -> Android Application Project].

 * Next를 클릭하여 다음으로 진행한다.
 * 프로젝트 정보
   - Application Name : NDKTest
   - Package Name : com.shnoh.ndktest
   - Activity Name : NDKTestMainActivity

package com.shnoh.ndktest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;

public class NDKTestMainActivity extends Activity {

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

2-1. Layout 구성

 * 단말 화면에 보여질 Layout을 구성한다.
   - 파일 위치 : NDKTest\res\layout\activity_ndktest_main.xml
 * Button 하나와 TextView 하나를 추가한다.



2-2. Activity 구현

 * Button과 TextView의 View ID를 가져온다.
 * Button을 눌러 JNI 함수를 호출하는 부분을 추가한다.
 * Native 함수를 호출할 class 이름을 NativeCall 이라고 만든다.

package com.shnoh.ndktest;

import android.os.Bundle;
import android.app.Activity;
import android.view.Menu;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.TextView;

public class NDKTestMainActivity extends Activity {

 private Button mBtn;
 private TextView mTextView;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_ndktest_main);
        
        mBtn = (Button) findViewById(R.id.callBtn);
        mTextView = (TextView) findViewById(R.id.textVal);
        
        mBtn.setOnClickListener(new OnClickListener() {
   
            @Override
            public void onClick(View arg0) {
                // TODO Auto-generated method stub
                NativeCall nativeCall = new NativeCall();
                int ret = nativeCall.add(10,20);
                String retStr = nativeCall.stringFromJNI();
                mTextView.setText(retStr);
            }
        });
    }   
}

2-3. JNI를 위한 class 생성

 * 앞 단계에서 이름 지은 NativeCall class를 생성한다.
   - 파일 위치 : NDKTest\src\com.shnoh.ndktest\NativeCall.java
 * 소스 내용
   - native 키워드 : javah 가 헤더(header) 파일을 생성할 때 참조하는 키워드임.
   - 구현부는 없음.
   - static 부분 : class 객체가 생성될 때(new 될 때) 호출됨.
   - System.loadLibrary("my_lib") : ndk-build로 생성된 lib 이름("my_lib").
   - Library 파일 명 : libmy_lib.so

package com.shnoh.ndktest;

public class NativeCall {

    static {
     System.loadLibrary("my_lib");
    }
    
    public native int add(int i, int j);

    public native String stringFromJNI();
 
}

2-4. javah 실행 : Native 소스를 위한 header 파일 생성

 * Eclipse의 NDKTest 프로젝트를 빌드를 하여, NativeCall.class 파일을 만든다.
 * Native 소스를 위한 header 파일 생성하기 위해 command창을 열어 javah 를 실행한다.
 * javah 의 실행 위치 및 command
   - 프로젝트 root 폴더에서 실행 :
     i. 명령어 : NDKTest>javah -classpath bin/classes com.shnoh.ndktest.NativeCall


     i. 결과 화면

   - 프로젝트 bin 폴더에서 실행 :
     i. NDKTest\bin>javah -classpath classes com.shnoh.ndktest.NativeCall


     i. 결과 화면

   - 한번만 해도 될 것을 테스트성으로 각기 다른 폴더에서 javah를 실행함.

 * 이제 프로젝트 루트 폴더에 /jni 폴더를 만들어, 위에서 만든 헤더 파일을 이동한다.


   - header 파일 내용

/* DO NOT EDIT THIS FILE - it is machine generated */
#include 
/* Header for class com_shnoh_ndktest_NativeCall */

#ifndef _Included_com_shnoh_ndktest_NativeCall
#define _Included_com_shnoh_ndktest_NativeCall
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_shnoh_ndktest_NativeCall
 * Method:    add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_shnoh_ndktest_NativeCall_add
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     com_shnoh_ndktest_NativeCall
 * Method:    stringFromJNI
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_shnoh_ndktest_NativeCall_stringFromJNI
  (JNIEnv *, jobject);

#ifdef __cplusplus
}
#endif
#endif

2-5. Native 소스 구현

 * jni 폴더에 my_lib.c 파일을 만들어, 위에서 선언한 함수들을 구현한다. 2개의 함수이다.
   - String을 return 해주는 함수
   - 2개의 정수를 입력 받아 합을 return 해주는 함수
 * my_lib.c 파일 내용

#include "com_shnoh_ndktest_NativeCall.h"

JNIEXPORT jstring JNICALL Java_com_shnoh_ndktest_NativeCall_stringFromJNI(JNIEnv *env, jobject obj)
{
    return (*env)->NewStringUTF(env, "Hello JNI!!!!!");
}

JNIEXPORT jint JNICALL Java_com_shnoh_ndktest_NativeCall_add(JNIEnv *env, jobject obj, jint i, jint j)
{
    return i + j;
}

2-6. Android.mk 파일 작성

 * 지난 번에 설치한 Android NDK의 Sample 폴더에 보면, hello-jni 폴더가 있다. 이 프로젝트의 Android.mk 파일을 가져와서 수정을 하자.
 * 수정된 부분은 LOCAL_MODULE 과 LOCAL_SRC_FILES 항목이다.
   - Android.mk 파일 내용

# Copyright (C) 2009 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    := my_lib
LOCAL_SRC_FILES := my_lib.c

include $(BUILD_SHARED_LIBRARY)

3. ndk-build : command 창 

 * 프로젝트의 root 폴더 또는 /jni 폴더에서 "ndk-build" 라는 명령을 실행한다.
   - 프로젝트 root 폴더에서 실행
     i. 명령어 : NDKTest>ndk-build


     i. 결과 화면

 * 빌드가 수행되고 나면, libs/armeabi 폴더에 "libmy_lib.so" 파일이 생성된다.

4. 실행 및 설치 : apk 빌드 및 설치

 * Eclipse 프로젝트에서 빌드 후 apk를 설치한다.

5. 실행 화면

 * apk를 실행하면 아래와 같은 화면을 볼 수 있다.



 * "Call JNI" Button을 누르면, "Hello JNI!!!!!" 라는 String이 보인다.


 * 2개의 정수를 더한 값을 return하는 것은 연결되어 있지 않다.

6. 샘플 소스

 * 위에서 사용한 샘플 소스이다.
   - https://snoh@bitbucket.org/snoh/androidndk
   - Mercurial command : hg clone https://snoh@bitbucket.org/snoh/androidndk

7. 출처 및 참고 사이트


7-1. 안드로이드 공식 사이트

 * Getting Started with the NDK
   -  http://developer.android.com/tools/sdk/ndk/index.html#GetStarted

7-2. 개인 블로그

 * Memories collected..."추억수집" : NDK를 이용한 안드로이드 App 기본예제
   - http://viiiin.tistory.com/12
 * 박상현님의 블로그 : javah 사용법
   - http://blog.naver.com/PostList.nhn?blogId=multisunchon&categoryNo=26&from=postList




2012년 8월 23일 목요일

[Android] Android NDK 빌드 환경 꾸미기

Android NDK Build 환경을 세팅할 일이 생겼다. 하나씩 하면서 진행해보자.

1. Android NDK 다운로드

 * http://developer.android.com/tools/sdk/ndk/index.html
 * 여기에서 Windows 용으로 다운로드 한다.
  - Revision 8b (July 2012) 버전이다.

 * 적당한 폴더를 지정하여 압축을 푼다.

 * 환경 변수 설정

  <Windows 경우>

   - ANDROID_NDK 라는 이름으로, 압축 푼 root 폴더를 지정해주자.

  <Linux 경우>

   - $HOME 경로에 보면 .bashrc 파일이 있다. 여기에 path를 설정해 주자.
    i. export PATH=${PATH}:/home/압축푼폴더/android-ndk-r8b
   - 입력 후 나와서, source .bashrc 라고 하면 적용된다.

2. Cygwin 다운로드(Windows만 해당)

 * http://cygwin.com/install.html
 * 여기에서 setup.exe 라고 되어 있는 link를 클릭하면, setup.exe 파일이 다운로드 된다.
 * 설치를 시작한 후, next 버튼을 눌러가며 진행한다.
 * 설치할 package를 묻는 창이 나오면, 아래 4개의 package를 선택하자.
  - Devel category
   i. devel/gcc-core
   i. devel/gcc-g++
   i. devel/make
  - editor category
   i. editor/gvim
   i. editor/vim 관련(2개 있음)
 * 설치를 마치는데까지 시간이 좀 걸린다.

3. 빌드를 해보자.

<Windows 경우>

 * 압축을 푼 NDK 폴더로 가서, ndk-build 를 실행해보자.
  - hello-jni 폴더로 들어가서, ndk-build 를 치면 잘 빌드되어, so파일도 잘 생긴다.
  - 1번에서 이미, ANDROID_NDK 라는 이름의 환경 변수를 만들어서, path에 등록을 해줬으니, 프로젝트 파일이 있는 곳(정확히는 /jni/Android.mk 파일이 있는 root 폴더)에서 ndk-build라고 하면 되는 것이다.
 * D:\~~~\hello-jni\libs\armeabi 폴더에 가면, libhello-jni.so 파일이 생성됨을 알 수 있다.

<Linux 경우>

 * 역시 마찬가지다. 1번에서 PATH를 설정해줬기 때문에, 실제 빌드할 폴더로 가서 ndk-build 만 입력하면 잘된다.
  - samples에 있는 hello-jni 폴더로 가서 하면 바로 libhello-jni.so 파일이 만들어짐을 알 수 있다.

4. 이클립스에서 hello-jni 프로젝트 생성해 보자.

 * 이클립스 화면

 * 설정 등을 해주고, application을 빌드하면 화면에 "Hello from JNI!" 라는 문구가 나오는 화면을 볼 수 있다.

5. Next 단계


 * Android NDK 예제를 만들어 보자.
  -  [Android] Android NDK를 이용한 예제 작성

6. 참고 사이트

 * android 공식 사이트 (NDK 다운로드 및 사용법)
  - http://developer.android.com/tools/sdk/ndk/index.html
 * cygwin 공식 사이트 ( install page)
  - http://cygwin.com/install.html
 * 기타 블로그
  - http://ninako21.tistory.com/487
  - http://mytv.pe.kr/tc/536
  - http://omen666.tistory.com/463
  - http://kottodat.com/xe/811 (Linux)