윈도우 환경에서의 gcc

Posted by ironmask84
2016. 10. 31. 15:24 나는 프로그래머다!/기초 다지기


GCC (GNU Compiler Collection)는 다양한 프로그램 언어의 컴파일을 지원하는 컴파일러 시스템이며, 특히 C와 C++의 컴파일에 활용될 수 있습니다. 리눅스나 FreeBSD 등의 유닉스 계열 OS에서 매우 광범위하게 사용되어 오면서 뛰어난 성능을 검증받았습니다.

 

윈도의 경우, cygwin과 MinGW가 윈도로 포팅된 gcc의 양대산맥이라고 할 수 있는데, 둘의 성격은 꽤 다른 편입니다. cygwin의 경우 윈도에서 리눅스 환경을 느끼면서 코딩할 수 있도록 배려한 라이브러리가 포함되어 있으며, 주로 유닉스 계열에서 쓰이는 POSIX API 집합을 지원합니다. 따라서 cygwin으로 컴파일된 프로그램을 실행하기 위해서는 별도의 라이브러리(cygwin1.dll)가 필요합니다. (cygwin이 GPL 라이센스를 따르므로 라이브러리 사용시 일부 라이센스 문제가 있을 수 있습니다.)

 

한편 MinGW의 경우 MS에서 제공하는 C 런타임 라이브러리(msvcrt)를 기반으로 동작합니다. 따라서 cygwin과 달리 런타임 라이브러리는 필요하지 않으나, msvcrt가 C99의 기능들을 지원하지 않는 관계로 libmingwex라는 추가 라이브러리를 통해 해당 부분에 대한 지원을 시도하는 중입니다. (출처) 해당 문제점은 MinGW에서 갈라져 나온 새로운 가지인 MinGW-w64에서 해결되었는데, C99의 기능 뿐만 아니라 더 다양한 API, 64비트 윈도우 등에 대한 지원이 추가되었으며, 32비트용 컴파일 또한 지원합니다.

 

결론적으로, 기존에 리눅스 환경에서 실행되던 프로그램을 윈도로 포팅하는 경우에는 cygwin을 사용하고, 일반적인 윈도용 어플리케이션을 개발하기 위한 범용 컴파일러는 MinGW-w64를 사용하는 것이 좋을것 같습니다.


http://jscript.blog.me/220084163392 펌


MinGW은 이클립스 플러그인으로도 제공됩니다.

MinGW에 간단 사용기 : http://neuro.tistory.com/32


 

SW 프로그램과 개발환경(리눅스)

Posted by ironmask84
2016. 10. 31. 14:48 나는 프로그래머다!/기초 다지기





컴퓨터 공학 전공으로 졸업하고, 어언 6년이 지났건만.. 
아직 기초가 부족한 부분이 많은 것 같습니다.


학부 때는 단순히 윈도우 환경에서 Visual Studio나 Eclipse 프로그램을 사용하여
자연스런 컴파일 환경을 통해 프로그래밍 언어를 습득하기에만 정신이 없었고...

모바일 폰 개발 회사에서 재직하는 동안에도 선배들이 만들어놓은 개발 환경을 그대로 이용만 하여,
프로그래밍을 해왔기에..  개발 환경에 대해 제대로 개념을 익히는 시간이 거의 없었습니다..

학부 때 잠시나마 배웠던, 컴파일에 대한 개념도 가물가물 해졌습니다. ㅜㅜ (밑에 간단 정리..)


c언어 코딩 부터 실행파일까지의 기본 순서 : *.c -> *.s -> *.o -> *.exe or *.elf 등등

*compiler : 고수준코드(*.c)에서 목적 코드(*.o)로 옮기는 과정을 통합하여 수행하는 프로그램을 가리킨다.

*좁은 의미의 compiler : 고수준 코드(*.c)를 저수준 코드 (*.s)로 옮기는 과정을 수행하는 프로그램.

*assembler : 저수준 코드(*.s)를 목적 코드 (*o)로 옮기는 작업을 수행하는 프로그램.

*linker : 컴파일러가 만든 목적 코드 (*.o)와 library를 모아 기계어인 실행파일 (*.elf or *.exe)로 변환하는 프로그램.


사실 SW 개발자 입장에서 개발 환경은 한 번 셋팅 해놓으면, 크게 신경을 쓰지 않기에 지나치기 쉬운 것 같습니다.


임베디드 SW를 만드는 업을 해왔지만, 주로 윗단을 (Application 단 + Framework 단) 다루다가,
최근에 아랫단를 (펌웨어) 개발해야 할 기회가 왔기에.. 다시금 개발환경에 대해 파악해보려 합니다.


모바일 폰에 사용되는 칩셋(CPU)의 Core는 ARM을 이용합니다.


그리고 펌웨어 개발 환경은 대부분 리눅스 커널 환경을 사용하기에 이에 대해 잠시 집고 가볼까 합니다.

잘 정리해 주신 블로거님이 계시기에 아래에 퍼왔습니다.


일단 결론을 말씀드리자면, 아래와 같습니다.

1. 리눅스 환경에서 개발 시에는 거기서 제공하는 tool chain을 다운로드하여 사용
   (apt-get 툴을 이용해 필요한 버전의 툴 체인 설치)
2. 윈도우 환경에서 개발 시에는 주로 Cygwin(gcc 제공)을 이용하게 됩니다.

** ARM 타깃용 크로스 툴 체인 --> http://linaro.org 참조


우리가 윈도우즈 환경에서 리눅스 ARM 용 프로그램을 빌드하기 위해서는, 그에 맞는 바이너리를 생성해 줄 수 있는 환경( 컴파일러, API 등 )을 구성할 필요가 있다. 윈도우즈에서 이를 가능하게 해 주는 것이 POSIX 기반의 시그윈 개발 환경이다. 
--> Cygwin 에서는 Windows에서 사용가능한 리눅스 환경의 API들을 제공하고,
     tool chain (ARM용 gcc 크로스 툴 체인, 
git 등)을 제공합니다.


우리는  시그윈 환경을 이용해 리눅스 ARM 용 프로그램을 빌드하고, 그것을 안드로이드 장치로 복사하고 설치하게 된다. 이것이 윈도우즈와 리눅스 간의  크로스 플래폼 개발이다. 안드로이드 SDK 를 사용하게 되면 자바 바이트 코드( 플래폼에 독립적인 중간 코드 )를 생성하기 때문에 빌드 환경이 중요하지 않지만, 안드로이드 NDK 는 실제 리눅스 API 를 이용하고 기계어로 컴파일하기 때문에 반드시 올바른 환경에서 개발해야만 한다.



좀 더 자세한 내용은 아래 펌 참고...

http://lifeisforu.tistory.com/132  (안드로이드 NDK 개발환경 예시)



NDK 로 개발을 한다는 것이 의미하는 바가 무엇인지 생각해 볼 필요가 있다. 많이들 알고 있는 사실이겠지만, 어떤 프로그램이 어떤 머신에서 실행되기 위해서는 해당 머신에 맞는 실행가능한 파일( executable )을 만들어야만 한다. 그것이 소위 우리가 알고 있는 '컴파일'과 '링크'라는 작업이다. 이 컴파일 작업과 링크 작업을 합쳐서 '빌드'라고 표현한다.


우리가 열심히 코딩한 라인들은 어셈블리어로 변환되고, 이 어셈블리어들은 다시 기계어로 변환된다. 그리고 CPU 는 이 기계어를 마이크로 명령어로 나누어서 프로그램을 실행하게 된다. 그런데 이 CPU 가 어떠한 명령어 집합 구조( Instruction Set Architecture, ISA )를 제공하느냐에 따라서 다른 기계어를 만들어야 하기 때문에, 프로그램을 빌드할 때는 해당 CPU 에 맞는 구성을 만들어야 한다. 예를 들어 CPU 가 x86 ISA 를 제공한다면 x86 에 맞는 빌드 구성을 해야 하고, CPU 가 x86/64 를 제공한다면 거기에 맞는 빌드 구성을 만들어야 한다.


자 우리가 NDK 를 통해 만든 바이너리를 실행할 플래폼의 환경은 어떠한가? 일반적으로 현재 안드로이드 OS 가 돌아 가는 환경은 ARM 코어를 사용하는 리눅스 환경이다. 이는 어떠한 사실을 내포할까?


    • 우리가 C/C++ 응용프로그램을 개발할 때 CreateFile() 과 같은 Win32 API 를 사용할 수 없다.

    • Visual Studio 를 이용할 수 없다. --> VC++ 컴파일러를 사용할 수 없다.


사실 Visual Studio 의 컴파일러를 GCC( GNU Compiler Collection ) C++ 컴파일러로 연결해 놓고 개발할 수는 있을 것이다. 하지만 기본 환경 자체가 Win32 서브시스템과 x86 혹은 x86-64 아키텍처를 위한 개발에 최적화되어 있으므로 참 어려운 일이 될 것이다. 구글링을 해 보면 여러 가지 자료들이 나오기는 하는데 얼마나 편한 지는 잘 모르겠다. 어쨌든 우리는 리눅스 OS 를 기반으로 ARM ISA 에 맞춰서 빌드해야만 하는 상황이고, 윈도우즈 환경에서 이를 가능하게 만들 수 있는 방법을 찾아야만 한다. 


이때 우리에게 한 줄기 빛을 비춰주는 존재가 있으니, 그것이 바로 시그윈이다.


Cygwin 이란 무엇인가?



일단 시그윈 공식 사이트의 설명을 인용해 보도록 하겠다. 출처 : http://cygwin.com/index.html


시그윈은 :

  • 윈도우즈를 위해 리눅스처럼 느껴지는 환경을 제공하는 도구들의 집합이다.

  • 많은 리눅스 API 기능을 제공하는 리눅스 API 레이어로서 동작하는 DLL( cygwin1.dll )이다.


그리고 다음과 같이 착각하지 말라고 경고하고 있다.


시그윈은  :

  • 윈도우즈 상에서 네이티브 리눅스 앱들을 실행하는 방법이 아니다. 당신이 윈도우즈 상에서 프로그램을 실행하기 원한다면, 소스로부터 앱들을 리빌드해야만 한다.
  • signal, pty 등과 같은 유닉스 기능들을 인지하는 네이티브 윈도우즈 앱들을 마술처럼 만들어 주는 방법이 아니다. 다시 말하지만, 당신이 시그윈 기능의 이점을 취하기 원한다면, 소스로부터 앱들을 리빌드할 필요가 있다.


