Build 클래스
안드로이드에서 설치된 장비(디바이스)의 정보를 확인하는 방법으로
Build 클래스를 통해 디바이스의 정보를 확인해보겠습니다.
안드로이드 공식 사이트 : https://developer.android.com/reference/android/os/Build
코드로 확인
Log.d("jjslee", "BOARD: " + Build.BOARD)
Log.d("jjslee", "SERIAL: " + Build.SERIAL)
Log.d("jjslee", "VERSION.RELEASE: " + Build.VERSION.RELEASE)
Log.d("jjslee", "MODEL: " + Build.MODEL)
Log.d("jjslee", "MANUFACTURER: " + Build.MANUFACTURER)
Log.d("jjslee", "DISPLAY: " + Build.DISPLAY)
Log.d("jjslee", "BOARD: " + Build.PRODUCT)
Log.d("jjslee", "DEVICE: " + Build.DEVICE)
Log.d("jjslee", "TYPE: " + Build.TYPE)
Log.d("jjslee", "TAGS: " + Build.TAGS)
일단 제가 가지고 있는 안드로이드 장비 3개에 대해 위 코드를 수행한 결과를 보면
1. T1006S
BOARD: mt6797
SERIAL: T1006XS32GB19353580932
VERSION.RELEASE: 8.0.0
MODEL: T1006S
MANUFACTURER: ALLDOCUBE
DISPLAY: O00623 test-keys
BOARD: T1006S
DEVICE: T1006S
TYPE: user
TAGS: test-keys
2. 갤럭시 노트10+ 5G
BOARD: exynos9825
SERIAL: unknown
VERSION.RELEASE: 10
MODEL: SM-N976N
MANUFACTURER: samsung
DISPLAY: QP1A.190711.020.N976NKSU1DTJ8
BOARD: d2xks
DEVICE: d2x
TYPE: user
TAGS: release-keys
3. 갤럭시 S7
BOARD: universal8890
SERIAL: ce0716077c5dbe1305
VERSION.RELEASE: 8.0.0
MODEL: SM-G930K
MANUFACTURER: samsung
DISPLAY: R16NW.G930KKKU3ETJ1
BOARD: heroltektt
DEVICE: heroltektt
TYPE: user
TAGS: release-keys
제조사, 모델명, 브랜드명, 제품 시리얼넘버등은 알수 있지만, 해당 디바이스가 모바일인지 키오스크인지여부는 따로 정리되어있지 않았다.
개발자 입장에서 세가지 기기를 구분하는 것은 디바이스에 따라 화면을 다르게 하기위함인 경우가 대부분일 것이다.
그럼 화면의 크기를 통해 디바이스를 구분해보겠다.
DisplayMetrics
위 클래스를 통해 크기, 밀도 및 글꼴 크기와 같은 디스플레이에 대한 일반 정보를 알수 있다.
안드로이드 공식사이트: https://developer.android.com/reference/android/util/DisplayMetrics
1. pixel(px)
스크린의 실제 픽셀 단위, 실제 크기나 밀도와 관련없다
절대적 표시 단위
해상도를 나타낼때 단위
mdpi에서 1dp = 1px 이다
ldpi : 1dp = 0.75px
mdpi : 1dp = 1px
hdpi : 1dp = 1.5px
xdpi : 1dp = 2px
예를들어 해상도가(320픽셀 × 480픽셀)이면 화소수는 153,600이다.
다바이스의 가로, 세로 픽셀수를 구해보면 다음과같다.
.widthPixels()
.heightPixels()
// Display
val display: String = getDisplay(this)
Log.d("jjslee", "getDisplay: " + display)
//.....
private fun getDisplay(context: Context?): String {
val displayMetrics = DisplayMetrics()
val windowManager = context?.getSystemService(Context.WINDOW_SERVICE) as WindowManager
windowManager.defaultDisplay.getMetrics(displayMetrics)
val deviceWidth = displayMetrics.widthPixels
val deviceHeight = displayMetrics.heightPixels
return deviceWidth.toString() + "x" + deviceHeight
}
1. T1006S 테블릿
getDisplay: 1920x1128
2. 갤럭시 노트10+ 5G
getDisplay: 1440x2759
3. 갤럭시 S7
getDisplay: 1080x1920
실제 물리적 화면의 크기는 1번 테블릿보다 2번 갤럭시노트보다 훨씬 크다.
하지만 픽셀수는 2번 갤럭시노트 10이 훨씬 크다.
다시말하면 작은 화면이지만 더 많은 픽셀로 표현 한다는 말이다.
즉, 이 픽셀수만 봐서는 실제 화면이 큰지 작은지는 알 수 없다.
다만, 같은 화면 크기이면, 얼마나 선명하게(자세히) 표현이 '가능'한가를 알수있을 뿐이다.
2. dpi(Dot per Inch)
1인치당 픽셀 수.
물리적인 단위인 1inch(2.54cm)에 몇 픽셀이 들어가는가를 나타내는 단위
Low density (120dpi) : ldpi
Medium density (160dpi) : mdpi (기본)
High density (240dpi) : hdpi
Extra High density (320dpi) : xdpi
xxhdpi : 480dpi
xxxhdpi : 640dpi
이 dpi만 봐서도 실제 화면이 큰지 작은지 알수 없다.
다만, 같은 화면 크기당 얼마나 선명하게(자세히)표현을 '실제로' 하고있는가 알수 있을 뿐다.
다바이스의 가로, 세로 dpi(Dot per Inch)를 구해보면 다음과같다.
.densityDpi()
Log.d("jjslee", "dots_per_virtual_inch: " + this.getResources().getDisplayMetrics().densityDpi)
1. T1006S
dots_per_virtual_inch: 240
2. 갤럭시 노트10+ 5G
dots_per_virtual_inch: 560
3. 갤럭시 S7
dots_per_virtual_inch: 480
3. dp (dip: Desnity Independent Pixel)
픽셀에 독립적인 단위로 안드로이드의 다양한 해상도를 지원하기 위해 만든 단위.
큰 화면이든 작은화면이든 같은 크기로 나타나게 되어있다.
즉, 화면이 작은 폰에서 10원짜리 만하게 나타난다면,
화면이 큰 폰에서도 10원짜리 만하게 나타나도록 되어있다.
4. inch(인치)
1인치(inch)=2.54센티미터(cm)
1번 px과 2번 dpi를 통해 화면의 물리적 절대값인 인치를 구할 수 있습니다.
아래 코드는 구해진 인치를 통해 테블릿과 스마트폰을 분류하여 화면을 각각 가로와 세로로 고정한 코드입니다.
// 태블릿, 폰 구분
val portrait_width_pixel = Math.min(this.getResources().getDisplayMetrics().widthPixels, this.getResources().getDisplayMetrics().heightPixels)
val dots_per_virtual_inch = this.getResources().getDisplayMetrics().densityDpi
val virutal_width_inch = portrait_width_pixel/dots_per_virtual_inch
if (virutal_width_inch <= 2) {
//is phone
Log.d("jjslee", "Device: Phone")
// 화면 세로로 고정
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT)
} else {
//is tablet
Log.d("jjslee", "Device: Tablet")
// 화면 가로로 고정
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE)
}
지금까지 안드로이드에서 화면의 밀도, 크기 및 해상도 등 다양한 속성들을 뽑아냈으면,
그 결과에따라 각 기기에 대한 레이아웃을 세분화하여 관리하는 방법을 살펴보자.
1. 화면 밀도에 따라 분류
- 화면 공간 안의 픽셀 개수, dpi(dots per inch)에 따라 분류합니다.
ldpi | 저밀도(120dpi) 화면에 해당합니다. |
mdpi | 중밀도(160dpi) 화면에 해당합니다. |
hdpi | 고밀도(240dpi) 화면에 해당합니다. |
xhdpi | 초고밀도(320dpi) 화면에 해당합니다. |
xxhdpi | 초초고밀도(480dpi) 화면에 해당합니다. |
xxxhdpi | 초초초고밀도(640dpi) 화면에 해당합니다. |
- 기기의 dpi가 기준 되는 dpi와 정확하게 맞아야 하는 것은 아닙니다. 기기의 dpi와 가장 비슷한 레이아웃으로
자동으로 찾아갑니다. 이때 고밀도에서 저밀도 순으로 우선순위가 정해집니다.
2. 최소 너비에 따라 분류
사용 가능한 화면 영역의 가장 짧은 치수를 기준으로 분류합니다.
sw<N>dp | 사용 예 : sw320dp, sw600dp, sw720dp |
- 예를 들어, sw600dp로 분류된 레이아웃은 화면의 사용 가능한 영역 중, 가로 또는 세로 중 짧은 치수를 기준으로
600dp가 넘는 경우에만 접근이 가능하도록 합니다.
3. 사용 가능한 화면 너비 또는 높이에 따라 분류
- 사용 가능한 최소 너비 또는 높이를 기준으로 분류합니다.
w<N>dp | 최소 사용 가능 너비를 dp로 지정합니다. 사용 예 : w720dp, w1024dp |
|
h<N>dp | 최소 사용 가능 높이를 dp로 지정합니다. 사용 예 : h720dp, h1024dp |
- 이전에 사용하던 화면 크기에 따른 분류(small, normal, large, xlarge)를 대체하여 사용하도록 권장되고 있습니다.
지정된 dp를 기준으로 가로 또는 높이가 기준 dp보다 높을 경우에만 접근이 가능하도록 합니다.
- 흔히 이 방법은 가로 모드와 세로 모드가 다른 레이아웃에 대응하기 위해 사용하기도 합니다.
4. 화면 방향에 따라 분류
- 화면 방향에 따라 분류합니다.
port | 세로 모드에 해당합니다. | |
land | 가로 모드에 해당합니다. |
5. 레이아웃은 하나로 통일시키고 dimens.xml을 세분화 하여 사용
위와 같이 각 조건별로 레이아웃 세분화 시에 어떤 장단점이 있을까요?
가장 큰 장점이라면 여러 기기에 대응이 가능하다는 점입니다.
여러 기기의 화면이 다름에도 같은 비율의 이미지들과 글자들을 사용하여 핸드폰, 태블릿 등을 같은 화면처럼 표현 할 수도 있고, 또는 핸드폰과 태블릿 등을 구분하여 다르게 구성할 수도 있겠죠.
반대로 단점으로는 관리가 힘들다는 점이었습니다.
유지보수 또는 추가 기능 등으로 인해 레이아웃이 바뀌게 된다면 세분화되어있는 모든 레이아웃을 수정해야만 합니다.
다른 방법으로는 dimens.xml을 이용하는 방법입니다.
레이아웃은 하나로 통일시키고 dimens.xml을 세분화 하여 사용하는 방법입니다.
dimens.xml은 레이아웃 세분화 할 때와 마찬가지로 생성하시면 되는데 이번에는 values폴더 안에 생성해줍니다.
이미지 사이즈 또는 텍스트 크기 등 기기의 해상도에 따라 변해야 하는 수치들을 각 해상도에 해당하는 dimens.xml에 정의하고 불러와 사용하도록 하였습니다.
이렇게 사용할 경우, 통합된 레이아웃을 사용하기 때문에 UI의 수정이 필요한 경우 레이아웃은 한번만 수정한 뒤, 각 해상도에 따라 dimens.xml에서 수치만 변경해주면 되기 때문에 유지보수 및 관리 측면에서 한결 간편하게 사용이 가능합니다.
참고
https://hs5555.tistory.com/150
https://developer.android.com/training/multiscreen/screensizes#alternative-layouts
https://re-build.tistory.com/34
'Android > Android 더하기' 카테고리의 다른 글
Android Shortcut(바로가기) (0) | 2022.02.12 |
---|---|
Android Kotlin + OpenCV (0) | 2021.08.06 |
안드로이드 메모리 관리 (0) | 2021.07.17 |
메모리 프로파일러를 사용하여 앱의 메모리 사용량 검사 (0) | 2021.07.17 |
Transformations LiveData 변형하기 (0) | 2021.05.13 |