안드로이드 리소스 정책 #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