앞에서도 언급했지만 특정 CPU 아키텍처에 대해 리눅스용으로 빌드된 프로그램은 윈도우즈에서 실행될 수 없다. 당연히 윈도우즈 환경에 맞는 구성으로 다시 빌드해야만 한다. 시그윈은 크로스 플래폼 개발을 가능하게 해주는 환경일 뿐이지, 에뮬레이터가 아니라는 것을 명심해야만 한다.


Cygwin 의 작동 원리.



그렇다면 시그윈은 어떻게 해서 리눅스와 같은 개발 환경을 지원하게 되는 것일까?


여러분은 Visual Sutdio 를 통해 프로젝트 설정을 하다가 '서브시스템' 이라는 항목을 본 적이 있을 것이다. 윈도우즈는 여러 개의 서브시스템을 가지고 있는데, 우리가 주로 사용하는 것이 Win32 서브시스템이다. 아래 그림은 Windows NT 의 시스템 아키텍처에서의 POSIX 서브시스템을 보여 주고 있다.


윈도우즈 NT 시스템 아키텍처( 출처 : 위키피디아 )


이 POSIX 라는 것은 Portable Operating System Interface 의 약자로 IEEE 가 운영체제 간의 호환성을 유지하기 위해서 제정한 표준이다.


POSIX( 대충 '파직스'라고 발음됨 )는 "Portable Operating System Interface" 의 머리글자들이며, 운영체제 간의 호환성을 유지하기 위해서 IEEE 에 의해 제정된 표준 패밀리이다. POSIX 는 다양한 유닉스 및 다른 운영 체제들 간의 소프트웨어 호환성을 위해 응용프로그램 인터페이스( API )와 명령줄 쉘, 그리고 유틸리티 인터페이스들을 정의한다.


중략...


유닉스 같은 운영 체제 환경을 위한 POSIX 명세는 원래 코어 프로그래밍 인터페이스를 위한 단일 문서로 구성되어 있었지만, 결국에는 19 개의 분리된 문서로 늘어 났다( 예를 들면 POSIX1, POSIX2, 등 ). 표준화된 사용자 명령 줄과 스크립팅 인터페이스들은 Korn Shell 에 기반했다. awk, echo, ed 등을 포함하는 많은 사용자 수준 프로그램, 서비스, 유틸리티들도 표준화되었으며, 기본적인 I/O( 파일, 터미널, 네트웤 )을 포함하는 프로그램 수준 서비스들도 포함한다. POSIX 는 표준 스레딩 라이브러리 API 도 정의하는데, 이는 현대의 거의 대부분의 OS 에 의해서 지원된다. 요새는 대부분의 POSIX 파트들이 하나의 IEEE Std 1003. 1-2008 표준에 포하모디었으며, 이는 POSIX 1-2008 로 알려져 있다.


하략...


- 출처 : 위키피디아, POSIX


OS/2 라는 것은 MS 와 IBM 이 초기에 제작한 운영체제로 요새는 별로 의미가 없으므로 관심있는 분들은 위키피디아의 OS/2 라는 글을 따로 읽어 보기 바란다.


POSIX 를 지원하는 OS 리스트는 다음 링크의 'POSIX-oriented operating systems' 절에서 찾아 볼 수 있다 : 위키피디아, POSIXGNU/Linux 같은 경우에는 POSIX 에 대해 '거의 대부분의 호환성' 을 가지고 있다. 시그윈은 POSIX 에 대해 '많은 호환성' 을 가지고 있다고 표현되고 있다. 즉 안드로이드 시스템의 기반이 되는 리눅스가 POSIX 를 거의 완벽하게 지원하고 있기 때문에, 우리는 윈도우즈 상에서 시그윈을 통해 거기에 맞는 환경을 구성할 수 있는 것이다.


위에서 윈도우즈의 POSIX 서브시스템에서 언급을 했는데 여기에서 윈도우즈의 POSIX 를 언급한 것은 그냥 예를 든 것 뿐이다. 시그윈이 윈도우즈의 POSIX 서브시스템의 레이어라는 이야기는 아니다. 왜 그럴까? 윈도우즈의 POSIX 서브시스템은 POSIX 표준을 제대로 지키고 있지 않기 때문이다. 


시그윈은 윈도우즈의 POSIX 와는 개별적으로 동작하는 개발환경이다. 시그윈 환경, 시그윈 서브시스템, 시그윈 플래폼 등의 용어를 사용해도 무방하지 않을까 싶다. 시그윈이 윈도우즈의 POSIX 서브시스템의 레이어로서 동작하지 않는 이유는 다음 글을 보면 좀 더 이해가 가지 않을까 싶다 : The Sad History of the Microsoft POSIX Subsystem. 아래에 일부만 인용해 보았다. 요약하면 윈도우즈 POSIX 가 허접(?)이란 것과 XP 부터는 POSIX 서브시스템을 지원하지 않는다는 것이다. 그 뒤의 이야기가 쭉 나오는데 다 읽어 보지는 못했다.


윈도우즈 NT 가 처음 개발되고 있었을 때, 목표 중의 하나는 커널을 프로그래밍 인터페이스와 분리하는 것이었다. NT 는 원래 OS/2 를 성공시키기 위한 것이었지만, 마이크로소프트는 윈도우즈 3.x 응용프로그램들을 실행하기 위한 호환성을 포함시키고, 방위산업 시장에 판매하기 위한 1980 년대 DoD( 국방성 ) Orange Book 과 FIPS 명세들을 만족시키기 원했다. 결과적으로 윈도우즈 NT 는 복잡한 자유재량에 의한 접근 제어 기능을 가진 멀티유저 플래폼으로서 개발되었으며, 하이브리드 마이크로커널 3 유저랜드1 환경들로서 구현되었다 :


  • Windows( Win32 )
  • OS/2
  • POSIX


마이크로소프트는 Win32 문제를 가지고 IBM 과 다퉜으며, NT 프로젝트는 OS/2 와 갈라섰다. 팀의 초점은 Win32 로 이동했다. 그래서 Win32 API 를 호스트하는 Client Server Runtime Subsystem( CSRSS ) 은 의무적이 되었으며, OS/2 와 POSIX 서브시스템이 실제로 완료되지 않았음에도 불구하고 그것들은 윈도우즈 NT 부터 윈도우즈 2000 까지 5 개의 버전에 포함되었다. OS/2 서브시스템은 단지 OS/2 1.0 명령줄 프로그램들만을 실행할 수 있으며, presentation manager 에 대한 지원이 존재하지 않았다. POSIX 서브시스템은 POSIX.1 명세를 지원했지만, 모든 종류의 쉘이나 유닉스 같은 환경을 제공하지 않았다. Win32 가 윈도우즈 95 의 형태에서 성공하면서, OS/2 와 POSIX 서브시스템의 개발은 중단되었다. 그것들은 윈도우즈 XP 와 윈도우즈 서버 2003 에서 완전히 죽고 사라졌다.


반면에 Softway Systems 는 1996 년 쯤에 OpenNT 라고 불리는 유닉스-윈도우즈 NT 간 포팅 시스템을 개발했다. OpenNT 는 NT POSIX 서브시스템 상에서 빌드되었지만, 그것에 살을 붙여 이용할 수 있는 유닉스 환경을 제공했다. 이는 유닉스 시스템이 매우 비싸진 시점이었다. Softway 는 OpenNT 를 사용해서 US Federal agency 들을 위한 여러 유닉스 응용프로그램들을 윈도우즈 NT 로 변경했다. 1998 년에 OpenNT 는 Interix 라고 이름을 바꿨다. Softway Systems 는, 마이크로소프트 POSIX 서브시스템이 지원하지 않았던 시스템 호출을 구현하고, 풍부한 libc,  파일 시스템에 대한 single-rooted view, 그리고 실용적인 gcc 를 개발하기 위해, 최종적으로 NT POSIX 서브시스템에 대한 완전한 대체물을 만들었다.


하략...


위키피디아에 의하면 Windows Server 2003 R2 부터는 사실은 Interix 의 변형인 SUA( Subsystem for UNIX-based Applications )를 통해서 POSIX 를 지원하고 있다고 한다. 이것은 SFU( Windows Services for UNIX )라고 불리기도 한다. Windows Vista 및 Windows 7 의 Enterprise 에디션과 Ultimate 에디션도 SUA 를 포함하고 있다고 한다. 자세한 내용은 Windows Services for UNIX 를 참조하라.


결론.



우리가 윈도우즈 환경에서 리눅스 ARM 용 프로그램을 빌드하기 위해서는, 그에 맞는 바이너리를 생성해 줄 수 있는 환경( 컴파일러, API 등 )을 구성할 필요가 있다. 윈도우즈에서 이를 가능하게 해 주는 것이 POSIX 기반의 시그윈 개발 환경이다. 


우리는  시그윈 환경을 이용해 리눅스 ARM 용 프로그램을 빌드하고, 그것을 안드로이드 장치로 복사하고 설치하게 된다. 이것이 윈도우즈와 리눅스 간의  크로스 플래폼 개발이다. 안드로이드 SDK 를 사용하게 되면 자바 바이트 코드( 플래폼에 독립적인 중간 코드 )를 생성하기 때문에 빌드 환경이 중요하지 않지만, 안드로이드 NDK 는 실제 리눅스 API 를 이용하고 기계어로 컴파일하기 때문에 반드시 올바른 환경에서 개발해야만 한다.


이제 시그윈이라는 것의 정체에 대해 어느 정도 이해할 수 있게 되었을 것이라 생각한다. 그리고 시그윈을 통해 뭔가를 빌드한다는 것의 의미에 대해서 이해할 수 있게 되었을 것이라 생각한다.



'나는 프로그래머다! > 기초 다지기' 카테고리의 다른 글

컴퓨터 시스템과 임베디드 시스템 개념  (0) 2017.09.25
유니코드 이해 하기  (0) 2017.09.19
디자인패턴  (0) 2017.04.01
윈도우 환경에서의 gcc  (0) 2016.10.31
 

I2C 통신

