Android/정리2009.05.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 삼스
Android/정리2009.05.06 15:59
Android Application을 개발하기 위해서는 다음 4가지 컴포넌트에 대해 알아야 한다.
 1. Activity
 2. Service
 3. Provider
 4. Receiver
 5. Manifest
이 외에 activity들의 스택인 task에 대해 알아야 한다.

1. Activity
 하나의 가상의 사용자 인터페이스에 대한 표현이다.
 - 화면에 나타나지 않을수 있고
 - 화면에 떠있을 수 있고
 - 어떤 값을 리턴할수 있고
 - 어떤 화면의 일부로 임베디드될수 있다.

 package com.android.myactivity;
import android.app.Activity;
import android.os.Bundle;
public class MyActivity extends Activity
{
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }
}

2. Service
 - 백그라운드로 수행되는 보이지 않는 클래스들이다.
 - Application process의 일부 또는 그 자체의 process로 동작할 수 있다.
 - 자신의 process또는 다른 process의 service에 bind할수 있다.
 - IDL로 정의된 remote-able interface로 한번 bind된 service와 통신이 가능하다.
 package com.android.myservice;
import android.app.Service;
public class MyService extends Service
{   
    public void onCreate() {
        Thread st = new Thread() {
            void run() { /* ... */ }
        };
        st.start();
    }
    public void onDestroy() {
        /*
        / ... *//
    }
}

3. Broadcast Receiver
 - Broadcast receiver는 broadcast announcement를 받아서 응답하는 일만 하는 다른 일은 아무것도 하지 않는 컴포넌트이다.
 - system에서 기본적으로 제공하는 많은 broadcast메세지들이 있다(예, 타임존의 변경, 배터리의 부족, 사진이 캡쳐되었는지, 사용자가 언어를 바꾸었는지등 ...)
 - Application에서 broadcast를 정의하여 발생시킬수도 있다(예, 어떤 데이터가 모두 다운되었는지 다른 app에 알리고자 할때)
 - 하나의 Application은 여러개의 broadcast receiver를 가질수 있다. receiver는 BroadcastReceiver base class를 파생시켜 작성한다.
 - Broadcast receiver는 UI를 가지고 있지 않으며 수신한 정보에 대한 응답으로 특정 activity를 시작한다거나 NotificationManager로 사용자에게 통지를 준다.
 - Notification은 다양한 방법으로 사용자에게 통지를 한다 - flashing the backlight, device떨림, 소리재생 등등...
 - 일반적으로 상태바에 아이콘으로 표시되며 사용자가 열어볼수 있게 한다.
 package org.kandroid.helloandroid;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MyReceiver extends BroadcastReceiver {
    @Override
    public void onReceive(Context arg0, Intent arg1) {
    }
}

4. Content provider
 - Application간에 특정 데이터를 공유할 수 있도록 해줌.
 - 획일화된 API를 제공
 - Content는 URI와 MIME type으로 표현됨.
 package org.kandroid.helloandroid;
import android.content.*;
import android.database.Cursor;
import android.net.Uri;
public class MyProvider extends ContentProvider {
    @Override public int delete(Uri arg0, String arg1, String[] arg2)
                            { return 0; }
    @Override public String getType(Uri arg0) {return null;}
    @Override public Uri insert(Uri arg0, ContentValues arg1)
                            { return null;}
    @Override public boolean onCreate() {return false;}
    @Override public Cursor query(Uri arg0, String[] arg1, String arg2,
                            String[] arg3, String arg4) {return null;}
                                        3
    @Override public int update(Uri arg0, ContentValues arg1, String arg2,
                            String[] arg3) {return 0;}
}


5. Component의 활성화
  - Content provider : ContentResolver에 의해 타켓팅될 때 활성화된다.
  - 나머지 3가지 component(Activity, Service, Receiver)는 intent로 불리는 비동기적인 메세지에 의해 활성화된다.
  - Activity, Service를 위한 Intent는 Action과 URI정보가 필요하다.
  - Broadcast receiver를 위한 intent는 action정보가 필요하다.

