Linux/버전관리2009. 5. 25. 13:10

cvs서버 다운로드 : http://www.march-hare.com/cvspro/#downcvsnt

CVSNT 를 사용중 피시를 옮기거나 OS 를 재설치를 할 경우 서버 세팅을 해야하는데 잘 모르시는분들이 많더군요.

 

얼떨결에 OS를 교체하게 되었는데 CVS세팅을 복원시키는것에 대해서 잠시 당황해 했지만 그다지 어렵지 않습니다.

 

 



1. 백업해놓은 CVS Repository 폴더를 적당한 위치에 둡니다.

 

2. CVS Control pannel 을 열어서 CVS Repository 위치를 잡아줍니다.

 

3. CVS Repository 의 Name 항목을 기존 항목과 동일하게 잡아줍니다.

 +- Name 이 기억이 나지 않는다면 해당 Repository 를 사용하는 파일이 위치하는 폴더에서 CVS폴(숨겨져있음)을 찾아서 Root 파일을 텍스트에디터로 열어보면 나옵니다.

 

4. 서비스를 재시작하고 접속테스트를 합니다.

 

여기까지 하면 일반적으로 백업해둔 CVS를 복원하는것입니다.

 

* 사용자의 ID 가 변경되었을 경우

 +- 기본적으로 백업 전의 사용자 계정을 똑같이 새로운 피시에 입력해두어야합니다. 비밀번호도 동일하도록 하는것이 좋습니다. 하지만 사용자의 계정이 입력이 안될경우(저같은경우 새로운 피시의 컴퓨터 이름을 이전의 CVS 아이디로 지정할 경우 윈도우 사용자 계정으로 추가할 수 없음) 가 있습니다.

  +- 프로젝트를 통째로 지우고 CVS에서 새로 생성된 ID 로 다시 Checkout 을 받는 방법

  +- 기존의 프로젝트 폴더에서 검색으로 모든 Root 파일을 찾은 후에 내부에 지정된 아이디를 새로운 아이디로 몽땅 교체하는 방법

 

Posted by 삼스
Android/Porting2009. 5. 19. 13:25

http://andrwj.blogspot.com/2009/05/howto-cupcake-kernel-2627-on-virtua.html


HOWTO: Cupcake (kernel 2.6.27) on VirtualBox 2.2.2


Cupcake (kernel 2.6.27) on VirtualBox 2.2.2

2009.5.19 REV#002
Andrew J. Kim<andrwj@gmail.com>

$ sudo su
# apt-get install ssh flex bison gperf libsdl-dev libesd0-devlibwxgtk2.6-dev build-essential zip curl valgrind sun-java6-jdk git-core gnupg zlib1g-dev libncurses5-dev
# curl http://android.git.kernel.org/repo > /usr/local/bin/repo
# chmod +x /usr/local/bin/repo
# mkdir -p /home/aj/eeePC

# cd /home/aj/eeePC
# repo init -u git://android.git.kernel.org/platform/manifest.git -b cupcake
# repo sync
# cd .repo
# vim local_manifest.xml
<xml ?="" encoding="UTF-8" version="1.0"> <manifest> <project name="platform/vendor/asus/eee_701" path="vendor/asus/eee_701"> </project> </manifest>
# cd ..
# repo sync


x86 patch

# cd /home/aj/
# mkdir android.patch
# cd android.patch