Posted by ironmask84
2016. 10. 27. 15:11 나는 프로그래머다!/Sensor




센서 연구개발에 첫 발을 떼고 있습니다..

센서와 브레드보드(일명 빵판) 사이에는 I2C로 통신을 많이 하는 것으로 보여,
첫 관심사로 잡았습니다. ㅎㅎ


이미 블로그에 정리를 잘해주신 분들의 자료를 참고하려고 하며,
아래에 간단히 머리에 들어오는 블로그 링크 걸어 둡니다. ^^


* I2C통신으로 검색

http://blog.naver.com/jinoh9272/220578118650  <-- I2C 통신에 사용되는 SCL, SDA 와 레지스터들 기본 설명

http://cubloc.blog.me/220051675031  <-- I2C 통신 예시

http://blog.naver.com/gkf9876/220453341286 <-- MPU6050 가속-자이로 센서 +  ATmega128 PCB 예시
http://playground.arduino.cc/Main/MPU-6050 <-- MPU6050  아두이노 페이지

 

  1. I2C 통신에는 Master가 되는 PCB와 Slave가 되는 것들 (센서 등)이 있다.
  2. RS232에 비해 큰 장점이 1 : N 통신이 가능하다는 점이다. (1이 Master, N이 Slave)


 

[안드로이드-API] Layout Traversal

Posted by ironmask84
2016. 7. 8. 10:46 나는 프로그래머다!/Java & Android


Example.java

/* basic usage */

ViewGroup root = (ViewGroup) findViewById(android.R.id.content);

 

LayoutTraverser.build(new LayoutTraverser.Processor() {

  @Override

  public void process(View view) {

    // do stuff with the view

  }

}).traverse(root);


/* traverse multiple hierarchies using the same processing logic */

LayoutTraverser traverser = LayoutTraverser.build(new LayoutTraverser.Processor() {

  @Override

  public void process(View view) {

    // do stuff with the view

  }

});

 

traverser.traverse(root);

traverser.traverse(root2);

traverser.traverse(root3);



/* two static methods: finding views by tag and finding views of a specific type */

// all views tagged "coolView" under "root"

List<View> coolViews = Views.find(root, "coolView");

 

// all ImageView views under "root"

List<ImageView> imageViews = Views.find(root, ImageView.class);


LayoutTraverser.java
package com.androidwtf.android;
 
import android.view.View;
import android.view.ViewGroup;
 
public class LayoutTraverser {
  public interface Processor {
    void process(View view);
  }
 
  private final Processor processor;
 
  private LayoutTraverser(Processor processor) {
    this.processor = processor;
  }
 
  public static LayoutTraverser build(Processor processor) {
    return new LayoutTraverser(processor);
  }
 
  public void traverse(ViewGroup root) {
    final int childCount = root.getChildCount();
 
    for (int i = 0; i < childCount; ++i) {
      final View child = root.getChildAt(i);
      processor.process(child);
 
      if (child instanceof ViewGroup) {
        traverse((ViewGroup) child);
      }
    }
  }
}


Views.java

package com.androidwtf.android;

 

import android.view.View;

import android.view.ViewGroup;

 

import java.util.ArrayList;

import java.util.List;

 

final public class Views {

  private Views() {}

 

  public static List<View> find(ViewGroup root, Object tag) {

    FinderByTag finderByTag = new FinderByTag(tag);

    LayoutTraverser.build(finderByTag).traverse(root);

    return finderByTag.getViews();

  }

 

  public static <T extends View> List<T> find(ViewGroup root, Class<T> type) {

    FinderByType<T> finderByType = new FinderByType<T>(type);

    LayoutTraverser.build(finderByType).traverse(root);

    return finderByType.getViews();

  }

 

  private static class FinderByTag implements LayoutTraverser.Processor {

    private final Object searchTag;

    private final List<View> views = new ArrayList<View>();

 

    private FinderByTag(Object searchTag) {

      this.searchTag = searchTag;

    }

 

    @Override

    public void process(View view) {

      Object viewTag = view.getTag();

 

      if (viewTag != null && viewTag.equals(searchTag)) {

        views.add(view);

      }

    }

 

    private List<View> getViews() {

      return views;

    }

  }

 

  private static class FinderByType<T extends View> implements LayoutTraverser.Processor {

    private final Class<T> type;

    private final List<T> views;

 

    private FinderByType(Class<T> type) {

      this.type = type;

      views = new ArrayList<T>();

    }

 

    @Override

    @SuppressWarnings("unchecked")

    public void process(View view) {

      if (type.isInstance(view)) {

        views.add((T) view);

      }

    }

 

    public List<T> getViews() {

      return views;

    }

  }

}


출처 : https://gist.github.com/gelitenight/7999448

 

[Java] String, StringBuffer, StringBuilder 차이

Posted by ironmask84
2016. 6. 17. 17:18 나는 프로그래머다!/Java & Android


0. 들어가기 전에

 자바에서 String 문자를 더해가는건 큰 이슈가 있습니다. 보통 사람들은 String 에서 +를 이용하여 문자를 결합합니다. 이 방법은 작은 규모의 몇백자 정도로는 그렇게 큰 차이를 보이지 않을지도 모르지만 잘 모르고 쓴다면 작은 규모에서도 큰 차이를 보여줍니다. 이번에는 그 차이를 한번 따져보려고 합니다.  

 

1. 이론적인 차이

 

 1-1. String의 경우 

 

자바에서 String은 Immutable(불변의) 속성을 가지고 있습니다. 우리는 보통 String을 저장할 때 이렇게 합니다.

 

 String name = "펭귄";  

 name="치킨";  // 펭귄을 치킨으로 바꿨습니다.

 

 

위와 같이 한다면 name에 있던 펭귄이라는 치킨으로 수정되는 것 처럼 보이지만 내부적으로는 수정되는 것이 아니라 새로운 메모리를 잡고 치킨이라는 값을 저장한 후 그 곳을 가리키는 방식이 됩니다.

 

 

 

 

 + 연산자로 더하는 작업도 마찬가지입니다.

 

 String name = "펭귄";

 name = "심해"+ name; //결과 값은 심해펭귄이라고 저장됩니다.

 

새로운 메모리를 할당하여 그곳에 심해펭귄 이라는 글자를 저장하고 name이 그곳을 가리키게 한 후 기존의 펭귄이 저장된 메모리를 Garbage Collection이 제거해줍니다. 

 

 

 

단순히 문자를 몇개 더하는 경우도 이 과정을 거치지만 몇번 이내로 끝나는 횟수라면 굳이 다른 것을 쓰지 않으셔도 됩니다. (StringBuilder가 빠르지만 ns 단위의 차이입니다.) 다만 긴 문자를 몇 백번 이상 더할 경우에는 성능이 내려갈 수 있으므로 StringBuilder나 StringBuffer를 써주시는게 좋습니다. 

 

JDK5 이상의 버전부터는 String도 내부적으로 StringBuilder로 바꿔서 컴파일한다고는 하는데 막상 해보면 그다지 차이가 없습니다. 

 

 

 

 

 

1-2. StringBuilder와 StringBuffer의 경우

 

 StringBuilder와 StringBuffer는 String 과 다르게 가변의 속성을 가지고 있습니다. 그래서 할당된 공간에 계속 이어가는게 가능하며, append 메소드를 이용하여 문자를 추가합니다. 또한 할당된 공간이 오버플로우가 발생한 경우에는 자동으로 할당된 공간을 확장합니다. 

(이때 오버해드가 발생하여 속도가 약간 저하되는 듯 합니다.)

 

 StringBuilder의 경우 StringBuffer와 달리 동기화 된다는 보장을 하지 않지만 StringBuffer보다는 조금 빠른 속도를 보여줍니다.

만약 멀티 스레드를 사용하는 경우에는 동기화를 해야하는 경우가 생기는데  이 경우에는 StringBuffer를 이용하여야 합니다. StringBuffer는 멀티 스레드 작업에 대해서 안전하게 만들어져 있습니다. 하지만 일반적인 경우에는 멀티 스레드를 사용할 일이 별로 없으므로 StringBuilder를 사용하시면 되겠습니다.

 

 

 

 

2. 실제 속도 차이

 

속도를 계산하는 간단한 소스를 짜봤습니다. 글자수는 10자를 기준으로 하여 횟수를 조정하여 총 100자부터 10만자까지 더하도록 하겠습니다. 같은 시행횟수라도 시행때마다 값의 차이가 생깁니다. 하지만 그 차이는 그렇게 크지 않으며, 그 흐름 또한 일치하므로 오차가 조금 있을 수 있다 정도는 염두해 두시면 되겠습니다. 추출한 값은 ns로 추출하였지만 후반의 숫자가 매우 크므로 ms로 변환하여 표기하도록 하겠습니다.

 

 public class Main {

public static void main(String[] args) {

final int CYCLE_RATE = 10; //횟수 (10에서 10000까지 올릴겁니다) 

final String TEST_STR = "abcde12345";  //10자

for(int idx = 1; idx <= 10; idx ++){

System.out.print(idx*10*CYCLE_RATE +"\t\t"); //총 횟수

}

System.out.println("\n");

for(int idx = 1; idx <= 10; idx ++){

StringBuilderTest(CYCLE_RATE * idx, TEST_STR);

}

System.out.println("\n================================================================");

for(int idx = 1; idx <= 10; idx ++){

StringBufferTest(CYCLE_RATE * idx, TEST_STR);

}

System.out.println("\n================================================================");

for(int idx = 1; idx <= 10; idx ++){

StringTest(CYCLE_RATE * idx, TEST_STR);

}

}

public static void StringTest(int cycle, String txt){

long before = System.nanoTime();

String testString = "";

for(int idx = 0; idx < cycle; idx++){

testString += txt; //20자

}

long after = System.nanoTime();

System.out.print((after - before)+"\t\t");

}

public static void StringBuilderTest(int cycle, String txt){

long before = System.nanoTime();

String testStringBuilder = "";

StringBuilder builder = new StringBuilder();

for(int idx = 0; idx < cycle; idx++){

builder.append(txt);

}

testStringBuilder = builder.toString();

long after = System.nanoTime();

System.out.print((after - before)+"\t\t");

}

public static void StringBufferTest(int cycle, String txt){

long before = System.nanoTime();

String testStringBuffer = "";

StringBuffer buffer = new StringBuffer();

for(int idx = 0; idx < cycle; idx++){

buffer.append(txt);

}

testStringBuffer = buffer.toString();

long after = System.nanoTime();

System.out.print((after - before)+"\t\t");

}

}

 

 