각 component type별로 활성화하는 방법이 있다.
  - Activity : Content.startActivity() 또는 Activity.startActivityForResult()에 intent object를 넘겨서 activity를 활성화한다.
  - Service : Context.startService()에 intent object를 넘겨서 service를 활성화한다. Android는 Service의 onStart()메소드를 호출하고 intent object를 넘긴다.
  - Broadcast Receiver : Context.sendBroadcast(), Context.sendOrderedBroadcast(), Context.sendStickyBroadcast()에 intent object를 넘겨서 broadcast를 활성화한다.

6. Component의 비활성화
 - Content provider : ContentResolver의 request에 대하여 responding중에만 활성화된다.
 - Broadcast receiver : Broadcast message에 대한 responding중에만 활성화 된다.
 - 따라서 provider와 receiver는 명시적으로 component를 비활성화 할 필요가 없다.
 - Activity, Service : idle time에도 무언가 process가 이루어지는 컴포넌트이다.
 - Activity : finish()메소드로 비활성화한다. 특정 activity에서 다른 activity를 죽이려면 finishActivity()를 호출한다.
 - Service : stopService() 또는 Context.stopService()로 비활성화한다.

7. Manifest file
 - Android가 application component를 시작하기 전에 그 component가 존재하는지에 대해 먼저 알아야 한다. 그러므로 application component들에 대한 정보를 manifest 파일에 선언하고 Android package(.Apk) file에 applicaiton code, files, resources와 함께 묶음으로 담겨 있다.
 - XML file형식
 - 모든 application에 AndroidManifest.xml로 이름이 고정되어 있슴
 - component에 대한 기술 외에 library, permission등에 대한 정보도 선언됨.
 <manifest>
    <instrumentation>
    <uses-sdk>
    <uses-permission>
      uses permission
    <permission>
    <permission-group>
    <permission-tree>
    <application>
       pp
          <uses-library>
          <activity>
          <activity-alias>
          <provider>
           p
                      <grant-uri-permission>
          <receiver>
          <service>
               <intent-filter>
                      <action>
                      <category>
                      <data>
               <meta-data>




신고
Posted by 삼스
Android/정리2009.05.06 14:01
빌드하기

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(1.5에서 merge됨, 따라서 msm_defconfig로 변경)
$ 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-


테스트하기
1. 먼저 mydroid 의 out directory에서 아래의 세가지 image를
android sdk가 설치된 desktop에 download를 합니다.
~mydroid/out/target/product/generic/ramdisk.img
~mydroid/out/target/product/generic/system.img
~mydroid/out/target/product/generic/userdata.img
2. android sdk 1.0 이 설치된 desktop의 아래의 directory에서 ramdisk.img, system.img, use
rdata.img를 임시로 다른 곳으로 저장합니다.
android-sdk-windows-1.0_r1/tools/lib/images
3. 위에서 다운로운한 세가지 img 파일을 위의 디렉토리에 위치지운 후,
android-sdk-windows-1.0_r1/tools/emulator.exe를 실행합니다.
4. 만약 emualor가 정상적으로 실행되고, 내부 app. 들이 정상적으로 작동한다면,
안드로이드 source는 정상적으로 build되었다고 볼 수 있습니다.

신고
Posted by 삼스
Android/정리2009.05.06 13:58


1. Bootloader : 기본적인 hw initialize
2. Load linux
3. Start kernel - /init/main.c
4. Android initialization process - /etc/init.rc
   -> Start android services: Colsole, adbd, service manager, debuggerd, mountd, rild, zygote, mediaserver, installd, flash_recovery

아래는 init.rc의 process를 도식화한것이다.

init : init.rc를 해석하여 수행하고 초기화한다.
       /dev노드 아래에 %hardware%.rc를 참조하여 디바이스노드를 생성해낸다.