(download all patches from http://code.google.com/p/patch-hosting-for-android-x86-support/downloads/list)
# vim frameworks_v2.patch  (insert at first row)
project frameworks/base/
# vim 0001-1.-added-mouse-cursor.patch
(insert at first row)
project frameworks/base/

(modify  line #15 ~ 18)
diff --git a/core/java/android/view/RawInputEvent.java b/core/java/android/view/RawInputEvent.java
index 30da83e..4d9a11a 100644
--- a/core/java/android/view/RawInputEvent.java
+++ a/core/java/android/view/RawInputEvent.java



# cd /home/aj/eeePC
# vim patch.sh
#!/bin/bash
for patch in `pwd`/android.patch/*.patch ; do
        project=`awk '/^project /{print $2}' $patch`
        if [[ "$project" == "" ]]; then
                echo "not found"
        else
                (cd $project && patch -p1 < $patch)
        fi
done

# chmod +x patch.sh
# ./patch.sh


# vim vendor/asus/eee_701/eee_701.mk
$(call inherit-product, $(SRC_TARGET_DIR)/product/generic_with_google.mk)


(modify as .. )

$(call inherit-product, $(SRC_TARGET_DIR)/product/generic.mk)


SquashFS kernel patch


# cd /home/aj/
(download squashfs from http://nchc.dl.sourceforge.net/sourceforge/squashfs/squashfs3.4.tar.gz)
# tar xvfz squashfs4.0.tar.gz
# cd eeePC/
# patch -p1 < /home/aj/squashfs4.0/kernel-patches/linux-2.6.27-rc4/squashfs3.4-patch


AUFS kernel patch (DOT NOT apply)


참조사이트: http://aufs.sourceforge.net/
# cd /home/aj/

# git clone http://git.c3sl.ufpr.br/pub/scm/aufs/aufs2-standalone.git aufs2-standalone.git

# cd /home/aj/eeePC/kernel
# patch -p1 < /home/aj/aufs2-standalone.git/aufs2-standalone.patch
# vim fs/Makefile (#126 line, add)

obj-$(CONFIG_AUFS_FS)           += aufs/



kernel config


# cd /home/aj/eeePC
# cp vendor/asus/eee_701/kernel.config kernel/.config
# cd kernel

# make menuconfig
enable squashfs


building Android ...


# cd /home/aj/eeePC/

# TAGET_ARCH=x86 TARGET_PRODUCT=eee_701 DISABLE_DEXPREOPT=true make -j2 droid
# cd /home/aj/eeePC/out/target/product/eee_701/
# /home/aj/eeePC/vendor/asus/eee_701/make_boot_img.sh
# VBoxManage convertfromraw --format VDI installed.img eee701.vdi



Screenshot



Posted by 삼스

공개API 호환화… 중소 SNS사이트 '위젯' 공유

온라인 광고와 결합 수익창출
거대 SNS사이트 타격 입을듯



구글이 제휴업체들과 손잡고 하나의 웹애플리케이션(위젯)을 다수의 소셜네트워킹서비스(SNS) 사이트들에서 사용할 수 있게 하는 `호환화' 작업에 나선다. 이 전략이 성공을 거둘 경우 여러 중소 SNS 사이트들이 위젯을 공유할 수 있게 돼 마이스페이스나 페이스북 같은 거대 사이트들에 맞설 수 있는 계기를 마련할 것으로 전망된다.

◇`오픈소셜' 프로젝트로 SNS사이트들을 하나로=뉴욕타임스 등 외신들은 구글이 SNS용 공개 애플리케이션프로그래밍인터페이스(API) 보급을 목적으로 하는 `오픈소셜' 플랫폼 프로젝트를 추진하기로 했다고 31일(현지시각) 보도했다.

이 프로젝트에 참여의사를 밝힌 SNS 사이트들은 구글의 자회사인 오컷(Orkut)을 포함해 링크드인(LinkedIn), 하이파이브(Hi5), 프렌드스터(Friendster), 플락소(Plaxo), 닝(Ning) 등이다. 기업용 소프트웨어 업체인 오라클과 세일즈포스도 프로젝트에 동참한다.

API는 블로그, 지도, 채팅, 검색, 날씨 등의 다양한 위젯을 손쉽게 만들 수 있도록 하는 일종의 개발 도구다. API가 공개되면 누구나 자신이 원하는 각종 애플리케이션을 스스로 제작해 해당 웹사이트에서 사용할 수 있다. 오픈소셜 프로젝트에 참가하는 SNS 사이트들은 공개API를 통해 개발된 위젯을 공유할 수 있게 되는 셈이다. 구글은 오픈소셜 기반 위젯의 이용자 수가 1억명을 넘을 것으로 기대하고 있다. 위젯과 온라인 광고를 결합한다면 새로운 매출을 이끌어낼 수 있을 것으로 예상된다. 구글의 조 크라우스 이사는 "이번 프로젝트로 큰 이익을 거둘 것"이라고 자신감을 보였다.

◇거대 SNS 사이트들에는 위협이 될 듯=이에 따라 마이스페이스나 페이스북 같은 거대 SNS 사이트들은 신경을 곤두세워야 할 입장에 처했다. 특히 지난 5월 경쟁자들보다 앞서 공개API를 도입해 총 8000여개의 위젯을 확보하는 성과를 거둔 페이스북에게는 타격이 불가피할 것으로 보인다. 페이스북의 위젯 개발에 참여해 왔던 `아이라이크(iLike)', `슬라이드(Slide)', `플릭스터(Flixter)', `락유(RockYou)' 등의 업체들이 오픈소셜 프로젝트에 관여하기로 한 것도 불길한 징조다. 아이라이크의 알리 파토비 CEO는 "그동안 다른 SNS 사이트들의 위젯 제작 요청을 많이 받았지만 여기에 일일이 응할 수 없었다"며 "오픈소셜 프로젝트의 장점은 우리가 동시에 여러 SNS 사이트들에 위젯을 공급할 수 있는 일종의 신디케이트가 된다는 것"이라고 말했다.

이와 관련, 일각에서는 페이스북이 지분 매각처로 구글 대신 마이크로소프트(MS)를 선택한 배경에 오픈소셜 프로젝트가 있다는 분석을 내놓고 있다. 프로젝트 소식을 접한 페이스북이 구글을 견제하기 위해 MS와 손잡았다는 것이다. MS는 지난주 페이스북 지분 1.6%를 2억4000만달러에 인수하기로 합의했다.

◇투자자들의 높은 기대 속에 주가 700달러 돌파=투자자들도 이번 프로젝트에 큰 관심을 나타냈다. 31일 나스닥 시장에서 구글의 주가는 전날보다 12.23달러(1.76%)오른 707.00달러로 마감, 700달러선을 돌파했다. 지난달 8일 600달러를 넘어선지 3주일 만이다. 시가총액은 2206억8000만달러로 마이크로소프트(3443억7000만달러)에 이어 IT업계 2위를 기록하고 있다.

애널리스트들은 구글의 주가가 계속해서 상승세를 유지할 것으로 보고 있다. 가장 낙관적인 전망을 내놓은 다이노소어 증권의 데이비드 개리티 애널리스트는 내년 구글의 주가가 985달러까지 오를 것으로 내다봤다.

Posted by 삼스
Linux2009. 5. 17. 13:04
1. target platform 선정
2. cross compiler 설정
  gcc를 선정하게 되는데 platform에 맞는 컴파일러를 선정하면된다.
  ARM용 gcc는 아래위치에서 다운로드 가능하다.
  http://www.handhelds.org/download/projects/toolchain
  root권한으로 압축 해재
  #cp ./arm-linux-gcc-3.4.2.tar.bz2 /
  #cd /
  #tar xvjf arm-linux-gcc-3.4.2.tar.bz2
  이렇게 하면 /usr/local/arm/3.4.2디렉토리 밑으로 설치가 된다.
  #arm-lunux-gcc
    arm-linux-gcc: no input files


Posted by 삼스
Android/App개발2009. 5. 15. 17:52

playToEnd() function in CodecTest.java .

public static boolean playToEnd(String filePath){
        Log.v(TAG, "shortMediaStop - " + filePath);
        //This test is only for the short media file
        int duration = 200000;
        int updateDuration = 0;
        int currentPosition = 0;
        boolean isPlaying = false;
        MediaPlayer mp = new MediaPlayer();
        try{
            Thread.sleep(5000);
            mp.setDataSource(filePath);
            Log.v(TAG, "start playback");
            mp.prepare();
            //duration = mp.getDuration();
            mp.start();
            Thread.sleep(50000);
        }catch (Exception e){}
        isPlaying = mp.isPlaying();
        currentPosition = mp.getCurrentPosition();
        //updateDuration = mp.getDuration();
        Log.v(TAG, "seekToEnd currentPosition= " + currentPosition + " isPlaying = " + isPlaying);
        mp.stop();
        mp.release();  
        //Log.v(TAG, "duration = " + duration);
        //Log.v(TAG, "Update duration = " + updateDuration);
        if (currentPosition > duration || isPlaying)
            return false;
        else
            return true;       
    }

    public static boolean seektoBeforeStart(String filePath){
        Log.v(TAG, "seektoBeforeStart - " + filePath);
        //This test is only for the short media file
        int duration = 0;
        int currentPosition = 0;

        MediaPlayer mp = new MediaPlayer();
        try{
            mp.setDataSource(filePath);
            mp.prepare();
            duration = mp.getDuration();
            mp.seekTo(duration - 10000);
            mp.start();
            currentPosition=mp.getCurrentPosition();
            mp.stop();
            mp.release();
        }catch (Exception e){}
        if (currentPosition < duration/2)
            return false;
        else
            return true;       
    }

Posted by 삼스
JAVA2009. 5. 15. 15:55



JNI(Java Native Interface) 

플랫폼 독립성을 버리고, 기능을 취한다.

자바 프로그램을 작성하다보면, 부득이하게 시스템 의존적 코딩을 필요로 하는 때가 있다. 하지만, 자바로서는 그러한 욕구를 감당할 수는 없다. 따라서, 자바의 클래스 파일이 C/C++의 함수를 호출하여, 그 결과만 되돌려받게 하는 것도 한 방법이다. 그렇지만 이 자체로서 이미 플랫폼 독립적이라는 특성은 사라졌다고 볼 수밖에 없다.

 

프로그램 작성

 

첫째 단계, 자바 프로그램 작성 

 

우선, Native접근이 필요한 메쏘드만 native 키워드를 사용해 구현하지 않은 채 그대로 두고, 나머지는 모두 구현한 후, 컴파일한다.public class Hello {
    public native void getHello();    static {
        System.loadLibrary("hello");
    }
    
    public static void main(String[] args) {
        new Hello().getHello();
    }
}

javac Hello.java public native void getHello() : getHello 함수가 native method라는 것을 의미한다.static {
        System.loadLibrary("hello");
}이것은 공유 라이브러리를 실행시 로드하는 코드로 반드시 static 초기화에 포함되어야 한다. 이것은 플랫폼에 따라 다르게 행동하는데, 만일 Win32이면, hello.dll을, 솔라리스이면, libhello.so라는 이름의 라이브러리를 찾는다.

 

둘째 단계, C프로그램을 위한 헤더 파일 생성

 

javah와 -jni옵션을 이용하여, 헤더파일을 생성해 보자.javah -jni Hello생성된 헤더 파일 Hello.h는 다음과 같다./* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>

/* Header for class Hello */

#ifndef _Included_Hello
#define _Included_Hello
#ifdef __cplusplus
extern "C" {
#endif


/*
 * Class:     Hello
 * Method:    getHello
 * Signature: ()V
 */


JNIEXPORT void JNICALL Java_Hello_getHello
  (JNIEnv *, jobject);#ifdef __cplusplus
}
#endif
#endif여기서 생성된 함수 이름에 주목해 보자. '_'를 구분자로 크게 몇 부분으로 나뉘어져 있다.

    • Java : 항상 앞에 붙는다.
    • Hello : 클래스의 이름
    • getHello : 메쏘드의 이름

 

셋째 단계, 함수를 구현한다.

 

HelloImpl.c라는 이름으로 함수를 구현해 보자.#include <jni.h>
#include "Hello.h"
#include <stdio.h>JNIEXPORT void JNICALL Java_Hello_getHello(JNIEnv *env, jobject obj)
{
    printf("OOPSLA\n");
    return;
}

넷째 단계, C파일을 컴파일하여, 공유 라이브러리를 생성한다.

이때, 비주얼 C++을 이용할 경우 다음과 같은 옵션을 준다.cl /I본인의 자바 디렉토리)\include /I(본인의 자바 디렉토리)\include\win32 -LD HelloImp.c -Fehello.dll솔라리스에서 컴파일할 경우 다음과 같은 옵션을 준다.cc -G -I(자바 홈 디렉토리)/include -I(자바 홈 디렉토리)/include/solaris HelloImp.c -o libhello.so

 

마지막 단계, 프로그램을 실행한다.

 

java Hello실행 결과:OOPSLA

 

자바의 타입과 C++/C의 타입 매핑 문제

 

네이티브 메쏘드를 호출하는 것까지는 좋다. 하지만, 그 결과값이 있을 경우에는 타입의 괴리(Impedence)가 존재할 수밖에 없다. 따라서, jni.h에는 자바의 타입을 흉내낼 수 있는 여러 가지 타입을 정의해 놓았다.

Primitive Types

네이티브 메쏘드에서는 보통 자바의 타입 이름 앞에 j가 붙은 이름을 가진 타입을 사용함으로써, 마치 자바 프로그램을 작성하는 듯이 프로그램할 수 있다. 예를 들어, boolean은 jni.h에 jboolean이라는 이름의 타입과 매핑된다.

  • jboolean  : 자바의 boolean(8비트) - typedef unsigned char   jboolean
  • jbyte : 자바의 byte(8) - typedef signed char jbyte(WIN32의 경우이다. - System Dependent)
  • jchar  : 자바의 char(16) - typedef unsigned short  jchar
  • jshort : 자바의 short(16) - typedef short  jshort
  • jint : 자바의 int(32) - typedef long jint(WIN32의 경우이다. - System Dependent)
  • jlong : 자바의 long(64) - typedef __int64 jlong(WIN32의 경우이다. - System Dependent)
  • jfloat : 자바의 float(32) - typedef float jfloat
  • jdouble : 자바의 double(64) - typedef double  jdouble;
  • void : 자바의 void

위의 리스트에서, 오른쪽은 실제 jni.h가 이 타입들을 어떻게 정의하고 있는지를 보여 준다. 여기서, jbyte, jint, jlong은 시스템에 따라 적용할 타입이 변경될 소지가 있으므로, WIN32의 경우, 자바디렉토리\include\win32\jni_md.h에 정의되어 있다. 솔라리스인 경우에는 참고로 다음과 같다.#ifdef _LP64 /* 64-bit Solaris */
typedef int jint;
#else
typedef long jint;
#endif
typedef long long jlong;
typedef signed char jbyte;

 

객체 타입

 

이 경우에도 비슷하다. 일반 객체는 jobject타입으로 통용하고, 나머지 특수한 클래스에 대해 매핑되는 타입을 두기로 한다.

  • jobject : 모든 자바 객체로 뒤에 나열된 모든 타입의 슈퍼 타입이다.
  • jstring : 자바의 java.lang.String클래스이다.
  • jclass : 자바의 java.lang.Class클래스이다.
  • jarray : 자바의 배열이다.
  • jthrowable ; 자바의 java.lang.Throwable 예외 사항이다.

배열

기타, 기본 타입의 배열을 위한 배열 타입도, 하나의 클래스로 정의되어 있다.jbooleanArray;
jbyteArray;
jcharArray;
jshortArray;
jintArray;
jlongArray;
jfloatArray;
jdoubleArray;
jobjectArray; 

 

함수와 메쏘드간의 인자 전달

 

문제는 jstring을 비롯한 타입들은 실제 printf문 같은 곳에서 직접 쓰일 수 없다는 것이다. 이것들은 다시, C/C++의 타입으로 변환되어 사용되어야 한다. 이것에 관한 여러 함수들이 JNIEnv라는 구조체에 정의되어 있다.예를 들어, String객체를 C메쏘드에 넘기도록 앞의 Hello.java를 수정해 보자. 자바 소스는 단순히 선언을 바꾸는 것으로 끝난다.public native void getHello(String name);재컴파일과, javah를 이용해 만든 새로운 헤더 파일을 이용해 HelloImpl.c를 새로 작성해 보면,JNIEXPORT void JNICALL Java_Hello_getHello(JNIEnv *env, jobject obj,jstring name)
{
      char *str_name = (*env)->GetStringUTFChars(env, name, 0);
      printf("Hello %s\n",str_name);
      (*env)->ReleaseStringUTFChars(env, name, str_name);
      return;
}이와 같이, JNIEnv의 멤버 함수로부터 도움을 받아야 한다. 이제 각 타입에 대해 인자 전달과 결과값 반환 방법을 알아 보자.

 

Primitive Types

 

기본 타입의 경우에는 다음과 같이 기존의 C/C++타입중 호환되는 타입의 재명명이므로, 그다지 인자 전달에 문제가 없다.typedef unsigned char   jboolean;
typedef unsigned short  jchar;
typedef short           jshort;
typedef float           jfloat;
typedef double          jdouble;

WIN32:


typedef long jint;
typedef __int64 jlong;
typedef signed char jbyte;다만, boolean의 경우에는 true/false값이 다음과 같이 전달된다.#define JNI_FALSE 0
#define JNI_TRUE 1예를 들어, boolean타입의 인자를 주고, 반환받는 경우,Hello.java:
Hello h = new Hello();
System.out.println("h.getBoolean(true) = "+h.getBoolean(true));    // 결과 : trueHelloImpl.c:
JNIEXPORT jboolean JNICALL Java_Hello_getBoolean(JNIEnv * env, jobject jobj, jboolean jbool)
{
       ......
        return JNI_TRUE;
}

 

배열 타입

 

각 기본 타입에 따라 그 배열을 다룰 수 있는 배열 클래스가 제공된다. jarray
jbooleanArray
jbyteArray
jcharArray
jshortArray
jintArray
jlongArray
jfloatArray
jdoubleArray모든 배열 클래스들은 jarray 클래스의 하위 클래스이다.

 
배열의 길이 파악

 

모든 배열의 길이를 알아낼 수 있는 함수는 다음과 같다.jsize GetArrayLength(JNIEnv *, jarray array)(jsize는 jint와 동일하다)

 
자바의 배열을 C의 배열로 변환하는 함수

 

각 타입마다 자바 타입의 배열을 C타입으로 변환시켜 주는 함수가 있다.

  • jboolean * GetBooleanArrayElements(JNIEnv *env,jbooleanArray array, jboolean *isCopy)
  • jbyte * GetByteArrayElements(JNIEnv *env,jbyteArray array, jboolean *isCopy)
  • jchar * GetCharArrayElements(JNIEnv *env,jcharArray array, jboolean *isCopy)
  • jshort * GetShortArrayElements(JNIEnv *env,jshortArray array, jboolean *isCopy)
  • jint * GetIntArrayElements(JNIEnv *env,jintArray array, jboolean *isCopy)
  • jlong * GetLongArrayElements(JNIEnv *env,jlongArray array, jboolean *isCopy)
  • jfloat * GetFloatArrayElements(JNIEnv *env,jfloatArray array, jboolean *isCopy)
  • jdouble * GetDoubleArrayElements(JNIEnv *env,jdoubleArray array, jboolean *isCopy)

 

정수의 경우를 예로 들어 보자.       jsize iSize = (*env)->GetArrayLength(env,jiarray);
       jint *iArray = (*env)->GetIntArrayElements(env,jiarray,0);
       for(i=0; i < iSize; i++) {
                printf("iArray[%d] = %d\n",i,iArray[i]);
                iArray[i]++;
       }
       (*env)->ReleaseIntArrayElements(env,jiarray,iArray, 0);  자바의 배열을 JNI에서 사용할 경우, 이것은 현재의 실행 루틴을 수행하는 쓰레드가 이 배열 객체에 대해 PIN 연산을 수행하거나, 아니면 전체의 로컬 복사본을 사용하게 되는 것이다. 이로 인해, 이 연산의 반대 급부로 반드시 UNPIN연산에 해당하는 ReleaseIntArrayElements가 불려지는 것이 좋다.

  • void ReleaseBooleanArrayElements(JNIEnv *env,jbooleanArray array,  jboolean *elems,  jint mode)
  • void ReleaseByteArrayElements(JNIEnv *env,jbyteArray array, jbyte *elems, jint mode)
  • void ReleaseCharArrayElements(JNIEnv *env,jcharArray array, jchar *elems,  jint mode)
  • void ReleaseShortArrayElements(JNIEnv *env,jshortArray array, jshort *elems,  jint mode)
  • void ReleaseIntArrayElements(JNIEnv *env,jintArray array, jint *elems, jint mode)
  • void ReleaseLongArrayElements(JNIEnv *env,jlongArray array, jlong *elems, jint mode)
  • void ReleaseFloatArrayElements(JNIEnv *env,jfloatArray array, jfloat *elems, jint mode)
  • void ReleaseDoubleArrayElements(JNIEnv *env,jdoubleArray array, jdouble *elems, jint mode)

 

이 외에도 다음과 같은 함수들이 있다.

 

  • jdoubleArray NewDoubleArray(jsize len)를 비롯해 각 기본 타입마다 새로운 자바 배열을 생성할 수 있다.
  • void GetBooleanArrayRegion(jbooleanArray array, jsize start, jsize len, jboolean *buf)를 비롯해 각 기본 타입마다 Sub배열을 획득할 수 있는 함수가 제공된다.

 

자바 객체의 사용

 

네이티브 코드 내에서 자바 객체를 사용할 수도 있다. 즉 콜백과 비슷한 형식을 지원한다. private영역까지 접근할 수 있다.

 

자바 객체의 클래스 정보 얻기

 

일단, 인자로 넘겨지는 자바 객체에 대한 클래스 정보를 획득하는 함수가 제공된다.jclass cls = (*env)->GetObjectClass(env, jobj);여기서 주의할 것은 반환값으로 돌아오는 cls의 레퍼런스값은 오직 이 네이티브 메쏘드가 수행이 끝날 동안에만 유효하다는 것이다.

자바 객체 및 클래스 타입의 래퍼런스는 네이티브 메쏘드 실행시마다 결정되므로, 한 번 실행해 얻은 레퍼런스를 다음번 메쏘드에서 다시 사용하려는 것은 잘못된 것이다.

따라서, 원칙적으로 객체 레퍼런스 변수를 전역 변수로 할당하는 것은 위험한 일이다. 하지만, 꼭 허용되지 않는 것은 아니다. 전역 레퍼런스로 지정해 줄 수 있는 함수가 있다. jobject NewGlobalRef(JNI_Env* env, jobject lobj)   

 

네이티브 코드를 호출한 객체의 메쏘드에 대한 ID얻기

 

객체의 메쏘드를 호출하기 위해 그 메쏘드의 ID를 획득해야 한다. 이것은 메쏘드의 이름과 시그너쳐를 이용하는데, 이름은 별 무리가 없겠으나, 시그너쳐는 까다롭다. 시그너쳐는 메쏘드의 인자 리스트와 반환 타입 정보를 스트링화한 것으로, 다음과 같은 규칙이 있다.

  • 시그너쳐 : "(인자 리스트)반환값"으로 이루어진 스트링이다.
  • 인자리스트의 인자들은 아래의 타입 기호에 따라 표기되며, 서로 ';'으로 구분된다.
  • 반환값 역시 타입 기호에 따라 표시된다.

타입 기호는 다음과 같다. 이것은 자바 가상 머신 스펙에서 클래스 파일 포맷 부분에 등장하는 기호와 동일하다.Z :  boolean  
B :  byte
C :  char
S :  short
I  :  int
J :  long
F :  float
D : double

  • 이들의 배열은 이들의 타입 기호 앞에 '['를 붙인다. 즉 int 배열은 [I가 된다.
  • 클래스 타입의 경우, L뒤에 클래스명을 패키지명까지 포함해 나열하면 된다. 즉, String클래스인 경우, Ljava.lang.String이다.

 

이것은 수작업으로 할 경우, 실수가 많을 수 있으나, javap를 이용해, 쉽게 기호화된 시그너쳐를 확인할 수 있다.javap -s -p HelloCompiled from Hello.java
class Hello extends java.lang.Object {
    static {};
        /*   ()V   */
    Hello();
        /*   ()V   */
    public static void coo(java.lang.String, java.lang.String);
        /*   (Ljava/lang/String;Ljava/lang/String;)V   */
    private void foo(java.lang.String, java.lang.String);
        /*   (Ljava/lang/String;Ljava/lang/String;)V   */
    public native boolean getBoolean(boolean);
        /*   (Z)Z   */
    public native byte getByte(byte);
        /*   (B)B   */
    public native char getChar(char);
        /*   (C)C   */
    public native double getDouble(double);
        /*   (D)D   */
    public native float getFloat(float);
        /*   (F)F   */
    public native java.lang.String getHello(java.lang.String);
        /*   (Ljava/lang/String;)Ljava/lang/String;   */
    public native int getInt(int);
        /*   (I)I   */
    public native int getIntArray(int[])[];
        /*   ([I)[I   */
    public native long getLong(long);
        /*   (J)J   */
    public native short getShort(short);
        /*   (S)S   */
    public static void main(java.lang.String[]);
        /*   ([Ljava/lang/String;)V   */
}

 

이것은 다음과 같이 Hello클래스에 두 메쏘드를 추가한 후의 javap결과이다.   

 

private void foo(String str,String str1) {
        System.out.println("Hello.foo() = "+str+str1);
    }    public static void coo(String str,String str1) {
        System.out.println("Hello.coo() = "+str+str1);
    }이제 foo메쏘드의 ID를 획득해 보자.    // 클래스 정보 획득
    jclass cls = (*env)->GetObjectClass(env, obj);

    // 메쏘드 ID
    jmethodID fooM = (*env)->GetMethodID(env, cls, "foo", "(Ljava/lang/String;Ljava/lang/String;)V");

    // 그런 메쏘드가 없으면, 0반환
    if(fooM == 0) {
        printf("Method foo isn't found\n");
    }
    else {
               ......
    }  

 

인자 생성 및 메쏘드 호출

 

이제 메쏘드를 호출하는 일이 다음 순서가 되겠다. 물론 여기에 해당되는 함수들이 제공되는데, 이 함수들을 통해, 클래스 내의 메쏘드를 호출하므로, 메쏘드 ID와 더불어 메쏘드의 인자들을 리스트화해서 보내야 한다. 두 가지 방법이 있다.

  • C의 va_list구조체를 이용한다.
  • jvalue 유니온를 이용한다.

 

여기서는 jvalue 유니온을 이용해 보자. 그 구조는 다음과 같다.typedef union jvalue {
    jboolean z;
    jbyte    b;
    jchar    c;
    jshort   s;
    jint     i;
    jlong    j;
    jfloat   f;
    jdouble  d;
    jobject  l;
} jvalue;그러면, 스트링 두 개를 인자로 받는  foo메쏘드를 호출해 보자. String은 객체이므로, l에 스트링 객체의 레퍼런스를 할당하면 된다.jvalue* args;
.......


args = (jvalue*)malloc(sizeof(jvalue)*2);
args[0].l = (*env)->NewStringUTF(env,"oops");
args[1].l = (*env)->NewStringUTF(env,"la");
(*env)->CallVoidMethodA(env, obj, fooM,args );   // JNIEnv, jobject, Method ID, jvalue여기에서는 foo가 void 타입이므로,  CallVoidMethodA가 쓰였지만, 이 외에에도 반환값에 따라 여러 함수가 제공된다. 이들의 인자는 위와 동일하다.

  • jboolean CallBooleanMethodA
  • jbyte CallByteMethodA
  • jchar CallCharMethodA
  •  jshort CallShortMethodA
  •  jint CallIntMethodA
  •  jfloat CallFloatMethodA
  •  jdouble CallDoubleMethodA

참고로, va_list를 이용하여 인자를 전달하는 함수들은 A로 끝나지 않고, V로 끝나는데, 역시 마지막 인자만 va_list타입으로 수정해 주면 된다. 

정적 메쏘드 호출

정적 메쏘드 또한 호출할 수 있는 함수가 따로 있다.

메쏘드 ID : GetStaticMethodID함수 이용

jMethodID cooM = (*env)->GetStaticMethodID(env, cls, "coo", "(Ljava/lang/String;Ljava/lang/String;)V");
if(cooM == 0) {
        printf("Method foo isn't found\n");
    }
else {  .....

 
인자 형성 방법은 동일하다.

 

메쏘드 호출 : CallStaticVoidMethodA 이용

 

cooM = (*env)->GetStaticMethodID(env, cls, "coo", "(Ljava/lang/String;Ljava/lang/String;)V");
if(cooM == 0) {
        printf("Method foo isn't found\n");
}
else {
        args = (jvalue*)malloc(sizeof(jvalue)*2);
        args[0].l = (*env)->NewStringUTF(env,"papa");
        args[1].l = (*env)->NewStringUTF(env,"ya");
        (*env)->CallStaticVoidMethodA(env, cls, cooM,args );
} 여기서 주의할 것은 CallStaticVoidMethodA의 두 번째 인자는 jobject타입이 아닌, jclass타입이란 것이다. 클래스 메쏘드이니 당연하기도 하다. 

 

상위 클래스의 메쏘드 호출

 

한 걸음 더 나아가 상위 클래스의 메쏘드도 호출할 수 있다. 여기에 해당되는 메쏘드는 모두 NonVirtual이라는 이름을 포함하고 있는데, c++을 배운 이라면, NonVirtual의 의미를 알고 있을 것이다.

 

상위 클래스 타입의 jclass 객체 획득

 

jclass sClass = (*env)->GetSuperclass(env,cls);

 

메쏘드 ID : GetMethodID함수 이용

 

superFooM = (*env)->GetMethodID(env, sClass, "foo", "(Ljava/lang/String;Ljava/lang/String;)V");
if(superFooM == 0) {
      printf("Method foo isn't found\n");
}
else {
       .....
}

 

 메쏘드를 호출: CallNonvirtualVoidMethodA

 

args = (jvalue*)malloc(sizeof(jvalue)*2);
args[0].l = (*env)->NewStringUTF(env,"can");
args[1].l = (*env)->NewStringUTF(env,"dy");
 (*env)->CallNonvirtualVoidMethodA(env,obj,sClass ,superFooM,args );

 

멤버 필드 접근

 

 필드를 접근하는 방법 또한 메쏘드를 접근하는 방법과 크게 다르지 않다. 필드가 Private일지라도 접근할 수 있다. 이 또한 몇 가지 함수에 의존하고 있는데, 그 함수의 형식이 메쏘드를 호출하는 함수와 거의 유사하기 때문이다. 일단 다음의 기호를 잊지 말자.Z :  boolean  
B :  byte
C :  char
S :  short
I  :  int
J :  long
F :  float
D : double

  • 이들의 배열은 이들의 타입 기호 앞에 '['를 붙인다. 즉 int 배열은 [I가 된다.
  • 클래스 타입의 경우, L뒤에 클래스명을 패키지명까지 포함해 나열하면 된다. 즉, String클래스인 경우, Ljava.lang.String이다.

 

 이제 Hello.java에 몇 가지 필드를 추가해 보자.    private int intVal;
    private static int iStaticIntVal;
    private String strVal = "Hello";이를 재컴파일 후, javah를 실행하고, 새로이 생긴 함수의 선언부를 HelloImpl.c로 복사해 이것에 대해 추가적으로 구현해 보기로 하자.필드를 접근하는 것은 두 단계로 이루어진다.

  • 클래스와 필드의 이름과 타입을 이용해 필드의 ID를 얻어낸다.
  • 필드의 ID와 객체를 이용해 실제 필드의 값을 얻어낸다.

 

인스턴스 필드 접근

 

먼저 필드의 ID를 얻어내기 위한 함수는 다음과 같다. jfieldID GetFieldID(JNI_Env* env,jclass clazz, const char *name, const char *sig)
그리고, 인스턴스 필드를 접근하는 함수들은 다음과 같다.

 
1) Read 함수

 

  • jobject GetObjectField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jboolean GetBooleanField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jbyte GetByteField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jchar GetCharField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jshort GetShortField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jint GetIntField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jlong GetLongField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jfloat GetFloatField(JNI_Env* env,jobject obj, jfieldID fieldID)
  • jdouble GetDoubleField(JNI_Env* env,jobject obj, jfieldID fieldID)
 
2) Write 함수

 

  • void SetObjectField(JNI_Env* env,jobject obj, jfieldID fieldID, jobject val)
  • void SetBooleanField(JNI_Env* env,jobject obj, jfieldID fieldID, jboolean val)
  • void SetByteField(JNI_Env* env,jobject obj, jfieldID fieldID,jbyte val)
  • void SetCharField(JNI_Env* env,jobject obj, jfieldID fieldID, jchar val)  
  • void SetShortField(JNI_Env* env,jobject obj, jfieldID fieldID,jshort val)
  • void SetIntField(JNI_Env* env,jobject obj, jfieldID fieldID,jint val)
  • void SetLongField(JNI_Env* env,jobject obj, jfieldID fieldID, jlong val)
  • void SetFloatField(JNI_Env* env,jobject obj, jfieldID fieldID, jfloat val)
  • void SetDoubleField(JNI_Env* env,jobject obj, jfieldID fieldID, jdouble val)

 

 

클래스 필드 접근

 

Static 필드를 접근하기 위해 먼저 ID를 얻어내야 한다.jfieldID GetStaticFieldID(JNI_Env* env,jclass clazz, const char *name,  const char *sig)그리고, 필드를 접근하는 함수들은 다음과 같다.

 
Getter 함수

 

  • jobject GetStaticObjectField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jboolean GetStaticBooleanField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jbyte GetStaticByteField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jchar GetStaticCharField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jshort GetStaticShortField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jint GetStaticIntField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jlong GetStaticLongField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jfloat GetStaticFloatField(JNI_Env* env,jclass clazz, jfieldID fieldID)
  • jdouble GetStaticDoubleField(JNI_Env* env,jclass clazz, jfieldID fieldID)
 
Setter 함수

 

  • void SetStaticObjectField(JNI_Env* env,jclass clazz, jfieldID fieldID, jobject value)
  • void SetStaticBooleanField(JNI_Env* env,jclass clazz, jfieldID fieldID, jint value)
  • void SetStaticByteField(JNI_Env* env,jclass clazz, jfieldID fieldID, jbyte value)
  • void SetStaticCharField(JNI_Env* env,jclass clazz, jfieldID fieldID, jchar value)
  • void SetStaticShortField(JNI_Env* env,jclass clazz, jfieldID fieldID, jshort value)
  • void SetStaticIntField(JNI_Env* env,jclass clazz, jfieldID fieldID, jint value)
  • void SetStaticLongField(JNI_Env* env,jclass clazz, jfieldID fieldID, jlong value)
  • void SetStaticFloatField(JNI_Env* env,jclass clazz, jfieldID fieldID, jfloat value)
  • void SetStaticDoubleField(JNI_Env* env,jclass clazz, jfieldID fieldID, jdouble value)

 

예제

 

이제 이들을 사용해 Hello 클래스의 필드들을 접근해 보기로 하자. Hello.java에 native메쏘드인 다음을 추가하고 컴파일 후, HelloImpl.c에서, 다음을 중심으로 코딩해 보자.public native void testFieldAccess()

 
정적 변수 접근

 

정적 필드인 iStaticIntVal 필드를 접근하여, 값을 읽어들인 후, 다시 2를 더해 값을 써 보자.jfieldID jFieldId;
jint iStaticIntVal;
jclass cls = (*env)->GetObjectClass(env, jobj);

jFieldId = (*env)->GetStaticFieldID(env,cls,"iStaticIntVal","I");
if(jFieldId == 0) {
                printf("Field iStaticIntVal not Found in Hello class\n");
                return;
}

//  값을 읽어들인 후,
iStaticIntVal = (*env)->GetStaticIntField(env,cls,jFieldId);

// 2를 더해, 다시 그 값을 쓴다.
(*env)->SetStaticIntField(env,cls,jFieldId,(iStaticIntVal+2));  

 
인스턴스 변수 접근

 

jint iVal;
jfieldID jFieldId;
jclass cls = (*env)->GetObjectClass(env, jobj);
jFieldId = (*env)->GetFieldID(env,cls,"intVal","I");
if(jFieldId == 0) {
                printf("Field intVal not Found in Hello class\n");
                return;
}
iVal = (*env)->GetIntField(env,jobj,jFieldId);
printf("iVal in C = %d\n",iVal);
(*env)->SetIntField(env,jobj,jFieldId,iVal);그런데, 실제로 int를 가지고 실험해 본 결과, C에서 값을 잘 넘겨받는 것까지는 좋은데, 다시 자바로 값을 써 줄 때, 인자가 잘 전달되지 않는 현상을 보였다. 좀더 생각해 볼 문제이다.

 
스트링 접근

 

스트링은 객체이므로 객체를 접근하는 방식을 통해 접근해야 한다. 우선 GetFieldID 함수의 인자로 "Ljava/lang/String;"을 주목하면, 객체의 접근 방식과 동일함을 알 수 있다. 여기에서 세미콜론(;)을 빠뜨리면, 인식하지 못하므로 주의하기 바란다.jstring jstr;
jfieldID jFieldId;
jclass cls = (*env)->GetObjectClass(env, jobj);

jFieldId = (*env)->GetFieldID(env,cls,"strVal","Ljava/lang/String;");
if(jFieldId == 0) {
                printf("Field strVal not Found in Hello class\n");
                return;
}jstr = (*env)->GetObjectField(env,jobj,jFieldId);
(*env)->SetStaticIntField(env,cls,jFieldId,(iStaticIntVal+2));  
str = (*env)->GetStringUTFChars(env, jstr, 0);
printf("Get String : %s\n",str);
새로운 스트링을 생성하여, 이것의 레퍼런스값을 str 필드에 할당하려면, 다음과 같이 한다.
jstr = (*env)->NewStringUTF(env, "123");
(*env)->SetObjectField(env, jobj, jFieldId, jstr);기타 객체를 호출하는 방법도 스트링과 거의 동일하다. (*env)->GetObjectField(env,jobj,jFieldId);를 통해, jobject타입의 객체를 얻어낸 후, 필요에 따라 이 객체의 메쏘드를 호출하면 된다. 

 

예외 사항

 

예외 사항 던지기

 

이제 예외 사항을 던지는 방법을 알아보자.  예외 사항들은 각각 클래스로 되어 있으므로, 이들의 클래스 정보를 얻어낸 후, 다음의 함수를 이용하면 된다. jint ThrowNew(JNI_Env* env, jclass clazz, const char *msg)
Hello.java에서 testFieldAccess가 java.io.IOException을 던지도록 수정해 보자.public native void testFieldAccess() throws java.io.IOException;javac Hello.java
javah -jni Hello 이제 새로이 HelloImpl.c에서, testFieldAccess의 끝에 다음을 추가해 보자.       jclass eCls;

       eCls = (*env)->FindClass(env, "java/io/IOException");
        if(eCls != 0) {
                (*env)->ThrowNew(env, eCls, "IOException from C");
        }

 

예외 사항 감지하기

 

JNI의 C코드에서, 자바의 메쏘드를 호출했을 때.예외 사항이 돌아올 수 있다. 이 때, 감지하는 데 사용되는 함수는 다음과 같다.jthrowable ExceptionOccurred(JNIEnv* env)이것은 jthrowable타입의 예외 사항 객체를 반환해 준다. 그 예외 사항에 정보를 출력하는 데 사용되는 함수도 제공된다.void ExceptionDescribe(JNI_Env* env) 그리고, 예외 사항이 처리된 후, 다시 예외 사항이 없는 것처럼 하려면, 다음과 같은 함수를 수행한다.void ExceptionClear(JNI_Env* env);이제 Hello.java에 새로운 메쏘드를 추가해 보자.public void returnException() throws java.io.IOException {
        throw new java.io.IOException("IOException from Java");
}이 메쏘드를 C에서 호출하면, 예외 사항이 그쪽으로 반환될 것이다. 이것을 처리하는 코드는 다음과 같다.       jmethodID jmId;
       jthrowable jexcp;

       jmId = (*env)->GetMethodID(env,cls,"returnException","()V");
        if(jmId == 0) {
                printf("Method returnException not found\n");
        }
        else {
                (*env)->CallVoidMethod(env,jobj,jmId);
                jexcp = (*env)->ExceptionOccurred(env);  
                if(jexcp) {
                        (*env)->ExceptionDescribe(env);   // 예외 사항 정보 출력
                        (*env)->ExceptionClear(env);
                }
        }

 

가비지 콜렉션

 

강제 레퍼런스 해제

 

원래 네이티브 메쏘드 내의 로컬 변수들이나 전역 변수들이 각각 지니고 있는 자바 객체에 대한 레퍼런스는 네이티브 메쏘드가 끝난 후에야 비로소 없어진다. 따라서, 네이티브 메쏘드가 오랜 시간동안 수행될 경우, 초반에만 실질적으로 사용될 뿐, 후반부에서는 쓰이지 않는 객체의 레퍼런스조차 메쏘드 전체가 수행이 끝날 때까지 남아있게 되는 셈이다. 이때 강제로 레퍼런스를 무효화시킬 수 있는 방법이 있다. 다음의 함수를 사용하면 된다.

  • void DeleteLocalRef(JNI_Env* env,jobject obj)   // 지역 변수
  • void DeleteGlobalRef(JNI_Env* env,jobject gref)  // 전역 변수

 

 

동기화

 

synchronized블록과 같은 동기화 블록을 C 코드내에서 지정해야 할 때가 있다. 바로 쓰레드에 의해 네이티브 메쏘드가 호출되었을 때, 이 메쏘드가 공유 변수들을 접근할 수 있기 때문이다. 그러한 용도로 사용되는 함수는 다음과 같다.

  • (*env)->MonitorEnter(JNI_Env* env,jobject obj);
  • (*env)->MonitorExit(JNI_Env* env, jobject obj);

 이 두 메쏘드 사이에 있는 코드들은 쓰레드들간에 동기화된다.

 
Posted by 삼스
JAVA2009. 5. 15. 15:54
Posted by 삼스
Android/App개발2009. 5. 12. 18:30
MediaPlayerDemo_Video.java 참조

           switch (Media) {
                case LOCAL_VIDEO:
                    /*
                     * TODO: Set the path variable to a local media file path.
                     */
                    //path = "sdcard/[PV] YUI - SUMMER SONG.avi"; // failed
                    //path = "sdcard/2008-01-11 02_01_00.3gp"; // ok
                    //path = "sdcard/FighterPilot_H264_720_480_30fps_4.1Mbps_AAC256Q100.mp4"; // fail
                    //path = "sdcard/leekunho_goal6.mp4"; // ok : frame skip
                    //path = "sdcard/Qpang.avi"; // fail
                    path = "sdcard/[M35_700]sample.avi"; // fail
                    if (path == "") {
                        // Tell the user to provide a media file URL.
                        Toast
                                .makeText(
                                        MediaPlayerDemo_Video.this,
                                        "Please edit MediaPlayerDemo_Video Activity, "
                                                + "and set the path variable to your media file path."
                                                + " Your media file must be stored on sdcard.",
                                        Toast.LENGTH_LONG).show();

                    }
                    break;
                case STREAM_VIDEO:

                    /*
                     * TODO: Set path variable to progressive streamable mp4 or
                     * 3gpp format URL. Http protocol should be used.
                     * Mediaplayer can only play "progressive streamable
                     * contents" which basically means: 1. the movie atom has to
                     * precede all the media data atoms. 2. The clip has to be
                     * reasonably interleaved.
                     *
                     */
                    path = "";
                    if (path == "") {
                        // Tell the user to provide a media file URL.
                        Toast
                                .makeText(
                                        MediaPlayerDemo_Video.this,
                                        "Please edit MediaPlayerDemo_Video Activity,"
                                                + " and set the path variable to your media file URL.",
                                        Toast.LENGTH_LONG).show();

                    }

                    break;


            }

            // Create a new media player and set the listeners
            mMediaPlayer = new MediaPlayer();
            mMediaPlayer.setDataSource(path);
            mMediaPlayer.setDisplay(holder);
            mMediaPlayer.prepare();
            mMediaPlayer.setOnBufferingUpdateListener(this);
            mMediaPlayer.setOnCompletionListener(this);
            mMediaPlayer.setOnPreparedListener(this);
            mMediaPlayer.setAudioStreamType(AudioManager.STREAM_MUSIC);

MediaPlayer
  -> setDataSource(path)  : URI로 content의 path가 전달 -> MediaPlayer service로부터 해당 path로 IMediaPlayer생성 -> 생성된 IMediaPlayer내부에 유지
  -> prepare()
      -> prepareAsync_I()
          -> setAudioStreamType() : 생성된 IMediaPlayer의 setAudioStreamType()임
                  in IMediaPlayer.cpp
 status_t setAudioStreamType(int type)
{
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
        data.writeInt32(type);
        remote()->transact(SET_AUDIO_STREAM_TYPE, data, &reply);
        return reply.readInt32();
}
          -> prepareAsync() : 생성된 IMediaPlayer의 prepareAsync()임.
                  in IMediaPlayer.cpp
    status_t prepareAsync()
    {
        Parcel data, reply;
        data.writeInterfaceToken(IMediaPlayer::getInterfaceDescriptor());
        remote()->transact(PREPARE_ASYNC, data, &reply);
        return reply.readInt32();
    }
     -> wait for prepare done
         if (mPrepareSync) {
            mSignal.wait(mLock);  // wait for prepare done
            mPrepareSync = false;
         }
  -> start()


Posted by 삼스
Android/App개발2009. 5. 12. 10:46
1. ARM GNU/Linux Target Platform 용 Cross-compiler 설치
아래의 사이트에 접속하여 Cross-compiler 를 설치한다.
http://www.codesourcery.com/gnu_toolchains/arm/download.html

2. 간단한 helloandroid.c 를 작성한다.

#include <stdio.h>
 
int main(int argc, char** argv)
{
        printf("Hello Android !n");
        return 0;
}
3. Cross Compile을 통해 ARM GNU/Linux 용 Application을 만든다.
> arm-none-linux-gnueabi-gcc -static helloandroid.c -o helloandroid
(주의: -static option을 필요 사용할 것.)
4. Android Device에 해당 애플리케이션을 Upload 한 후, 실행한다. > adb push helloandroid data/helloandroid
> adb shell
# chmod 755 data/helloandroid
# data/helloandroid
Hello Android ! <- 실행 결과
#
Posted by 삼스
Android/정리2009. 5. 11. 14:19
출처: http://www.kandroid.org/board/board.php?board=androidsource&command=body&no=4


안드로이드 전체 소스 코드 빌드 방법

 
먼저 안드로이드 소스를 빌드하기 위해선 리눅스 ubuntu 환경을 만드는 것이 바람직할 듯 합니다.
구글도 ubuntu 를 추천하고 있기 때문이고, 다른 package 사용하면 리눅스 초보자의 경우 작업이
힘들 수 있을 것으로 보입니다. 가급적 우분투를 사용하시기 바랍니다.
 
그럼 이제부터, 제가 build한 절차를 os 설치에서 부터 순차적으로 설명드리도록 하겠습니다.
최종적으로 모두 build하기 까지 꽤 많은 시간이 소비되니 충분한 시간을 가지고 빌드하시기 바랍니다.
 
1. 리눅스 Ubuntu 패키지 설치.
 
   전 참고로 ubuntu-8.04.1 desktop-i386을 사용하였음을 알려드립니다.
 
   - 먼저 아래의 url에서 우분투 iso 이미지를 얻으셔서 리눅스 설치 CD를 만듭니다.

      ftp://ftp.daum.net/ubuntu-releases/8.04.1/ubuntu-8.04.1-desktop-i386.iso
 
   - 그 이후 적당한 컴퓨터에 리눅스를 설치합니다.
 
2. 리눅스가 모두 설치되면 루트 passwd를 일단 설정합니다
 
    $ sudo passwd root
 
3. 만약 설치된 리눅스 Desktop에서 직접 작업을 원하시지 않는다면 ssh를 설치합니다
    저의 경우엔 ssh client를 사용하여 windows에서 접속하여 안드로이드 소스를 빌드하였습니다.
    ssh 설치 방법은 다음과 같습니다.
 
    $ sudo apt-get install ssh
 
4. 안드로이 설치 환경 준비
 
    - 기본적으로 다음과 같은 package를 인스톨하여야 합니다.
 
       $ sudo apt-get install flex bison gperf libsdl-dev libesd0-dev libwxgtk2.6-dev build-essential zip curl
       $ sudo apt-get install valgrind
 
    - 안드로이드는 Phython 2.4 이상이 요구됩니다.
       우분투 8.04.1에는 이미 Phython 2.5가 포함되어 있기 때문에 이 부분은 skip하셔도 됩니다.
 
    - JDK 5.0, Update 12 또는 그 이상이 요구됩니다.
       이를 위해선 다음과 같이 설치하시면 됩니다.
 
       $ sudo apt-get install sun-java6-jdk
 
    - Git 1.5.4 또는 그 이상 버전, 그리고 Repo가 요구됩니다.
 
       $ cd ~
       $ mkdir bin
 
       vi 로 ~/.bashrc 에 다음과 같이 환경변수를 추가합니다.
 
       $ vi ~/.bashrc
 
       export LANG=c
       export PATH=/home/<your_home>/bin:$PATH:.
       export JAVA_HOME=/usr/lib/jvm/java-6-sun-1.6.0.07
       export ANDROID_JAVA_HOME=$JAVA_HOME
 
       환경설정을 반영하기 위해 다시 로그인 하시던가 아니면 터미날을 종료했다 다시 실행하세요.
       csh의 경우엔 source ~/.cshrc를 하면 되는데..bash를 잘 모르겠네여.
 
       다음으로 git와 repo를 설치입니다.
 
       $ sudo apt-get install git-core gnupg      
 
       $ curl http://android.git.kernel.org/repo >~/bin/repo
       $ chmod a+x ~/bin/repo
 
       $ mkdir mydroid
       $ cd mydroid
 
       $ repo init -u git://android.git.kernel.org/platform/manifest.git
  
       여기까지 실행하시면, repo initialized in /home/<your_home>/mydroid 란 메시지가 나옵니다.
       이렇게 되면 환경설정은 이제 마무리 되었다고 보셔도 됩니다.
 
5. 안드로이드 소스 얻기
 
       아래과 같이 수행하면 안드로이드 전체 소스를 다운로드 하게 됩니다.
 
       $ repo sync

 
6. 안드로이드 빌드 하기
 
      $ make
 
      이 과정을 수행하는 동안 zlib.h error가 발생할 수 있습니다.
      이 경우에는 아래와 같이 zlibb1g-dev를 설치하시고 계속 make를 수행하면 됩니다.
 
      $ sudo apt-get install zlib1g-dev
      $ make
 
      이 과정을 수행하는 동안 -lncurses error가 발생할 수 있습니다.
      이 경우에는 아래와 같이 libncurses5-dev를 설치하시고 계속 make를 수행하면 됩니다.
 
       $ sudo apt-get install libncurses5-dev
       $ make
 
7. 결과 확인하기
 
       out 디렉토리에 build된 안드로이드 full package가 위치하게 됩니다.
 
       $ cd out
 
8. Kernel 별도로 빌드하기
 
     - msm
 
        $ cd ~/mydroid/kernel
        $ make msm_defconfig ARCH=arm
        $ make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-
 
     - goldfish (android 1.5에 merge되었으므로 이 커맨드는 동작하지 않음)
 
        $ cd ~/mydroid/kernel
        $ make goldfish_defconfig ARCH=arm
        $ make ARCH=arm CROSS_COMPILE=../prebuilt/linux-x86/toolchain/arm-eabi-4.2.1/bin/arm-eabi-
 


Posted by 삼스