10개자리 문자를 시행횟수만큼 더한 결과입니다.

문자를 10개 정도 더해도 String이 builder나 buffer보다 3-4배 정도 느린걸 알 수 있습니다. StringBuffer의 경우 처음 버퍼를 생성하는 시간 때문인지 첫 시행때 다소 시간이 걸립니다.

builder와 buffer가 속도가 느려졌다 빨라졌다 하는건 할당한 메모리가 다 차서 메모리를 늘려주는 작업을 하기 때문인 듯 합니다. 

 

 시행횟수

 10

 20

 30

 40

 50

 60

 70

 80

 90

 100

 StringBuilder

 0.009 ms

 0.012 ms

 0.016 ms

 0.027 ms

 0.03 ms

 0.03 ms

 0.039 ms

 0.037 ms

0.076  ms

 0.04 ms

 StringBuffer

 0.048 ms

 0.011 ms

 0.018 ms

 0.021 ms 

 0.023 ms 

0.027 ms  

 0.039 ms

 0.029 ms

 0.032 ms 

 0.04 ms

 String

 0.022 ms

 0.039 ms

 0.059 ms 

0.116 ms

 0.063 ms

0.077 ms 

0.133 ms 

 0.213 ms

0.129 ms

0.149 ms 

 

 

시행횟수가 백번 이상으로 넘어가면 속도차이가 확연하게 벌어집니다. Builder와 Buffer는 그렇게 큰 차이가 나진 않지만 String과의 차이는 40배 이상으로 벌어졌습니다.

 시행횟수

 100

 200

 300

 400

 500

 600

 700

 800

 900

 1000

 StringBuilder

 0.047 ms

 0.09 ms

 0.14 ms

 0.14 ms

 0.19 ms

 0.15 ms

 0.1 ms

 0.056 ms

0.056  ms

 0.076 ms

 StringBuffer

 0.050 ms

 0.021 ms

 0.032 ms

 0.040 ms 

 0.056 ms 

0.066 ms  

 0.052 ms

 0.057 ms

 0.061 ms 

 0.078 ms

 String

 0.15 ms

 0.44 ms

 2.3 ms 

0.85 ms

 2.9 ms

1.9 ms 

1.7 ms 

 2.2 ms

2.8 ms

3.5 ms 

 

 

시행횟수가 1000이 넘어가면 String과의 격차는 몇백배 입니다.

 시행횟수

 1000

 2000

 3000

 4000

 5000

 6000

 7000

 8000

 9000

 10000

 StringBuilder

 0.44 ms

 0.52 ms

 0.19 ms

 0.27 ms

 0.22 ms

0.24 ms

 0.37 ms

 0.45 ms

 0.38 ms

 1.74 ms

 StringBuffer

 0.14 ms

 0.17 ms

 0.18 ms

 0.23 ms 

 0.24 ms 

 0.26 ms  

 0.33 ms

 0.33 ms

 1.65 ms 

 0.4 ms

 String

 5.8 ms

 16.9 ms

35.1 ms 

66.4 ms 

 100.98 ms

138.43 ms 

190.3 ms 

 266.6 ms

331.78 ms 

417.3 ms

 

 

시행횟수가 10만이 되면 String은 너무 느려서 쓸 수 없습니다. 1000ms = 1초인데 62000ms라면 62초나 걸리게 됩니다.

문자가 200만개가 되니 610000 ms가 걸렸습니다. 610초 즉 10분입니다.

 시행횟수

 100000

 200000

 300000

 400000

 500000

 600000

 700000

 800000

 900000

 1000000

 StringBuilder

 9.7 ms

 8.8 ms

 18.6 ms

 15.2 ms

 29 ms

23.7 ms

 29.5 ms

 37.4 ms

 34.7 ms

 56.2 ms

 StringBuffer

 5.6 ms

 13 ms

 15.9 ms

 23.7 ms 

 25.9 ms 

 32.6 ms  

 40.6 ms

 39.5 ms

 48.7 ms 

 60.7 ms

 String

 62024 ms

  613483 ms

 ...ms 

 ...ms 

 ... ms

 ...ms 

 ...ms 

 ... ms

... ms 

... ms

 

 

덤으로 1개짜리 문자를 10000번 더하는 것이 100개짜리 문자를 100번 더하는것보다는 오래 걸리며, 100자짜리 문자를 100번 더하는 것이, 10자짜리 문자를 100번 더하는 것보다 오래 걸립니다.


펌 : http://blog.naver.com/platinasnow/220197411183


** CharSequences 인터페이스

CharSequences는 인터페이스로 String/StringBuffer/StringBuilder 세가지 클래스는 모두 

CharSequences 인터페이스를 상속받고 있습니다.


때문에 Charsequence에는 위 3가지 클래스를 모두 수용할 수 있습니다.(Up-casting)

또한 사용할 때에는 down-casting 해서 사용하시면 됩니다.


String/StringBuffer/StringBuilder 세가지 클래스를 매개변수로사용하는 함수라면 매개변수를 Charsequence로 해주는 좋겠죠?


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
public class CharSequenceTest {
 
    /**
     * @param args
     */
    public static void main(String[] args) {
        anythingString("a");
        anythingString(new StringBuffer("a"));
        anythingString(new StringBuilder("a"));
    }
    
    public static void anythingString(CharSequence c){
        System.out.println(c);
    }
   
}
 
 

펌 : http://blog.naver.com/tkddlf4209/220706609022

 

[Java] Collection Framework 간단 정리

Posted by ironmask84
2016. 6. 17. 16:15 나는 프로그래머다!/Java & Android




Collection Framework는 크게 3가지 형태로 분류할 수 있다.
  - Map  : key와 Value를 가지는 자료구조입니다. HashMap, Hashtable, TreeMap 등
  - List  : 순서가 있고 중복이 허용되는 자료구조입니다. ArrayList, LinkedList, Vector 등
  - Set   : 중복을 허용하지 않습니다.  HashSet, TreeSet 등



인터페이스에 대한 hierarchy관계를 이해하고 사용예제를 통해 각 인터페이스에 대한 특성을 확인해 보도록 한다.

[그림 3] Collection Interface 구성도


기본적으로 Collection의 경우 연속된 순서의 선형 자료형을 구현한 인터페이스이며, MAP은 Key, Value를 다루는 자료형을 구현한 인터페이스 이다. 기존에 구현된 Vector와 Hashtable의 경우, Synchronized를 지원하도록 설계되었기 때문에 다중 스레드 접근 시 병목현상을 유발할 수 있기 때문에 유의해서 사용하도록 한다.

** Collections Synchronized 

import java.util.*;

public class SynchronizedCollectionTest {
   public static void main(String[] args) {
       // create vector object
       List<String> list = new ArrayList<String>();

       // populate the list
       list.add("1");
       list.add("2");
       list.add("3");
       list.add("4");
       list.add("5");

       // create a synchronized list
       List<String> synlist = Collections.synchronizedList(list);
       System.out.println("list :"+synlist);
   }
}



참고 : http://rocksea.tistory.com/336
        http://whosnext.blog.me/100037993078




 

bulb 와 switch

Posted by ironmask84
2016. 5. 17. 17:14 나는 프로그래머다!/코딩 중...




다양한 공식적인 프로그래밍 대회가 있지만

참고로 아시아권에서 펼쳐지는 프로그래밍 대회로 ACML 라는 게 있습니다.


그리고 코드포스 (code forces) 라는 (https://codeforces.com/)

프로그래밍 경시대회? 혹은 프로그래밍 올림피아드 같은 비공식 대회가 있습니다.

https://ironmask.net/279 에서 한번 간략히 소개를 했었네요 ㅋㅋ


저는 2016년에 가입을 햇었고 사내 프로그래밍 대회에 참여를 해보려는 심산이었죠 ㅎㅎ

생각보다 프로그래밍에 그렇게 취미를 붙이기는 쉽지 않아서

결국 2문제 도전 해보고 포기했네요 ㅜㅜ


그 중 처음으로 풀어서 문제 조건을 해결해낸 문제가 아래 문제입니다.

http://codeforces.com/contest/615/problem/A


보통 프로그래밍 대회에서 나올법한 문제들은,

대량의 연산을 요구하고, 이를 빠른 수행이 완료될 것을 요구합니다.

그리고 실제대회에서는 이러한 문제를 시간내에 풀어야 하죠 ㅜㅜ

사실 문제 풀 시간을 무한정 주더라도 문제 풀어내기가 힘든 레벨입니다. ㅋ


프로그래머를 직업으로 했던 저로서는 부끄러운 일 일지 모르겠습니다만,

원래 하던 코드만 만지다 보면 이런 코드 상당히 어렵습니다.


참고로, 국정원에 도전해본적이 있었는데,

실기 시험문제가 비슷한 방식의 문제들이었던 것 같네요.


아래는 해결했던 코드입니다.

사실 Java보다 C나 C++로 해야 더욱 빠른 해결 접근법이 가능합니다만,

이때부터 Java가 주력언어가 되어서 Java로 해결했습죠..


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.Scanner;
import java.util.StringTokenizer;
 
public class Bulbs_standard {
 
    public static void main(String[] args) {
        Scanner sc = null;
        
        int c;
        String str1 = null;
        String str2 = null;
 
        int n, m = 0// button num, bulb num
        boolean[] bulbs = null;
        int cnt_turn_on = 0;
        int turn_on_bulb_num = 0;
 
        sc = new Scanner(System.in);
 
        if (sc.hasNextLine())
            str1 = sc.nextLine();
        else
            return;
 
        StringTokenizer stk = new StringTokenizer(str1, " ");
        n = Integer.parseInt(stk.nextToken()); // button number
        m = Integer.parseInt(stk.nextToken()); // bulb number
 
        bulbs = new boolean[m];
 
        while (sc.hasNextLine()) {
            str2 = sc.nextLine();
 
            stk = new StringTokenizer(str2, " ");
            cnt_turn_on = Integer.parseInt(stk.nextToken());
 
            for (int i = 1; i <= cnt_turn_on; i++) {
                turn_on_bulb_num = Integer.parseInt(stk.nextToken());
                bulbs[turn_on_bulb_num - 1= true;
            }
        }
 
        for (int i = 0; i < m; i++) {
            if (bulbs[i] == false) {
                System.out.println("NO");
                return;
            }
        }
        System.out.println("YES");
    }
}
cs


언젠가 다시..

프로그램 개발을 Job으로 하는 날이 올거라고 생각합니다..

물론 수준 높은 처우와 함께.. ^^


기초부터 쌓아올려서 다시금 이 때 레벨까지 올라가서

Codeforces를 재방문하는 날이 기다려지네요!





 

안드로이드 리소스 정책 #4 - 관리 및 방법 편

Posted by ironmask84
2016. 4. 28. 10:24 나는 프로그래머다!/Java & Android


앞서 안드로이드 플랫폼에서 리소스에 따른 정책에 대해 공유드렸습니다.

이번엔 그러한 정책에 따른 해상도별 관리를 어떻게 하는 것이 좋을지에 대해 공유 드립니다.


이번에도 이미 잘 정리해놓으신 분들의 글을 좀 퍼왔습니다. (http://arabiannight.tistory.com/entry/293 펌)

아직 앱 개발 초보라 모르는 것이 많아서 ㅠㅠ..


사실 안드로이드 플랫폼을 탑재한 모든 기기(모바일 폰, 태블릿 등등)에 대해 해상도를 최적으로 맞추기는 불가능한 수준입니다. 그래서 최대한 여러 해상도를 커버하기 위한 방법에 대해 생각해보면 아래와 같습니다.


[범용 해상도 맞추는 법]

1) 해상도별 폴더를 만들어라.

-> 안드로이드 단말만 수천개 이상, 현실적으로 불가능.

-> 타겟 단말을 지정해서 개발 해라. 


[범용 해상도를 최대한 고려한 작업 방법]

1) match_parent를 잘 활용 하라.

2) weight를 사용하라.