console : shell을 시작한다.
service manager : binder IPC service manager를 시작한다.
mountd : 모든 filesystem을 마운트한다.
debuggerd : debug system을 시작한다.
rild : Radio Interface Layer daemon을 시작한다.
zygote : Android Java VM runtime을 시작하고 system server를 시작한다. 가장 중요한 프로세스이다.
media server : Audio/Surface flinger, MediaPlayerService, Camera service를 시작한다.
Installd : install package daemon을 시작한다.
      
  • 모든 안드로이드 어플리케이션은 zygote process에 의해 fork된다.
  • system_servier는 fork된 zygote에 의해 최초로 적재되는 특별한 프로세스이며 Core service들을 시작한다.
    • ActivityManager, WindowsManager, PackageManager, ...
  • 다른 안드로이드프로세스는 ActivityManagerService에 의해 생성된다.

더 자세한 정보를 원한다면 /frameworks/base/services/java/com/android/server/am/ActivityManagerService.java 와 /frameworks/base/core/java/android/os/Process.java

ActivityManagerService.systemReady에서 persistent application을 부팅시 시작하도록 되어 있다. 따라서 AndroidManifest.xml에서 아래와 같이 정의된 Application은 부팅시 실행된다.

 <application android:name="PhoneApp"
    android:persistent="true"
    android:label="@string/dialerIconLabel"
    android:icon="@drawable/ic_launcher_phone">

intent.CATEGORY_HOME으로 설정된 component가 적재된다.
intent.ACTION_BOOT_COMPLETED로 설정된 component가 부팅 완료후 적재된다.
receiver component중 android.enabled와 android.exported가 false이면 ACTION_BOOT_COMPLETED가 set되어 있더라도 적재되지 않는다.
<receiver android:name=".service.BootReceiver" android:enabled="false"
<receiver android:name=".DownloadReceiver" android:exported="false"> 




신고
Posted by 삼스
Android/정리2009.05.06 11:40
1. 안드로이드란?
 안드로이드는 모바일디바이스들을 위한 SW Stack으로써, OS, Middleware, Key application을 포함하고 있다.

 안드로이드SDK는 Java language를 사용하여 안드로이드플랫폼상의 application 개발에 필요한 API들과 도구들을 제공한다.

2. Features
 애플리케이션 프레임워크 : 컴포넌트의 재사용과 대체(replacement)를 가능하게 함.
 달빅(Dalvik) 가상머신 : 모바일 디바이스에 최적화됨.
 통합(Integrated) 브라우저 : 오픈 소스 Webkit 엔진 기반임.
 최적화된 그래픽 : 구글이 만든 2D 그래픽 라이브러리를 사용함.
 OpenGL ES 1.0 스펙에 기반한 3D 그래픽을 사용함 (하드웨어 가속은 선택사항임)
 SQLite : 정형화된 데이터 저장공간을 위한 것임.
 미디어 지원 : 일반적인 오디오, 비디오, 그리고 정지(still) 이미지 포맷들을 지원
                    (MPEG4, H.264, MP3, AAC, AMR, JPG, PNG, GIF)
 GSM과 CDMA 텔레포니(Telephony) (하드웨어 의존적)
 블루투스, EDGE, 3G, WiFi (하드웨어 의존적)
 카메라, GPS, 나침반, 그리고 가속도계 (하드웨어 의존적)
 풍부한 개발 환경 : 디바이스 에뮬레이터, 디버깅 도구, 메모리 및 성능 프로파일링 그리고 Eclipse
 IDE를 위한 플러그인을 포함함 

3. Architecture

3.1 Applications
 안드로이드가 기본적으로 제공하는 Java Applications

3.2 Application Framework
 자바기반의 프레임웍으로 대부분 native C/C++코드로 작성되어 JNI로 자바와 인터페이싱되어 있다.
 코어시스템서비스와 하드웨어 서비스로 구성되어 있다.
 Core System Services
  - Activity Manager
  - Package Manager
  - Resource Manager
  - Content Provierss
  - Window Manager
  - View System
 Hardware services
  - low-level access to hw device
  - Location Manager
  - Telephony Manager
  - Blutooth service
  - Wifi service
  - USB service
  - Sensor service

