오픈 소스 삼성에 있는 방법을 그대로 했는데, 갤탭에 이미지를 굽는 것만 하고 그 이상이 되지 않는다.  결국 컴파일만 한 것 같다.

먼가 더 있는 것 같은데.. 찾기 어렵다.  하여튼 실패기도 넣는 것도 좋을 것 같아서 적어본다.

 

--------------------------------

 

기존 정보는 오픈소스 삼성 싸이트(https://opensource.samsung.com)에 공개되어 있다.

갤럭시탭 소스는 두가지 버전이 있다. 해외버전인 gt-p1000과 국내버전인 SHW-M180 버전이 있다. 나는 국내버전의 LGT 용만 가지고 테스트하려고 한다.


https://opensource.samsung.com/reception/receptionSub.do?method=search&searchValue=gt-p1000
https://opensource.samsung.com/reception/receptionSub.do?method=search&searchValue=m180

 

<운영체제 확인>

$ dpkg -s libc6  | grep Archite
Architecture: i386

이러면  32 비트, amd64가 나오면 64비트이다.

진저브레드 이상 컴파일하려면 64비트에서 돌리는 것이 편하다.

다운로드 링크 –> http://www.ubuntu.com/download/ubuntu/download

 

* 참고 32비트에서 컴파일 하려면. 좀 귀찮은 작업을 해야 한다.

아래와 같은 에러 문구가 나와서 여기저기 손봐야 한다.

build/core/main.mk:76: ************************************************************
build/core/main.mk:77: You are attempting to build on a 32-bit system.
build/core/main.mk:78: Only 64-bit build environments are supported beyond froyo/2.2.
build/core/main.mk:79: ************************************************************
build/core/main.mk:80: *** stop.  Stop.

1. 32비트 운영체제일 때는  ./build/core/main.mk 파일을 아래와 같이 주석을 추가한다. .

73 ifeq ($(BUILD_OS),linux)
74 build_arch := $(shell uname -m)
75 ifneq (64,$(findstring 64,$(build_arch)))
76 $(warning ************************************************************)
77 $(warning You are attempting to build on a 32-bit system.)
78 $(warning Only 64-bit build environments are supported beyond froyo/2.2.)
79 $(warning ************************************************************)
80 $(error stop)
81 endif
82 endif

=>

73 #ifeq ($(BUILD_OS),linux)
74 #build_arch := $(shell uname -m)
75 #ifneq (64,$(findstring 64,$(build_arch)))
76 #$(warning ************************************************************)
77 #$(warning You are attempting to build on a 32-bit system.)
78 #$(warning Only 64-bit build environments are supported beyond froyo/2.2.)
79 #$(warning ************************************************************)
80 #$(error stop)
81 #endif
82 #endif

 

2. 다음 mk 파일에서 m64->m32로 변경한다.

./external/clearsilver/cgi/Android.mk
./external/clearsilver/java-jni/Android.mk
./external/clearsilver/util/Android.mk
./external/clearsilver/cs/Android.mk

LOCAL_CFLAGS += -m64
LOCAL_LDFLAGS += –m64

->

LOCAL_CFLAGS += -m32
LOCAL_LDFLAGS += –m32

 

 

 

<갤탭 소스 다운로드>

LGT 의 갤럭시탭 소스를 다운받는다.

https://opensource.samsung.com/reception/receptionSub.do?method=search&searchValue=m180

image

 

최신버전은 update3을 다운받는다. 다운받아서 내용을 보면, 달랑 kernel과 readme.txt 파일밖에 없다.

image

 

readme.txt 파일에 따르면, update2.zip 파일에 있는 플랫폼 파일을 다운받으라고 한다. 다운받고 커널 파일과 플랫폼 파일을 합친다.

<NOTICE>

The Platform opensource code is the same as that of TF09 version.

Get TF09 version opensource code - filename: SHW-M180L_Opensource_Update2.zip
(download site: opensource.samsung.com)
Unzip it, then you will see the file SHW-M180L_Platform_Gingerbread.tar.gz

 

파일을 모아본다.

image

 

tar.gz으로 묶인 플랫폼 소스의 readme.txt 파일을 보면, build 설명 방법이 잘 나와 있다.

How to build


1. Get android open source.
    : version info - Android gingerbread 2.3.3
    ( Download site : http://source.android.com )

2. Overwrite modules that you want to build.
- \external\iproute2 : Write "ip \" into "build\core\user_tags.mk" so that add this module.
- \external\webkit  : Delete this source tree at Android gingerbread and then copy & execute "clean build".
- \external\alsa-lib : Write "libasound \" into "build\core\user_tags.mk" so that add this module.

3. Add the following lines at the end of build/target/board/generic/BoardConfig.mk

BOARD_HAVE_BLUETOOTH := true
BOARD_HAVE_BLUETOOTH_BCM_BTLA := true
BT_ALT_STACK := true
BRCM_BT_USE_BTL_IF := true
BRCM_BTL_INCLUDE_A2DP := true
BOARD_USES_ALSA_AUDIO := true

4. make
- ./build.sh user

 

ubuntu 11.10 amd64 비트를 기반으로 설명한다.


<소스 다운로드>

* 참고자료
http://source.android.com/source/downloading.html

* jdk 6 설치

$ sudo add-apt-repository "deb http://archive.canonical.com/ lucid partner"
$ sudo apt-get update
$ sudo apt-get install sun-java6-jdk

 

* 필요 패키지 설치

$ sudo apt-get install git-core gnupg flex bison gperf build-essential  zip curl zlib1g-dev libc6-dev lib32ncurses5-dev ia32-libs x11proto-core-dev libx11-dev  lib32z-dev libgl1-mesa-dev g++-multilib mingw32 tofrodos python-markdown libxml2-utils xsltproc lib32readline-gplv2-dev

(원래 문서에서는 lib32z-dev를 설치하라고 되어 있지만, Ubuntu 11.10 64비트에서는 해당 모듈을 설치할 수 없다. 따라서 대안인 lib32readline-gplv2-dev을 설치한다.)

$ sudo apt-get install libx11-dev:i386

 

* repo 설치

$ mkdir ~/bin
$ PATH=~/bin:$PATH
$ curl https://dl-ssl.google.com/dl/googlesource/git-repo/repo > ~/bin/repo
$ chmod a+x ~/bin/repo

 

* 안드로이드 2.3.3 소스 다운로드
$ mkdir android-2.3.3-galtab
$ cd android-2.3.3-galtab
$ repo init -u https://android.googlesource.com/platform/manifest -b android-2.3.3_r1
$ repo sync

 

* LGT 삼성 갤탭 소스 복사
vmware player에서 소스가 있는 곳을 공유(/mnt/hgfs/vmware-share)해서 복사한다.


$ tar zxvf /mnt/hgfs/vmware-share/SHW-M180L_Platform_Gingerbread.tar.gz –C .

$ tar zxvf /mnt/hgfs/vmware-share/SHW-M180L_Kernel_Gingerbread.tar.gz –C .

$ mv Platform/ android-2.3.3-galtab-platform

$ mv Kernel/ android-2.3.3-galtab-kernel

 


<커널 소스 빌드>

* 툴체인 (Tool Chain) 설치

$ cd /usr/local
$ wget http://www.codesourcery.com/public/gnu_toolchain/arm-none-linux-gnueabi/arm-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2
$ tar xvf arm-2009q3-67-arm-none-linux-gnueabi-i686-pc-linux-gnu.tar.bz2

* build.sh 파일 수정

$ cd ~/android-2.3.3-galtab-kernel
$ vi build_kernel.sh

1. TOOLCHAIN과 TOOLCHAIN_PREFIX 변수를 수정한다.

TOOLCHAIN=~/opt/toolchains/arm-2009q3/bin/
TOOLCHAIN_PREFIX=arm-none-eabi-
=>
TOOLCHAIN=/usr/local/arm-2009q3/bin/  
TOOLCHAIN_PREFIX=arm-none-linux-gnueabi-        

2. 28번째 줄에 있는 ^M은 삭제한다. (빌드시 에러처럼 보일 수 있어서.)

output 디렉토리를 확인한다.

ANDROID_OUT_DIR=`pwd`/Android/out/target/product/SHW-M180L

* Kernel 빌드

$ cd ~/android-2.3.3-galtab-Kernel/Kernel

$ make menuconfig

General setup->Initramfs source file->exit->exit->Yes 하고 설정을 save 한다.

image

(initramfs 적용방법과 적용하지 않는 방법 둘 다 써도 문제임)

$ cd ..

$ ./build_kernel.sh

(sh 내부에 ARCH=arm, tool chain 확인)

빌드 결과는 zImage과 커널 모듈파일이다. 커널 이미지가 제대로 있는지 확인한다.

$ ls ~/android-2.3.3-galtab-kernel/Kernel/arch/arm/boot/zImage

커널 모듈 파일이 제대로 있는지 확인한다.

$ ls -al ~/android-2.3.3-galtab-kernel/Kernel/drivers/*/*

 

* 나중에 이 파일을 이용하면 성능 효과를 높일 수도 있을 수 있을 것 같아서 우선 기억해둔다.

arch/arm/configs/p1_kor_M180L_defconfig 

* Clean 하기

$ ./build_kernel.sh Clean

 

<커널 파일을 tar로 만들기>

$ cd ~

$ tar cvf SHW-M180L-kernel.tar android-2.3.3-galtab-kernel/Kernel/arch/arm/boot/zImage
android-2.3.3-galtab-kernel/Kernel/arch/arm/boot/zImage

기존 이미지를 풀어서 새로 컴파일한 zImage 파일만 replace  해 본다.

image

 

그리고, 윈도우에서 7zip으로 tar 파일로 만들면 upload failed 가 뜬다. ubuntu에서 tar로 묶는다.

image

tar로 묶은 후 Odin으로 굽는다.

image

image

 

갤탭 로고는 나오는데, 무한 부팅되면서 이미지 upload 실패했다.

zImage 크기가 순정과 컴파일 이후의 것이 800kb가 차이날 정도로 다르다. 먼가 더 있는 것 같은데. 잘 모르겠다.

 

 

<안드로이드 소스 빌드>

$ cd ~/android-2.3.3-galtab

ubuntu 11.10에서 에러가 발생할 수 있으니. 일부 make 파일을 수정해야 한다.

$ vi frameworks/base/libs/utils/Android.mk

LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS)

=>

LOCAL_CFLAGS += -DLIBUTILS_NATIVE=1 $(TOOL_CFLAGS) -fpermissive

-fpermissive에 대한 설명은 gcc 4.1 이슈로서, 자세한 내용은 링크(http://nineye.com/blog/archives/543)를 참조한다.

$ vi build/core/combo/HOST_linux-x86.mk

HOST_GLOBAL_CFLAGS += -D_FORTIFY_SOURCE=0   
HOST_GLOBAL_CFLAGS += -U_FORTIFY_SOURCE -D_FORTIFY_SOURCE=0

FORTIFY_SOURCE에 대한 설명은 링크(http://studyfoss.egloos.com/5280245)를 참조한다.


$ source build/envsetup.sh

$ lunch full-eng

============================================
PLATFORM_VERSION_CODENAME=REL
PLATFORM_VERSION=2.3.3
TARGET_PRODUCT=full
TARGET_BUILD_VARIANT=eng
TARGET_SIMULATOR=false
TARGET_BUILD_TYPE=release
TARGET_BUILD_APPS=
TARGET_ARCH=arm
HOST_ARCH=x86
HOST_OS=linux
HOST_BUILD_TYPE=release
BUILD_ID=GRI40
============================================

$ make

….
Target system fs image: out/target/product/generic/obj/PACKAGING/systemimage_intermediates/system.img
Install system fs image: out/target/product/generic/system.img
Target ram disk: out/target/product/generic/ramdisk.img
Target userdata fs image: out/target/product/generic/userdata.img
Installed file list: out/target/product/generic/installed-files.txt

 

 

<플랫폼 소스 수정 및 빌드>

$ cd ~/android-2.3.3-galtab-platform/

$ vi build/target/board/generic/BoardConfig.mk

다음을 추가한다.
BOARD_HAVE_BLUETOOTH := true
BOARD_HAVE_BLUETOOTH_BCM_BTLA := true
BT_ALT_STACK := true
BRCM_BT_USE_BTL_IF := true
BRCM_BTL_INCLUDE_A2DP := true
BOARD_USES_ALSA_AUDIO := true

$ vi build.sh

안드로이드 컴파일했던 디렉토리를 PLATFORMPATH로 수정한다.

export PLATFORMPATH="/home/kimyonghwan/android-2.3.3-galtab"

$ cd ~/android-2.3.3-galtab-platform/

$ ./build.sh user

Posted by My Story '김용환'
출 처: http://knight76.tistory.com/


Ubuntu에서 deb 설치

 


      # sudo dpkg -i *.deb


명령들처럼 쉬우면서도 까먹는 명령어 하나입니다.
Ubuntu
에서는 Windows 시리즈처럼 특정 폴더에 프로그램을 설치하지 않아도 됩니다. 물론 Windows C:\Program Files 폴더를 고집하지 않아도 설치가 가능은 합니다만, 그렇게 사용해보니 가끔 헷갈리기도 하고 시스템도 그다지 안정적이지 못하다는 느낌을 갖게 됩니다.

리눅스에서는 대부분의 어플리케이션이 Free Software 배포되고, 리눅스의 종류에 따라 서로 다른 명령어를 사용하지만 설치 또한 자동 설치를 지원합니다. 외의 프로그램들은 각자 다운받아서 스스로 설치를 하게끔 되어 있습니다.
확장자가 deb 파일은 원래 Debian 리눅스에서의 설치파일입니다. (Ubuntu 원래 Debian 리눅스에서 파생되었기 때문에, 많은 부분에서 서로 닮아있습니다. 따라서 별다른 변환 절차 없이 바로 설치가 가능합니다.) 이런 deb 설치 파일의 대표적 종류에는 Opera 브라우저가 있습니다. Opera 브라우저의 설치는 관련 게시물 참조하세요.


sudo dpkg -i *deb


위의 명령어를 실행하면 프로그램 내에서 설정된 디렉토리를 생성하고 스스로 설치를 시작하게 됩니다.

이와 유사한 설치 파일의 종류에는 rpm 파일이 있습니다. 이는 Redhat 리눅스에서 사용되는 형식입니다. Ubuntu에서는 이를 변환시켜서 deb 파일로 만든 후에 위의 방식을 적용하여 설치할 있습니다. 자세한 내용은 다음에 설명드리겠습니다.

우분투 64비트에서 안드로이드 AVD가 돌아가지 않을때.

  에러명: Failed to get the adb version: Cannot run program "/home/hskim/devtools/android/android-sdk-linux_x86-1.6_r1/tools/adb": java.io.IOException: error=2, No such file or directory

  문제: 안드로이드 SDK는 32비트라서 64비트 윈도우에서는 그 라이브러리를 찾을 수 없어서 발생
  해결:
   다음 링크에서 getlibs라는 프로그램을 받는다.
    http://frozenfox.freehostia.com/cappy/getlibs-all.deb
   받은 파일을 설치한다.
   터미널을 열고,
   android-sdk-linux_x86/platform-tools로 이동
   다음 명령을 수행한다.
    $ getlibs aapt

   설치 프로그램: ia32-libs lib32asound2 lib32gcc1 lib32ncurses5 lib32stdc++6 lib32z1 libc6-i386
   업그레이드 프로그램 : libc6 libc6-dev

  eclipse를 다시 실행하면 된다,
  (원문: http://blog.jayway.com/2009/10/21/getting-android-sdk-working-on-ubuntu-64/)

 해당 로그

01-01 02:41:44.054  1188  1188 D installd: DexInv: --- END '/system/app/AngryBirds_samsungMID.apk' (success) ---

01-01 02:41:44.054  1292  1306 D PackageManager: scanPackage : /system/app/test.apk

01-01 02:41:44.062  1292  1306 W ResourceType: Failure getting entry for 0x7f070000 (t=6 e=0) in package 0 (error -75)

01-01 02:41:44.062  1292  1306 W ResourceType: Failure getting entry for 0x7f020005 (t=1 e=5) in package 0 (error -75)

01-01 02:41:44.062  1292  1306 W ResourceType: Failure getting entry for 0x7f070000 (t=6 e=0) in package 0 (error -75)

01-01 02:41:44.062  1292  1306 I PackageManager: /system/app/test.apk changed; collecting certs

01-01 02:41:44.124  1188  1188 D installd: DexInv: --- BEGIN '/system/app/test.apk' ---

01-01 02:41:44.140  1504  1504 D dalvikvm: creating instr width table

01-01 02:41:44.156  1504  1504 D dalvikvm: DexOpt: load 4ms, verify+opt 2ms

01-01 02:41:44.218  1188  1188 D installd: DexInv: --- END '/system/app/test.apk' (success) ---

01-01 02:41:44.218  1292  1306 D PackageManager: scanPackage : /system/app/test2.apk

01-01 02:41:44.242  1292  1306 W ResourceType: Failure getting entry for 0x7f020002 (t=1 e=2) in package 0 (error -75)

01-01 02:41:44.249  1292  1306 W ResourceType: Failure getting entry for 0x7f020097 (t=1 e=151) in package 0 (error -75)

01-01 02:41:44.249  1292  1306 I PackageManager: /system/app/test2.apk changed; collecting certs

01-01 02:41:44.398  1292  1294 D dalvikvm: GC_CONCURRENT freed 777K, 53% free 6511K/13767K, external 1596K/2108K, paused 2ms+14ms

01-01 02:41:44.679  1292  1294 D dalvikvm: GC_CONCURRENT freed 1831K, 57% free 6027K/13767K, external 1596K/2108K, paused 2ms+5ms

01-01 02:41:44.749  1188  1188 D installd: DexInv: --- BEGIN '/system/app/test2.apk' ---

01-01 02:41:44.789  1505  1505 D dalvikvm: creating instr width table

 

위의 빨간색 부분을 보면 Resource Type을 불러올 때 Error가 발생하는 것을 확인할 수 있습니다.

해당 문제에서 발생하는 원인은 Resource Type을 불러올 때, 해당 리소스가 존재하지 않아서 발생되는 문제입니다.

위의 로그를 분석해 보면 다음과 같습니다.

01-01 02:41:44.242  1292  1306 W ResourceType: Failure getting entry for 0x7f020002 (t=1 e=2) in package 0 (error -75)

0x7f020002 Resource Index를 뜻합니다. 여기서 보면 0x7f는 무시하시고 020002가 보이는데 이것은 리소스의 ID값입니다.

ID값을 확인하기 위해서는 다음의 폴더로 이동하여 파일을 열어보면, 위에서 호출한 ID값이 어떤 Resource인지 알 수 있습니다.


 

Android\out\target\common\obj\APPS\test2_intermediates\public_resources.xml

<!-- Declared at res/drawable-small-ldpi/test2_trayicon.png:0 -->

<!-- Declared at res/drawable-small-land-ldpi/test2_trayicon.png:0 -->

<!-- Declared at res/drawable-normal-mdpi/test2_trayicon.png:0 -->

<!-- Declared at res/drawable-hdpi/test2_trayicon.png:0 -->

<!-- Declared at res/drawable-normal-hdpi/test2_trayicon.png:0 -->

<!-- Declared at res/drawable-large-xhdpi/test2_trayicon.png:0 -->

<public type="drawable" name="test2_trayicon" id="0x7f020002" />

 

이 파일이 생성되는 순서는 Resource 파일의 일정 규칙에 의해서 ID값이 생성이 됩니다.

따라서 새로운 리소스 파일이 추가되지 않는 이상은 해당 ID값은 변동되지 않습니다.

 

위의 파일을 열어보면 해당 Resource ID값을 확인할 수 있습니다.

 

그러면 왜 ResourceType에서 해당 파일이 존재하는데도 왜 못찾을까요. 그 문제에 대한 답은 다음과 같습니다.

 

처음에 Package정보를 불러올 때,  Manifest File에서 불러오게 됩니다.

이때, Menifest File에서 정의되어 있는 String이라던가 Drable의 이미지 파일들 같은 리소스가 존재할 경우, 해당 해상도 폴더에 존재하지 않게 되면, 위와 같은 현상이 발생되는 것입니다.

예를 들면, ABC라는 Project에서 res 폴더에 다음과 같이 정의 되어 있을 경우, 위와 같은 에러가 발생되는 것입니다.

Res

res/drawable-small-ldpi/test2_trayicon.png

res/drawable-small-land-ldpi/ test2_trayicon.png

res/drawable-normal-mdpi/ test2_trayicon.png

res/drawable-normal-hdpi/ test2_trayicon.png

res/drawable-large-xhdpi/ test2_trayicon.png

res/values/strings.xml:4

res/values-normal-hdpi/strings.xml:4

res/values-normal-land-hdpi/strings.xml:4

 

위의 문제를 해결하기 위해서는 다음과 같이 사용하는 해상도와 관련된 폴더를 생성하여, Manifest에서 사용하는 파일들을 추가해 주시면 됩니다.

res/drawable-hdpi/ test2_trayicon.png

res/values-hdpi/strings.xml:4

위의 해당 파일을 추가.

 

그러면 다시 컴파일하고 확인하시면 아시겠지만, 해당 로그가 사라지는 것을 확인 할 수 있습니다.

이는 해당 리소스를 불러왔기 때문에, 로그가 찍히지 않는 것입니다.

안드로이드 웹뷰를 이용하여 Epub나 자체 html viewer를 꾸밀시, 페이지내(뷰어) 텍스트 선택이 필요한 경우가 있습니다.
아래 루틴을 사용하여 웹뷰 자체 텍스트 선택 화면을 활용할 수 있습니다.
구글링 도중에 찾은 것을 공유합니다.

    public void selectAndCopyText() {

        try {

            Method m = WebView.class.getMethod("emulateShiftHeld"null)

            m.invoke(webViewnull);

        } catch (Exception e) {

            e.printStackTrace();

            KeyEvent shiftPressEvent = new KeyEvent(0,0,

                 KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);

            shiftPressEvent.dispatch(this);

        }

    }

=====================================================================================
위의 내용은 구글링하면서 찾은 내용입니다.
위에서 보면   KeyEvent shiftPressEvent = new KeyEvent(0,0, KeyEvent.ACTION_DOWN,KeyEvent.KEYCODE_SHIFT_LEFT,0,0);
란 부분이 있습니다.
여기서 보면 KeyEvent를 생성하여 강제적으로 ACTION_DOWN이라는 이벤트를 통해, 항상 Down Event가 들어가도록 되어 있으며, 두번째 인자인 KeyCode에서의 
KEYCODE_SHIFT_LEFT 라는 부분에 의해 SHIFT 키를 호출함 으로써, 항상 SHIFT KEY가 눌러져 있다는 KeyEvent를 생성하게 되는 것입니다.

KEYCODE_SHIFT_LEFT 의 역할은  키보드에서의 SHIFT키를 뜻합니다.
LEFT 또는 RIGHT이 있으며, 이는 둘중 아무거나 사용해도 상관 없습니다. 

안드로이드 TextView 기본 개행 단위는 아래 사진과 같이 스페이스(빈 공간)입니다.

 

이를 문자 단위의 개행으로, 아래와 같이 바꾸겠습니다.

 

아래 메쏘드는 제가 필요에 의해 만든 놈입니다.

(tistory에서 DynamicCoder님께서 작성하신 글을 참고하였습니다.)

 

/**

 * TextView의 문자열을 읽어와서 한 line에 width 만큼의 문자로 구성한다.

 * 이 때 width는 TextView의 width이다.

 *

 * @param textView 문자기준 개행을 적용하려는 대상 TextView.

 */

private void applyNewLineCharacter(TextView textView) 
{
    Paint paint = textView.getPaint();
    String text = (String) textView.getText();
    int frameWidth = 118;
    int startIndex = 0; 
    int endIndex = paint.breakText(text , true, frameWidth, null);  
    String save = text.substring(startIndex, endIndex);

    // Count line of TextView

    int lines = 1;


    while(true)
    {
        // Set new start index
        startIndex = endIndex;
        // Get substring the remaining of text
        text = text.substring(startIndex);


        if(text.length() == 0) break;

        else line++;

 

        if(lines == 4) // 3줄이 넘으면 줄임표(...)를 붙인다.
        {
            save = save.substring(0, save.length() - 2) + "...";
            break;
        }


        // Calculate end of index that fits
        endIndex = paint.breakText(text, true, frameWidth, null);
        // Append substring that fits into the frame
        save += "\n" + text.substring(0, endIndex);
    }
    // Set text to TextView
    textView.setText(save);
}

참고 :  
http://docs.cena.co.kr/?mid=textyle&sort_index=regdate&order_type=desc&comment_srl=13049&listStyle=list&document_srl=42137 

Paint 에 보면 breakText 라는 메소드가 있습니다.
이 함수의 기능은 입력한 텍스트를 지정한 길이에 맞게 계산하여 길이를 리턴해 줍니다.

http://blog.naver.com/taiji567?Redirect=Log&logNo=123892102
참고 

네이티브 애플리케이션 자동 서명용 디버그 키저장소 만들기
에뮬레이터에 내장된 네이티브 애플리케이션이 어떤 키/인증서로 서명되었는지 알았으니, 커스텀 디버그 키저장소(Custom debug keystore) 파일을 만들고, 이것을 이클립스에 등록하여 이클립스가 자동으로 네이티브 애플리케이션에 서명하도록 할 수 있습니다.
키저장소를 만들기 전에 알아둘 사항이 있는데, 생성된 java keystore 파일을 이클립스에서 사용하기 위해서는 반드시 alias는 androiddebugkey, password는 android이어야 한다는 겁니다. 그리고 openssl 과 JDK(1.6 권장)가 설치돼 있어야 합니다.
자 그럼, testkey.pk8 및 testkey.x509.pem 파일로부터 testkey.jks 파일을 만들어봅시다. 

  • 키 파일 : testkey.pk8
  • 인증서 파일 : testkey.x509.pem
  • 키 알리아스 : androiddebugkey
  • 키 패스워드 : android
  • 키저장소 패스워드 : android
  • 생성할 키저장소 파일 : testkey.jks

1. PK8 유형의 키 파일을 PEM 유형 키로 변환

$ openssl pkcs8 -inform DER -nocrypt -in testkey.pk8 -out testkey.pem

2. 키와 인증서를 포함하는 PKCS#12 포맷의 저장소 생성

$ openssl pkcs12 -export -in testkey.x509.pem -inkey testkey.pem -out testkey.p12 -password pass:android 
-name androiddebugkey

3. PKCS#12 포맷 저장소 파일을 자바 키저장소 포맷으로 변환
(1) JDK 1.5인 경우 jetty 라이브러리에 포함된 PKCS12Import 클래스를 이용

$ java -classpath jetty-core-6.1.14.jar org.mortbay.jetty.security.PKCS12Import testkey.p12 testkey.jks 

(2) JDK 1.6인 경우 JDK에서 제공하는 keytool을 이용

$ Keytool -importkeystore -deststorepass android -destkeystore testkey.jks -srckeystore testkey.p12 -srcstoretype PKCS12 -srcstorepass android

* 참고로 위의 1 ~ 3까지의 작업을 단순화시킨 keytool-importkeypair라는 스크립트가 있습니다. 아래와 같이 사용합니다

$ keytool-importkeypair -k testkey.jks -p android -pk8 testkey.pk8 -cert testkey.x509.pem -alias androiddebugkey

드디어 네이티브 애플리케이션을 이클립스를 통해 자동으로 디버그 모드 서명하기 위한 키저장소 파일을 만들었습니다. 

이클립스에 커스텀 디버그 키저장소 파일 설정하기
생성한 키저장소 파일 testkey.jks를 적당한 곳에 두고 이클립스 Preferences 창의 Android > Build 메뉴에서 커스텀 디버그 키저장소(Custom debug keystore) 필드에 설정해줍니다.

 

안드로이드에서 기본적으로 지원하지 않는 UI 를 만들때 CustomView 를 사용합니다.

이러한 CustomView 의 기본적인 작성방법을 알아보도록 하겠습니다.

 

CustomView 는 “android.view.View” 클래스를 상속해서 만들어 집니다.

기본적으로 onDraw() 메소드만 재정의해서 xml 에 view 태그만 추가하면 오류없이 출력되는것을 볼 수 있습니다.

 

이번 포스트에서는 간단히 클릭하면 반응하는 CustomView 를 만들어 보도록 하겠습니다.

먼저 CustomView 소스를 확인해 보도록 하겠습니다.

 

- CustomView.java

package net.cranix.android.customviewtest;

import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.util.AttributeSet;
import android.util.Log;
import android.view.KeyEvent;
import android.view.MotionEvent;
import android.view.View;

public class CustomView extends View {

private String text = null;
private int backgroundColor = Color.RED;

private String tempText;


// 속성이 없는 생성자는 소스상에서 직접 생성할때만 쓰인다.
public CustomView(Context context) {
super(context);
Log.w(Constants.TAG,"CustomView("+context+")");
}
/*
* 리소스 xml 파일에서 정의하면 이 생성자가 사용된다.
*
* 대부분 this 를 이용해 3번째 생성자로 넘기고 모든 처리를 3번째 생성자에서 한다.
*/
public CustomView(Context context,AttributeSet attrs) {
this(context,attrs,0);
Log.w(Constants.TAG,"CustomView("+context+","+attrs+")");
}

/*
* xml 에서 넘어온 속성을 멤버변수로 셋팅하는 역할을 한다.
*/
public CustomView(Context context,AttributeSet attrs,int defStyle) {
super(context,attrs,defStyle);

this.text = attrs.getAttributeValue(null,"text");

Log.w(Constants.TAG,"CustomView("+context+","+attrs+","+defStyle+"),text:"+text);
}

/*
* xml 로 부터 모든 뷰를 inflate 를 끝내고 실행된다.
*
* 대부분 이 함수에서는 각종 변수 초기화가 이루어 진다.
*
* super 메소드에서는 아무것도 하지않기때문에 쓰지 않는다.
*/
@Override
protected void onFinishInflate() {
setClickable(true);
Log.w(Constants.TAG,"onFinishInflate()");
}

/*
* 넘어오는 파라메터는 부모뷰로부터 결정된 치수제한을 의미한다.
* 또한 파라메터에는 bit 연산자를 사용해서 모드와 크기를 같이 담고있다.
* 모드는 MeasureSpec.getMode(spec) 형태로 얻어오며 다음과 같은 3종류가 있다.
* MeasureSpec.AT_MOST : wrap_content (뷰 내부의 크기에 따라 크기가 달라짐)
* MeasureSpec.EXACTLY : fill_parent, match_parent (외부에서 이미 크기가 지정되었음)
* MeasureSpec.UNSPECIFIED : MODE 가 셋팅되지 않은 크기가 넘어올때 (대부분 이 경우는 없다)
*
* fill_parent, match_parent 를 사용하면 윗단에서 이미 크기가 계산되어 EXACTLY 로 넘어온다.
* 이러한 크기는 MeasureSpec.getSize(spec) 으로 얻어낼 수 있다.
*
* 이 메소드에서는 setMeasuredDimension(measuredWidth,measuredHeight) 를 호출해 주어야 하는데
* super.onMeasure() 에서는 기본으로 이를 기본으로 계산하는 함수를 포함하고 있다.
*
* 만약 xml 에서 크기를 wrap_content 로 설정했다면 이 함수에서 크기를 계산해서 셋팅해 줘야한다.
* 그렇지 않으면 무조껀 fill_parent 로 나오게 된다.
*/
@Override
protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {

// height 진짜 크기 구하기
int heightMode = MeasureSpec.getMode(heightMeasureSpec);
int heightSize = 0;
switch(heightMode) {
case MeasureSpec.UNSPECIFIED: // mode 가 셋팅되지 않은 크기가 넘어올때
heightSize = heightMeasureSpec;
break;
case MeasureSpec.AT_MOST: // wrap_content (뷰 내부의 크기에 따라 크기가 달라짐)
heightSize = 20;
break;
case MeasureSpec.EXACTLY: // fill_parent, match_parent (외부에서 이미 크기가 지정되었음)
heightSize = MeasureSpec.getSize(heightMeasureSpec);
break;
}

// width 진짜 크기 구하기
int widthMode = MeasureSpec.getMode(widthMeasureSpec);
int widthSize = 0;
switch(widthMode) {
case MeasureSpec.UNSPECIFIED: // mode 가 셋팅되지 않은 크기가 넘어올때
widthSize = widthMeasureSpec;
break;
case MeasureSpec.AT_MOST: // wrap_content (뷰 내부의 크기에 따라 크기가 달라짐)
widthSize = 100;
break;
case MeasureSpec.EXACTLY: // fill_parent, match_parent (외부에서 이미 크기가 지정되었음)
widthSize = MeasureSpec.getSize(widthMeasureSpec);
break;
}


Log.w(Constants.TAG,"onMeasure("+widthMeasureSpec+","+heightMeasureSpec+")");

setMeasuredDimension(widthSize, heightSize);
}


/*
* onMeasure() 메소드에서 결정된 width 와 height 을 가지고 어플리케이션 전체 화면에서 현재 뷰가 그려지는 bound 를 돌려준다.
*
* 이 메소드에서는 일반적으로 이 뷰에 딸린 children 들을 위치시키고 크기를 조정하는 작업을 한다.
* 유의할점은 넘어오는 파라메터가 어플리케이션 전체를 기준으로 위치를 돌려준다.
*
* super 메소드에서는 아무것도 하지않기때문에 쓰지 않는다.
*/
@Override
protected void onLayout(boolean changed, int left, int top, int right,
int bottom) {
Log.w(Constants.TAG,"onLayout("+changed+","+left+","+top+","+right+","+bottom+")");
}


/*
* 이 뷰의 크기가 변경되었을때 호출된다.
*
* super 메소드에서는 아무것도 하지않기때문에 쓰지 않는다.
*/
@Override
protected void onSizeChanged(int w, int h, int oldw, int oldh) {

Log.w(Constants.TAG,"onSizeChanged("+w+","+h+","+oldw+","+oldh+")");
}


/*
* 실제로 화면에 그리는 영역으로 View 를 상속하고 이 메소드만 구현해도 제대로 보여지게 된다.
*
* 그릴 위치는 0,0 으로 시작해서 getMeasuredWidth(), getMeasuredHeight() 까지 그리면 된다.
*
* super 메소드에서는 아무것도 하지않기때문에 쓰지 않는다.
*/
@Override
protected void onDraw(Canvas canvas) {
final Paint p = new Paint();
p.setColor(backgroundColor);
canvas.drawRect(0,0,getMeasuredWidth(),getMeasuredHeight(), p);
if (text != null) {
p.setColor(Color.BLACK);
canvas.drawText(text, 10, 15, p); // 왼쪽 아래를 0,0 으로 보고있음
}
Log.w(Constants.TAG,"onDraw("+canvas+")");
}


/*
* 현재 view 가 focus 상태일때 key 를 누르면 이 메소드가 호출됨.
* 즉 이 메소드를 사용하려면 setFocusable(true) 여야함.
*
* 그리고 super 메소드에서는 기본적인 키 작업(예를들면 BACK 키 누르면 종료)을 처리하기 때문에 일반적으로 return 시에 호출하는게 좋다.
* 만약 기본적인 작업을 하지않게 하려면 super 함수를 호출하지 않아도 된다.
*
* 다른 event 메소드들도 유사하게 동작한다.
*/
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
Log.w(Constants.TAG,"onKeyDown("+keyCode+","+event+")");
return super.onKeyDown(keyCode, event);
}

/*
* 이 view 에 touch 가 일어날때 실행됨.
*
* 기본적으로 touch up 이벤트가 일어날때만 잡아내며
* setClickable(true) 로 셋팅하면 up,move,down 모두 잡아냄
*/
@Override
public boolean onTouchEvent(MotionEvent event) {
Log.w(Constants.TAG,"onTouchEvent("+event+")");
switch(event.getAction()) {
case MotionEvent.ACTION_UP:
backgroundColor = Color.RED;
text = tempText;
break;
case MotionEvent.ACTION_DOWN:
backgroundColor = Color.YELLOW;
tempText = text;
text = "Clicked!";
break;
case MotionEvent.ACTION_MOVE:
backgroundColor = Color.BLUE;
text = "Moved!";
break;
}
invalidate();
return super.onTouchEvent(event);
}


public String getText() {
return text;
}
public void setText(String text) {
this.text = text;
}
}

- 크기 계산하기

여기서 중요한 메소드는 onMeasure() 메소드 입니다.

이 메소드는 뷰의 전체 크기를 정하는 메소드 인데 안드로이드의 크기 정하는 방법에 따라 구현법이 달라져야 합니다.

 

안드로이드 레이아웃 xml 파일에서 크기를 지정하는 방법은 4가지가 있습니다.

   - fill_parent (상위 View 의 크기에 따름)

   - match_parent (상위 View 의 크기에 따름)

   - fixed (100px 와 같이 픽셀로 박아놨을때)

   - wrap_content (현재 뷰의 내용에 따름)

 

이렇게 4가지 방법의 특성에 따라서 넘어오는 크기의 종류는 3가지로 구분됩니다.

   - MeasureSpec.EXACTLY : fill_parent, match_parent, fixed 와 같이 상위에서 이미 결정되어버린 크기가 넘어올때 선택됩니다.

   - MeasureSpec.AT_MOST : wrap_content 를 선택했을때 선택됩니다.

   - MeasureSpec.UNSPECIFIED : xml 에 의하지 않고 소스상에서 직접 넣었을 때 나옵니다.

 

여기서 EXACTLY 과 UNSPECIFIED 는 외부에서 크기가 구해져서 내려오는 것이기 때문에 따로 계산할 것이 없으나 AT_MOST 는 내부적으로 크기계산을 해 주어야 합니다.

위의 소스에서는 간단하게 100,20 으로 박아놨지만 실제로 CustomView 를 구현하게 된다면 뷰의 특성에 따라 구현이 달라져야 할 것입니다.

 

 

- xml 에서 파라메터 받아내기

안드로이드 리소스 xml 에서 파라메터를 받아내려면 위 소스의 3번째 생성자에 있는것 처럼 아래와 같은 구문을 써야 합니다.

this.text = attrs.getAttributeValue(null,"text");

 

 

- xml 파일 구성하기

이렇게 만든 CustomView 를 xml 파일에서 사용하려면 아래와같은 xml 구성이 필요합니다.

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<view class="net.cranix.android.customviewtest.CustomView"
android:layout_width="fill_parent"
android:layout_height="wrap_content"
text="test"
/>
</LinearLayout>

 

- 실행해 보기

이렇게 구성된 뷰를 Activity 에 넣고 실행해 보면 아래와 같은 화면이 나옵니다.

마우스를 클릭,이동 할때마다 색깔이 변경되는것을 볼 수 있습니다.

image

image

image


'안드로이드' 카테고리의 다른 글

paint에서의 breaktext 함수의 기능.  (0) 2011.12.16
KeyStore 새성 및 sign  (0) 2011.11.07
Text의 너비와 높이를 구하는 방법  (0) 2011.10.26
텍스트 마퀴 효과  (0) 2011.10.19
Animation 에서의 interpolator  (0) 2011.10.13
1. Text의 너비와 높이를 구하는 방법
가끔 코딩을 하다가 보면 Text의 너비와 높이를 구하고 싶을 때가 있다. 
그럴때는 너비는 쉽게 구할 수 있다.

/* 페인트에 기본적인 세팅을 하고 나서 */
Paint textpaint = new Paint(Paint.ANTI_ALIAS_FLAG);
textpaint.setTypeface(Typeface.DEFAULT_BOLD);
textpaint.setColor(textcolor);
textpaint.setTextSize(textsize);

/* text의 너비를 구할 수 있다.*/
float width = textpaint.measureText(text);

하지만 문제가 되는 높이.. 방법이 없다. 하지만 얻비슷하게는 구할 수 있다.
Rect r = new Rect();
textpaint.getTextBounds(text, 0, name.length(), r);
int height = r.height(); 

아니면
float height = textpaint.getFontSpacing();
이 함수도 높이랑 비슷한 값을 나타낸다고 한다. 
하지만 정확한 수치는 아니니 조심해야 한다.


* 정확한 너비와 높이는 아니다.

'안드로이드' 카테고리의 다른 글

KeyStore 새성 및 sign  (0) 2011.11.07
android CustomView 생성하기  (0) 2011.10.27
텍스트 마퀴 효과  (0) 2011.10.19
Animation 에서의 interpolator  (0) 2011.10.13
Activity 이동시 Animation 효과 주기  (0) 2011.10.13

+ Recent posts