3) RelativeLayout을 사용 하라.

-> align, parent, below, above 등의 속성를 사용하라.

4) dp값을 활용하라.

5) 나인패치를 활용하라.

6) 통이미지라면 큰 이미지를 사용해서 작은 화면에 적용 하라.

7) Scrollview를 잘 활용하라.


나인패치 관련
개념 :  http://blog.naver.com/purplestudiogames/220605836258 참고

적용 :  http://bcho.tistory.com/1059 참고

 

안드로이드 리소스 정책 #3

Posted by ironmask84
2016. 4. 22. 16:46 나는 프로그래머다!/Java & Android


AndroidManifest.xml 파일에 속성 중에 리소스 identifier 와 비슷한 속성 설정이 있는데 아래와 같다.


android:configChanges 값이 아무것도 없을 때는 단말을 돌려서 단말 표시 모드가 portrait mode -> landscape mode 가 되면 위에서 설명된 것과 같이 기본 동작은 Activity 가 destroy 되었다가 다시 시작합니다.

android:configChanges = "orientation" 이 설정되면, portrait mode -> landscape mode 가 되어도, Activity는 destroy 되지 않습니다. 대신에 Activity에 override 된 onConfigurationChanged() 함수가 호출되며, 여기서 환경변화 ( config changes ) 에 대한 처리를 해줍니다.


이거 그냥 Activity 가 재시작되도록 둬도 될 것 같은데.. 왜, 언제 사용해요?


 가장 흔하게 접할 수 있는 경우가 위에서 예를 든 orientation changes 경우입니다.

마찬가지로 흔하게 접할 수 있는 것이 keyboardHidden 입니다.
keyboardHidden 은 hardware keyboard가 보이냐 안 보이냐에 따라서 발생하는 변화입니다.

가장 대표적인 hardware keyboard를 갖춘 device인 옵티머스 Q를 보면, 슬라이드 형식으로 QWERTY 자판을 꺼냈다 숨겼다 할 수 있죠.
이 때 변화가 없어도 되는데 쓸데 없이 Activity 가 파괴되고 생성되면 안 되겠죠? 그래서 QWERTY 자판이 있을 경우는 거의 대부분 이 attribute 설정이 필요하게 됩니다.

그 외에도 configChanges 가 발생했을 때 단순한 Activity의 재시작 이외에 추가적 작업을 해 줄 때에도 사용됩니다.



그럼 configChanges에 들어갈 수 있는 값들은 뭐가 있나요?


먼저 configChanges에는 여러가지 값들을 '|' ( or ) 구분자를 통해서 함께 입력 가능합니다.

 ValueDescription 
 "mcc"  SIM 이 Detect 되고 MCC 가 Update 될 경우. ( IMSI Mobile Country Code가 변했을 때 ) 
 "mnc" SIM 이 Detect 되고 MNC 가 Update 될 경우. ( IMSI Mobile Network Code가 변했을 때 ) 
 "locale" User 가 새로운 Language 를 선택했을 때 ( Locale 이 변경될 때 ) 
 "touchscreen" Touch Screen Hardware 가 바뀌었을 때 ( 보통은 절대 일어나지 않는 Case 임 ) 
 "keyboard" User 가 External Keyboard를 꽂았을 때를 비롯하여 Keyboard 의 Type 변경시. 
 "keyboardHidden" User 가 Hardware Keyboard를 보이고 감추는 등의 Keyboard의 Accessibility가 변경되었을 때 
 "navigation" Navigation Type ( 트랙볼 / DPad ) 가 변경되었을 때 ( 보통 절대 일어나지 않는 Case ) 
 "orientation" User가 Device 를 돌리는 등의 행위로 Screen 의 Orientation 이 변경되었을 경우.
 "screenLayout"  Screen의 Layout이 변했을 때, 다른 Display 가 Activate 되었을 경우 Layout이 변한 경우
 "fontScale" User 가 새로운 Font Size 를 선택했을 때. 
 "uiMode"  User 가 Device 를 Desk 나 Car Dock 등에 비치하여 Interface Mode 를 바꾸었을 때.


펌 : http://aroundck.tistory.com/36

 

안드로이드 리소스 정책 #2

Posted by ironmask84
2016. 4. 19. 14:09 나는 프로그래머다!/Java & Android




 Providing Resource

프로그래머는 어플리케이션의 테마를 독립적으로 유지하기위해서, 
이미지나 스트링같이 자신이 만든 코드를 통해서 어플리케이션 리소스를 외부에 보여주게 됩니다.

또한 '특정 기기 환경(specific device configurations)'을 위한 대체 리소스도 만들어야 합니다.
이 리소스들은 주제별로 그룹지어서 각각의 특성에 맞게 이름붙여진 디렉토리에 만듭니다.

실행 시, 안드로이드는 '현재 기기 환경(current configuration)'을 기반으로 적절한 리소스를 찾아 사용합니다.
스크린 사이즈에 의존되어진 UI Layout이라던가, 언어 설정에 의존된 글자 등을 예로 들수있습니다.

참고 자료 : Resource Tytpes
(주제, 특성별로 그룹지어진 Resource Type에 대한 자료입니다.)

접기

여기서 말하는 특정 기기 환경 
: 프로그래머가 미리 몇가지 특정 환경에 맞추어 제공할 리소스들이 적용될 환경

여기서 말하는 현재 기기 환경
: 프로그래머가 개발한 어플리케이션이 실행 될 기기의 환경

프로그래머가 특정환경에 맞추어진 리소스들을 제공했을때,  
예를들자면, hdpi 에 사용될 리소스들(res/drawable-hdpi 에 저장되어야 하는)을 제공했고,
사용자(어플리케이션을 사용하는)의 기기가 480*800 해상도(hdpi)를 지원하는 기기라면,
그 설정에 맞추어 res/drawable-hdpi 에 있는 리소스를 알아서 가져다 쓴다는 것입니다.
만약 res/drawable-hdpi 에 리소스가 없다면, default로 주어지는 resource를 가져다 사용하거나,
다른 특정 기기 환경에 있는 리소스를 가져다 자신의 기기에 맞게 이미지 변환 등을 통해서 사용합니다.





 Providing Alternative Resource - 대체 리소스 제공

거의 모든 안드로이드 어플리케이션은 특정 기기를 위한 대체 리소스를 지원합니다.
프로그래머는 다른 여러 screen densitiy와 여러 언어를 대체할 수 있는 drawable resource를 만들어야 합니다.

실행 시, 안드로이드는 현재 기기의 설정을 찾아서 각 어플리케이션에 적절한 리소스(resource)를 load합니다.



그렇기 때문에 대체될 리소스들에는 '특정 기기 설정'에 대해 명시해줘야 합니다.

접기

특정 기기 설정.. 이라는 표현을 쓰기는 했는데,
간단하게 생각해보면 해상도나 기타 여러가지 것들을 의미합니다.
안드로이드 디바이스는 디바이스마다 해상도나 언어설정 등이 다르기 때문에 그런것들을 의미합니다.

기본적으로 이 포스트에서 알아보려는 것은 다양한 디바이스에 따라서 안드로이드가 어떻게 리소스들을 
어떻게 매칭시켜주는지에 대한것입니다. 

접기




예를 들면, 아래와 같이 resource를 제공 할 수 있습니다.
아래의 리소스들은 default로 사용되는 resource와, 
hdpi(특정 기기의 설정(이하 - 특정 기기의 환경) : 해상도)에 사용되는 대체 리소스입니다.

- default 리소스와 hdpi 대체 리소스 -


기본적으로는 특정설정에 대한 대체 리소스 디렉토리는 아래와 같이 사용합니다.

1. res/ 디렉토리 하위로 디렉토리를 만듭니다.

2. 디렉토리 이름은 <resources_name>-<config_qualifier> 의 형태로 합니다.

3. <qualifier>는 각각의 리소스들이 사용될 개별적인 환경을 명시한 것입니다.
    qualifier에 대해서는 아래의 table 2를 참고하세요.
참고자료 -  Android Developers Providing Resource : table 2

4. 프로그래머는 여러 특정설정에 대해서 추가할 수 있습니다.(디렉토리 만드는 것)
   이때는 각 설정마다 dash(-)로 연결해줍니다.

5. 각각의 대체 리소스는 위에서 특정설정에 따라만든 디렉토리에 저장합니다.

