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