3.3 Libraries
 안드로이드가 내장하고 있는 기본적인 라이브러리는 Bionic Libc, Function Library, Navive Service, Hardware Abstraction Library로 구성된다.
 - Bionic Libc : 임베디드에 최적화된 구글에서 직접 구현한 libc이다. 이를 직접 구현한 이유는 GPL를 피하여 일부 라이선스 프리를 보장하기 위한것과, 개별프로세스마다 포함되어야 하고 빨라야 하기 때문이다. 따라서 가볍고 빠른 libc를 목표로 작성된 Libc이다.
 - Function Library : Webkit, OpenCORE, SQLite들이 있다.
 - Native server : Surface flinger, Audio flinger가 있다. 이는 시스템 전반에 걸친 화면과 소리를 담당하는 서버라고 보면된다.
 - Hardware Abstraction Layer : OS로 사용하고 있는 리눅스운영체제가 다수의 드라이버개발모델을 가지고 있어 이를 통합하고자 하는 의도가 보이는 대목이다. 이를 이용하여 안드로이드플랫폼을 하드웨어인터페이스로부터 분리할수 있다. GPL을 피할수 있으며 안드로이드가 별도의 하드웨어 요구사항을 정의하고 있다.
 - 안드로이드 런타임 라이브러리 : Dalvik가상머신과 Core라이브러리들로 구성된다.

3.4 안드로이드 런타임 라이브러리
 - Dalvik 가상머신 : 안드로이들에서는 자바 가상머신을 사용하지 않는다. 이유는 여러가지가 있는데 속도와 안드로이드 프레임웤구조때문이다. 달빅가상머신은 프로세스별로 생성되어 어플리케이션간의 청정영역(clean-room)을 제공한다.
    - Register 기반의 가상머신 (no JIT, interpreter-only)
    - Optimized for low memory requirements
    - Designed to allow multiple VM instances to run at one
    - Relying on underlying OS for process isolation,
       memory management and threading support
    - Executes Dalvik Executables (DEX) files which are zipped into
an Android Package (APK)
 - Core라이브러리 : 강력하지만 단순하고 익숙한 개발 플랫폼을 제공하는 자바언어를 위한 Core API들을 포함하고 있다. Application개발시 필요한 거의 모든 자바Core API들이 있다고 보면된다. Data structure, Utility, File access, Network access, graphic, ...
    - Bundled in android.jar
    - Android platform library: android.*.
       XML Parser implementations included (DOM, SAX, XMLPullParser)
    - Apache Harmony (Standrard Java Library implementation)
    - Several popular Open Source projects available out-of-the-box.
        Apache Commons (HttpClients 2/4, Codec), BouncyCastle JCE providers, SQLite, JUnit 3.8.x
    - GData APIs partly included as wireless version(com.google.wireless.gdata)

4. 리눅스 커널
 - 리눅스커널을 기반으로 하고 있으나 리눅스는 아니다.
    X-Windows내장하지 않음, Glibc지원하지 않음, 표준리눅스유틸리티 전체를 포함하지 않는다.
 - 리눅스커널 버전 2.6.23, 2.6.24, 2.6.25, 2.6.27를 사용해왔으며 안드로이드지원을 위해 패치를 포함한다.
 - 리눅스를 사용하는 이유
    - 메모리 및 프로세스관리
    - Permission기반의 보안모델
    - 검증된 드라이버모델
    - 공유라이브러리 지원
    - 오픈소스기반 등의 장점을 이용함.
 - 확장된 리눅스커널영역
    - Alarm, Ashmem, Binder, Power Management, Low memory killer, Kernel debugger, logger
 - http://git.android.com에서 배포
신고
Posted by 삼스

티스토리 툴바