6. 이 리소스 파일은 default 로 만들었던 리소스 파일과 이름이 정확히 일치해야 합니다.(바로 위의 그림 참고)





 Qualifier name rules - Qualifier 이름 규칙

Qualifier의 이름을 만들때는 위의 참고자료로 주어졌던 table 2 를 참고합니다.

예를들어서 기본적으로 안드로이드 프로젝트를 실행했을때 주어진 Qualifier 들이 있습니다.

res/drawable-hdpi/ : hdpi
res/drawable-mdpi/ : mdpi
res/drawable-ldpi/ : ldpi

이런 특정설정들처럼 추가적으로 특정설정에 대해서 대체 리소스들을 만들어 둘 수 있습니다.
위의 각 Qualifier(hdpi, mdpi, ldpi)는 해상도를 나타냅니다. 해상도에 대해서는 아래의 그림을 참고합니다.




하나 하나 씩 특정설정에 대한 대체리소스를 만들때는 
drawable-hdpi 라고만 써도 무방합니다.
하지만 더욱 특화시켜서 만들려고 한다면 여러개의 Qualifier를 복합해서 사용할 수 있습니다.

아래는 복합적인 사용에서의 옳은 Qualifier name과 잘못된 Qualifier name 입니다.
  • Wrong: drawable-hdpi-port/
  • Correct: drawable-port-hdpi/

둘 모두 qualifier는 정확히 사용했지만, 하나는 옳고 하나는 틀렸습니다.

그 이유는, 안드로이드는 위의 table 2 의 리스트를 위에서 부터 순서대로 확인하며 리소스를 찾기때문입니다.
(MCC, MNC 부터 SystemVersion 까지 순서대로)

위의 port(Screen Orientation)와 hdpi(Screen pixel density - dpi) 중에서는 Screen orientation 이 위에 있기때문에
drawable-hdpi-prot/ 라고 만들면 잘못된것입니다. 반드시 table 2의 순서를 지켜야 합니다.

마찬가지로 화면 방향에 따른 레이아웃을 지정하려면 아래처럼 디렉토리를 만들면 됩니다.

layout-land : 가로 레이아웃에 사용되는 리소스가 저장될 디렉토리
layout-port : 세로 레이아웃에 사용되는 리소스가 저장될 디렉토리





 Creating alias resources -  alias 리소스 만들기

아래는 alias resource를 만들어 사용한 예입니다.
(이 방법은 하나의 resource를 두고 여러 resource처럼 만들어 사용할수 있게 해줍니다.)



Drawable

<bitmap> 엘리먼트를 사용해서 이미 존재하는 drawable에 대해 alias resource를 만드는 예입니다.
1
2
3
<?xml version="1.0" encoding="utf-8"?>
    android:src="@drawable/icon_ca" />

icon_ca 라는 bitmap(또는 이미지)가 drawable 디렉토리 어디엔가 존재한다고 했을 때, 위와 같이 만들 수 있습니다.
그리고 위의 xml 파일의 이름을 icon_alias.xml 이라고 대체 리소스 디렉토리에 저장을 합니다.

이렇게 한 경우 R.drawable.icon_alias 으로 사용하게 됩니다.

R.drawable.icon_alias을 사용했지만, 
실제로는 R.drawable.icon_ca(res/drawable에 있는) 리소스를 사용하는 것입니다.



Layout

<merge>엘리먼트를 부모 엘리먼트로 가지는 <include> 엘리먼트를 사용해서,
이미 존재하는 layout에 대해서 alias resource를 만드는 예입니다.
1
2
3
4
<?xml version="1.0" encoding="utf-8"?>
<merge>
    <include layout="@layout/main_ltr"/>
</merge>

main_ltr 이라는 layout이 이미 res/layout 에 존재한다고 했을 때, 위와 같이 만들 수 있습니다.
그리고 위의 파일을 main.xml 이라고 저장합니다.

이렇게 한 경우 R.layout.main 으로 사용하게 됩니다.

Drawable에서와 마찬가지로 R.layout.main 으로 접근해서 사용하지만, 
실제로는 R.layout.main_ltr 을 사용하는것입니다.



String

ID(name)을 다르게 함으로써 alias resource를 만드는 예입니다.
1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <string name="hello">Hello</string>
    <string name="hi">@string/hello</string>
</resources>

이렇게 한 경우, R.string.hello 로 사용해도 되지만, R.string.hi 를 사용할수있게됩니다.

Layout 부터 String 까지의 내용을 보시면 아시겠지만,
이 방법은 실제 있는 리소스를 가지고 다른 방법으로 사용할 수 있게 해줍니다. 참고자료 링크




아래는 color에 대한 예입니다. 다른 예들을 보려면 위의 other simple values 링크를 따라가시면 됩니다.
1
2
3
4
5
<?xml version="1.0" encoding="utf-8"?>
<resources>
    <color name="yellow">#f00</color>
    <color name="highlight">@color/red</color>
</resources>

이렇게 해 두면
R.color.yellow, R.color.highlight 로 사용할 수 있게 됩니다.
색상을 매번 직접 지정(android:textColor="#000" 과 같이 직접 지정하는 것)하지 않고, 
alias를 통해 사용할 수 있게됩니다.




 How Android Finds the Best-matching Resource
(안드로이드는 어떻게 가장적합한 리소스를 찾아서 매칭하는가?)


아래 표는 어플리케이션이 가지고 있는(프로그래머가 제공해준, 어플이 제공해줄수 있는) 이미지 resource들과,
실제 디바이스(기기)의 환경입니다.

 images device configuration
drawable/
drawable-en/
drawable-fr-rCA/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/
Locale = en-GB 
Screen orientation = port 
Screen pixel density = hdpi 
Touchscreen type = notouch 
Primary text input method = 12key 



실제로 안드로이드는 아래의 플로우 차트를 통해 리소스를 찾아내고 매칭합니다.


 
 1번. 기기 환경과 모순되는 것들 제거하기
  Locale이 en-GB로 설정되어있기 때문에
  drawable-fr-rCA/ 디렉토리를 제거합니다.

drawable/ drawable-en/ drawable-fr-rCA/ drawable-en-port/ drawable-en-notouch-12key/ drawable-port-ldpi/ drawable-port-notouch-12key/

 2번. MCC, MNC, Language, 
      그리고 나머지 순으로 Qualifier 확인하기



 3번. 분기. 
     (qualifier 중 포함되어있는 디렉토리 찾기)
 
        매칭되었으면 4번으로,
        매칭되지 않았으면 2번으로 돌아가기


 4번. 포함되어있지 않은 Qualifier 제거하기
  lanuage qualifier 가 포함되어있지 않은 디렉토리 제거  
 
drawable/
drawable-en/
drawable-en-port/
drawable-en-notouch-12key/
drawable-port-ldpi/
drawable-port-notouch-12key/


 5번. 하나의 디렉토리로 매칭될때까지 계속하기
  계속해서 2번, 3번, 4번의 스텝을 반복하게 되면,
  결국에는 drawable-en-port 만 남게됩니다.

drawable-en/
drawable-en-port/
drawable-en-notouch-12key/ 



이번 포스팅에서는 Providing Resource에 대해서 알아보았습니다.
아무래도 정말 다양한 안드로이드 기기들에 맞출 수 있도록 하기 위해서 존재하는 것일테지요.
실제로 providing resource를 잘만 활용 한다면,
여러 기기에서 같은 UI(해상도에 따라 조금씩은 다르겠지만)를 제공할 수 있을 겁니다.

  
  참고자료
    - Android Developer Reference : Providing Resource
  
  연관자료
    - Resourc types
    - Android Developer Reference : Resource Types
    - Android Developer Reference : More Resource Types 


퍼옴 : http://croute.me/323

 

안드로이드 리소스 정책 #1

Posted by ironmask84
2016. 4. 19. 14:01 나는 프로그래머다!/Java & Android



원글 : http://developer.android.com/guide/topics/resources/providing-resources.html

 

응용 프로그램 리소스를 독립적으로 유지하기 위해, 코드에서 이미지와 문자열과 같은 리소스를 구체화해야 한다. 또한 특별한 이름이 붙여진 리소스 디렉토리들 내에서 그것들을 그룹화하여, 특정한 디바이스 구성(Configuration)을 위해 대안적인 리소스들을 제공해야한다. 안드로이드는 실행시간에 현재 구성에 바탕을 둔 적합한 리소스를 사용한다. 예를 들어 화면 크기에 따라 다른 UI 레이아웃을 사용하거나 셋팅된 언어에 따라 다른 문자열이 제공되기를 기대할 수 있다.

 

일단 응용 프로그램 리소스를 구체화하면, 프로젝트의 R 클래스 내에 만들어진 리소스 ID들을 사용하여 리소스에 접근이 가능하다. 응용 프로그램에서 리소스를 사용하는 방법은 Accessing Resources에서 확인할 수 있다. 이 문서는 어떻게 안드로이드 프로젝트 내의 리소스들을 그룹화 하고 특정 디바이스 구성을 위한 대안적인 리소스들을 제공하는지 보여준다.

 

리소스 유형 그룹화

 

프로젝트의 /res 디렉토리의 특정 하위 디렉토리에 각 타입의 리소스를 배치해야 한다.

 

MyProject/
    src/
        MyActivity.java  
    res/
        drawable/  
            icon.png  
        layout/  
            main.xml
            info.xml
        values/  
            strings.xml
 

 

이 예에서 볼 수 있듯이, 하나의 이미지 리소스(icon.png), 두 개의 레이아웃 리소스(main.xml, info.xml), 하나의 스트링 리소스 파일들(strings.xml) 등 /res 디렉토리는 (하위 디렉토리들 안에) 모든 리소스를 포함한다. 리소스 디렉토리 이름은 중요하며 표 1에 설명되어 있다.  

 

표 1. 프로젝트 res/ 디렉토리 내에 지원되는 리소스 디렉토리

 

 

 animator/

property animations을 정의하는 XML 파일

 anim/

트윈 애니메이션을 정의하는 XML 파일. (프로퍼티 애니메이션 또한 이 디렉토리에 저장할 수 있다. 그러나 animator/ 디렉토리는 두 타입 중에 프로퍼티 애니메이션이 우선권이 있다.

 color/

색상 리스트를 정의하는 XML 파일들. Color State List Resource 을 참조한다.

 drawable/

아래와 같은 드로어블 리소스의 하위 타입들로 컴파일 되는 비트맵 파일.(.png, .9.png, .jpg, .gif)이나 XML 파일들

- 비트맵 파일

- 나인패치(크기가 재조정되는 비트맵)

- 상태 리스트

- Shapes

- 애니메이션 드로어블

- 외의 드로어블

Drawable Resources을 참조한다.

 layout/

사용자 인터페이스 레이아웃을 정의하는 XML 파일. Layout Resource을 참조한다.

 menu/

옵션 메뉴, 컨텍스트 메뉴, 서브 메뉴와 같은 어플리케이션 메뉴를 정의하는 XML 파일. Menu Resource를 참조한다.

 raw/

원시형태로 저장하는 임의의 파일. 원시 InputStream으로 이 리소스 파일들을 열기 위해서는 R.raw.filename과 같은 리소스 ID와 함께 Resources.openRawResource()를 호출한다.

 

그러나, 원본 파일 이름과 파일 구조에 접근해야하는 경우, (res/raw/ 대신에) assets/ 디렉토리에 리소스를 저장할 수 있다. assets/ 내의 파일들은 리소스 ID가 주어지지 않으며, 오직 AssetManager를 사용해서 읽을 수 있다.

 values/

문자열이나 정수와 색상 같은 간단한 값을 포함하는 XML 파일

 

다른 res/ 하위 디렉토리에 있는 XML 리소스 파일들은 XML 파일 이름에 기반하여 단일한 리소스를 정의하는데 반해, values/ 디렉토리에 있는 파일들은 다수의 리소스들을 기술한다. 이 디렉토리 내에 있는 파일의 경우, <resources> 요소의 각 자식들은 하나의 자원을 정의한다. 예를 들어,  <string>는 R.string 자원을 만들고 <color> 요소는 R.color 자원을 만든다.

 

각 자원은 자체 XML 요소로 정의되어 있기 때문에, 원하는 대로 파일 이름을 지정하고 하나의 파일에 여러 자원 유형을 배치할 수 있다. 그러나 명확성을 위해서, 다른 파일에 고유한 자원 유형을 배치할 수 있다. 다음은, 디렉토리에 만들 수 있는 자원의 파일 이름에 대한 몇가지 규칙이다.

 

- 배열 리소스는 arrays.xml (typed arrays)

- 색상 값은 colors.xml

- 크기, 치수 값은 dimens.xml

- 문자열 값은 strings.xml

- 스타일은 styles.xml

 

String Resources, Style Resource와 More Resource Types을 참조한다. 

 xml

Resources.getXML() 호출에 의해 런타임에 읽을 수 있는 임의의 XML 파일. searchable configuration와 같이 다양한 XML 구성 파일들은 여기에 저장해야 한다.

 

주의 : /res 디렉토리 내에 직접적으로 리소스 파일을 저장하지 않도록 한다. 이는 컴파일 에러의 원인이 된다.

 

리소스 타입들에 대한 더 많은 정보는, Resource Types 문서를 참조한다.

 

표 1에 정의된 하위 디렉토리들 내에 저장한 리소스들은 당신의 "디폴트" 리소스들이다. 즉 이 리소스들은 응용 프로그램의 기본 디자인과 컨텐츠를 정의한다. 그러나 다른 타입의 안드로이드 디바이스들은 다른 타입의 리소스들을 요구할지 모른다. 예를 들어 디바이스가 일반적인 화면보다 더 큰 화면을 졌다면, 추가 화면 공간을 용한 다른 레이아웃 리소스들을 제공해야 한다. 또 디바이스가 다른 언어로 셋팅되어있다면, 사용자 인터페이스에서 텍스트를 번역한 다른 스트링 리소스들을 제공해야 한다. 다른 디바이스 구성에 대해 다른 리소스들을 제공하기 위해, 디폴트 리소스뿐 아니라 대안적인 리소스들을 제공할 필요가 있다.

 

 

 

대안적인 리소스 제공

 

거의 모든 응용 프로그램은 특정 디바이스 구성을 지원하기 위해 대안적인 리소스들을 제공해야한다. 예를 들어, 다른 화면 밀도를 위해 대안적인 드로어블 리소스와 다른 언어를 위한 대안적인 스트링 리소스를 포함해야 한다. 실행 시간에 안드로이드는 현재 디바이스 구성을 발견하고 적합한 리소스들을 로드한다.

 

그림 1. 각각 다른 레이아웃 리소스를 사용하는 두 개의 다른 디바이스들 

 

리소스 셋에 대해 

 

1. <resources-name>-<config_qualifier> 내에 명명되어진 res/ 내에 새로운 디렉토리를 만들어라. 

ㅁ <resources_name>은 (표 1에 정의된)디폴트 리소스들에 대응하는 디렉토리 명이다. 

ㅁ <qualifier>는 (표 2에 정의된) 리소스가 사용되는 개인 컨피규레이션을 지정한 이름이다. 

대쉬로 각각 분리해서 <qualifier>를 하나 이상 추가할 수 있다. 

주의 : 다수의 한정자를 덧붙일 때, 표 2에 목록으로 만들어진 동일한 차수 내에서 그것들을 배치해야 한다. 한정자가 틀리게 지시받으면, 리소스들은 무시된다. 

2. 이 새로운 디렉토리 내에 각각의 대안 리소스들을 저장하라. 리소스 파일들은 디폴트 리소스 파일들과 정확히 동일한 이름을 지정해야 한다. 

 

예를 들어, 여기 디폴트 리소스와 대안 리소스가 있다: 

res/
    drawable/   
        icon.png
        background.png    
    drawable-hdpi/  
        icon.png
        background.png
 

 

hdpi 한정자는 고밀도 스크린을 가진 디바이스에 대한 디렉토리 내의 리소스들을 나타낸다. 각 드로어블 디렉토리들 내의 이미지들은 특정한 스크린 밀도를 위해 크기에 따라 분류된다. 그러나 파일 이들들은 정확하게 동일하다. 이 방법으로, icon.png나 background.png 이미지를 참조하는데 사용하는 리소스 ID는 항상 동일하다. 그러나 리소스 디렉토리 이름 내에 한정자로 디바이스 구성 정보를 비교하며 안드로이드는 현재 디바이스와 가장 잘 맞는 리소스 버전을 선택한다. 

 

안드로이드는 몇몇의 구성 한정자를 제공하고 당신은 대쉬로 각 한정자를 분리시킴으로써 하나의 디렉토리 이름에 다수의 한정자를 추가할 수 있다. 표 2는 유효한 구성 한정자를 우선 순위 차례대로 목록으로 보여준다. 리소스 디렉토리에 대해 다수의 한정자를를 사용한다면, 그것들이 표에 리스트된 순서대로 디레곹리 이름에 그것들을 추가해야 한다. 


퍼옴 : http://blog.naver.com/PostView.nhn?blogId=mad_ai&logNo=130165607607

 

[JAVA] Primitive type과 Reference type 그리고 Object 클래스

Posted by ironmask84
2016. 4. 12. 17:45 나는 프로그래머다!/Java & Android


Primitive type과 Reference type 그리고 Object 클래스





Primitive type (원시타입)


● 자바 언어에 내장된 기본 유형 
● 자바는 정수, 실수, 논리, 문자 방식의 primitive type을 지원한다. 
● wrapper class는 각 primitive type을 클래스로 만든 것이다. 
● stack 메모리에 저장됨. 

■ byte 

  • 8 비트 크기에 부호있는 정수
  • 표현할 수 있는 범위는 -128 ~ 127
  • 2의 보수로 메모리에 저장됨
  • 기본값 : 0
  • wrapper class : Byte

■ short 

  • 16 비트 크기에 부호있는 정수
  • 표현할 수 있는 범위는 -32,768 ~ 32,767
  • 2의 보수로 메모리에 저장됨
  • 기본값 : 0
  • wrapper class : Short

■ int 

  • 32 비트 크기에 부호있는 정수
  • 표현할 수 있는 범위는 -2,147,483,648 ~ 2,147,483,647
  • 2의 보수로 메모리에 저장됨
  • 주로 사용
  • 기본값 : 0
  • wrapper class : Integer

■ long 

  • 64 비트 크기에 부호있는 정수
  • 범위는 -9,223,372,036,854,775,808 ~ 9,223,372,036,854,775,807
  • 2의 보수로 메모리에 저장됨
  • 기본값 : 0L
  • wrapper class : Long

■ float 

  • 32 비트 크기에 실수
  • IEEE 754 표준을 따릅니다.
  • 부동소수점 방식으로 메모리에 저장됨
  • 화폐와 같이 정확한 값을 요하는곳에 double을 사용하면 안됨
  • 기본값 : 0.0f
  • wrapper class : Float

■ double 

  • 64 비트 크기에 실수
  • IEEE 754 표준을 따릅니다.
  • 부동소수점 방식으로 메모리에 저장됨
  • 화폐와 같이 정확한 값을 요하는곳에 double을 사용하면 안됨
  • 기본값 : 0.0d
  • wrapper class : Double

■ boolean 

  • true와 false의 두 가지 값을 가지는 논리형
  • 참 / 거짓 상태를 판별하기 위한 간단한 flag로 boolean을 사용합니다.
  • 1bit의 정보를 표현하지만, 사용하는 메모리 크기는 정확히 정해져 있지 않습니다.
  • 기본값 : false
  • wrapper class : Boolean

■ char 

  • 16 비트 유니 코드 문자
  • 범위는 0 ~ 65,535 혹은 '\ u0000' ~ '\ uffff'
  • 기본값 : ‘\u0000’
  • wrapper class : Character

Reference type


  • 클래스 타입(class type), 인터페이스 타입(interface type), 배열 타입(array type), 열거 타입(enum type)
  • Ball 클래스의 참조형 변수를 선언 : Ball b; → Ball 클래스 인스턴스를 생성 후 참조형 변수에 할당 : b = new Ball(); → heap 메모리에 저장.
  • 힙 메모리에 생성된 인스턴스는 메소드나 각종 인터페이스에서 접근하기 위해 JVM의 Stack 영역에 존재하는 Frame에 일종의 포인터(C의 포인터와는 다르다.)인 참조값을 가지고 있어 이를 통해 인스턴스를 핸들링한다.
  • 그래서 참조형 클래스 사용 시 아래의 변수 할당 방식을 사용시 할당된 변수가 변경되는 원소스에 해당되는 변수도 같이 변형된다. 그래서 원소스에 해당되는 인스턴스와 별개로 할당 변수를 사용하기 위해서는 clone 내지 별개의 힙 메모리에 복사를 하여 사용하는 것이 안전하다.
1
2
3
4
5
6
7
UserTypeCls cls = new UserTypeCls();  // 원소스 참조형 변수(클래스) 생성
UserTypeCls refCls = cls;             // 새 변수에 원소스 변수 할당
refCls.changeValue(234);           // 새 변수를 변경하면 원소스 참조형 변수도 변경된다.
 
// 원소스는 변경하지 않고 새 변수만 변경하기 위해서는 clone된 인스턴스를 사용해야 한다.
UserTypeCls newRefCls - cls.cloneInscance();
newRefCls.changeValue(5678);   // 새 변수만 변경되고 원소스 변수는 변경되지 않는다.


Object Class


  • 클래스 계층구조의 루트 클래스
  • Primitive type이 아닌 모든 type(배열 포함)이 Object 클래스를 직접, 간접적으로 상속합니다.
  • Object 클래스는 JVM(특히 Execute Engine / Garbage collector)에서 클래스 인스턴스의 생성과 소멸 등의 생명주기(life cycle)을 관리할 수 있게 한다.
  • 클래스의 생성자 Object 클래스의 finalize(), wait() 등 대부분의 메소드가 JVM에서 클래스를 핸들링하기 위해 사용되는 메소드다.
  • 참조형 변수(클래스)들은 기본적으로 Object를 상속하기 때문에 모든 클래스의 인스턴스의 라이프사이클을 관리할 수 있게 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
/**
 *  생명주기 확인 예제
 */
public class LifeCycleTest {
    // 생성자
    public LifeCycleTest() {
        super();
        System.out.println("생성자 호출 : 시스템 자원을 할당 받습니다.");
    }
    void use(){
        System.out.println("use 호출 : 시스템 자원을 사용합니다.");
    }
    // Object 클래스의 finalize() 메소드 오버라이드
    @Override
    protected void finalize() throws Throwable {
        System.out.println("finalize 호출 : 시스템 자원의 할당을 해제 합니다.");
        super.finalize();
    }
}
 
public static void main(String[] args) {
        /**
         * gc를 호출 한다고 해서 가비지 컬렉터가 즉시 실행 된다는 보장은 없다.
         * finalize를 정상적으로 출력되려면 JVM 프레세서를 가능한 한 빨리 실행되도록 OS스케쥴을 조정한다.
         * (윈도우의 경우 작업관리자에서 실행되고 있는 java 프로세서의 우선순위를 높게 설정하면 된다.)
         */
        LifeCycleTest obj = new LifeCycleTest();
        obj.use();       // ResourceUser 객체를 사용한다.
        obj = null;     // ResourceUser 객체를 더이상 필요치 않은 상태로 만든다.
        System.gc();   //System  클래스의 gc(garbage collector 메소드를 호출한다.
}


실행 결과
생성자 호출 : 시스템 자원을 할당 받습니다. 
use 호출 : 시스템 자원을 사용합니다. 
finalize 호출 : 시스템 자원의 할당을 해제 합니다.



  • Object 클래스의 메소드
- clone() - 객체와 동일한 클래스의 새로운 객체를 작성합니다.- equals(Object) - 두 객체의 동일성을 비교합니다. 
- finalize() - 객체에 대한 참조가 더 이상 없다고 판별되면 메모리를 회수하면서 호출됩니다. 
- getClass() - 객체의 런타임 클래스를 리턴합니다. 
- hashCode() - 객체의 해시 코드 값을 리턴합니다. 
- notify() - 해당 객체의 모니터에 대기중인 단일 스레드를 깨웁니다. 
- notifyAll() - 해당 객체의 모니터에 대기중인 모든 스레드를 깨웁니다. 
- toString() - 객체를 표현하는 문자열을 리턴합니다. 
- wait() - 객체에 있는 다른 변경의 스레드에서 통지할 것을 기다립니다.



String 클래스


  • 문자열을 primitive type 처럼 사용할 수 있도록 String 클래스를 특별하게 처리함. 즉, String 클래스는 일종의 Primitive 타입(원시타입)처럼 사용 가능하지만 원시타입에는 속하지 않는다.
  • String 클래스는 값이 변경되지 않으며, 값을 변경하는 함수가 있지만, 이 함수는 값이 다른 String 클래스 객체를 생성한다. (immutable object)
  • String s = “aaa”; 와 같이 큰따옴표를 사용하여 생성자를 호출할 수 있다.
  • String 클래스만이 + 연산자를 통해 문자열 연결
  • String 비교시 equals() 함수 사용
  • String class의 사용 예제 : 첨부 소스 참조



링크 목록


http://www.gliderwiki.org/wiki/79  펌


 

Eclipse 에서 Tap을 Space로 변경하기

Posted by ironmask84
2016. 3. 31. 09:13 나는 프로그래머다!/Java & Android


보통 안드로이드 프로젝트를 개발할 때는 git이란 형상관리도구를 사용합니다.


git에 소스를 반영할 때는 여러 사람이 반영하게 되므로, 보통 Code Rule을 몇 가지 정해놓고 반영하도록 하는데요..

그 중에 에러를 최소화하기 위해 tab 대신에 space로 반영하도록 하는 사항이 있습니다.


코드 가독성을 위해 tab으로 들여쓰기를 보통 사용하는데,

Eclipse에서 이 tab을 누르거나, 자동 들여쓰기 기능을 할 때, Space로 바꿔주는 기능이 있습니다.


아래 2가지 방법 중 1번으로 안될 경우, 2번까지 적용하시면 됩니다.

1. Window -> Preferences -> General -> Editors ->Text Editors ->Insert spaces for tabs 체크, 

                                                           -> Displayed tab width를 4로 설정


2. Window-> Preferences -> Java -> Code Style -> Formatter
  [
Edit] 버튼을 누르고 < Indentation > 텝에서 Tab policy을 Space only 로 변경, Profile 이름을 적당히 변경


 

PreferenceActivity 와 Fragment

Posted by ironmask84
2016. 3. 10. 16:23 나는 프로그래머다!/Java & Android


http://blog.naver.com/xinfra/80172458285

http://mainia.tistory.com/2006

http://blog.naver.com/rlawlss/80140113577

http://nekomimi.tistory.com/483

http://mainia.tistory.com/2052

http://taehoonkoo.tistory.com/132

 

BroadcastReceiver 간단 정리

Posted by ironmask84
2016. 2. 1. 15:20 나는 프로그래머다!/Java & Android


안드로이드에는 BroadcastReceiver 라는 Callback 이벤트를 처리해주는 컴포넌트가 제공됩니다.


쉽게말해서, A라는 앱을 만들었는데, 

문자가 왔을 때 어떤 데이터를 받고 싶다던가 배터리가 50% 이하가 되었을 때 뭔가 변화를 주고 싶다고 한다면

SMS 앱이나 배터리체크 앱에서 어떤 이벤트를 데이터와 함께 날리게 되고,

A에서는 그 이벤트와 데이터를 받아서 원하는 기능을 처리하도록 할 수 있다는 것입니다.


위에서 언급한 이벤트처리를 복잡하지 않고 쉽게 처리해주는 녀석이 BroadcastReceiver 라는 컴포넌트 인 것입니다.


아래에 2가지 방법에 대한 예시를 올립니다.


1. BroadcastReceiver 클래스를 상속  (AppWidgetProvider 도 가능, 아마 BroadcastReceiver를 가지고 있겠지..)

   onReceive() 를 Override해서 기능 정의

   androidManifest.xml에 등록되어 있어야 함.

 androidManifest 이용해서 등록하면, 명시적으로 해제해줄 수는 없다. (unRegisterReceiver 불가능)
    (
onReceive() 메소드가 완료되면 가비지 컬렉션 대상이 되서 해지될지도... 언제 될지는 모름...)


   ex) <receiver android:name=".favorite.MissedCallWidget" >

            <intent-filter>

                <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />

                <action android:name="lge.intent.action.MISSED_CALLS" />

            </intent-filter>


            <meta-data

                android:name="android.appwidget.provider"

                android:resource="@xml/missed_call_widget_info" />



2. Actvity, Service, ContentProvider에 registerReceiver() 내에서 등록한다. 

   * onDestory() 에서 this.registerReceiver() 해줬던것을 해제가능 (메모리 누수 방지 효과도 있음)


ex) 이미 있는 action이 아니라, 새로 만든 custom action을 이용한 예시

public static final String ACTION_KEY_CODE = "com.ironmask.home.KEYCODE_ALERT";

private BroadcastReceiver mKeyCodeReceiver = null;


onCreate() 

{ .........

MyregisterReceiver();

  .........

}


onDestory()

{ ...........

    this.unRegisterReceiver(mKeyCodeReceiver);


MyregisterReceiver() {

if (mKeyCodeReceiver != null)

return;


        IntentFilter filter = new IntentFilter();

        filter.addAction(ACTION_KEY_CODE);


this.mKeyCodeReceiver = new BroadcastReceiver() {

       @Override

       public void onReceive(Context context, Intent keyintent) {

           String action = keyintent.getAction();


           if (ACTION_KEY_CODE.equals(action)) {

...

};

this.registerReceiver(this.mKeyCodeReceiver, filter);

}


미리 Broadcast를 제공하는 App에서 아래와 같이 수행해 놓으면, 위 Receiver가 동작!! 

(SMS, Call 등 이미 기본 안드로이드 App에서 제공되는 것들도 많다.)

Intent keyCodeAlert = new Intent("com.ironmask.home.KEYCODE_ALERT"); 

keyCodeAlert.putExtra("key_code", keyCode);


mContext.sendBroadcast(keyCodeAlert);


--> 위의 예시가 맞는지 다시 확인 필요...


즉, 2번 예시의 경우도, com.ironmask.home.KEYCODE_ALERT이라는 액션을 가진 Activity 내에서 
위의 과정이 있어야 한다...