안드로이드는 System Feature라는 것을 정의하고, 이 디바이스가 어떤 기능을 지원하는지 App들이 알 수 있도록 합니다.
예를 들어, 안드로이드 디바이스가 카메라를 지원하지 않을 수 있습니다. SmartPhone은 대부분 카메라를 지원하지만 Watch는 지원하지 않을 수 있기 때문입니다. 어떤 카메라 앱이 Watch에 설치되었을 때 카메라 관련 코드를 수행하면 Exception이 발생하여 앱이 죽을 수 있습니다. 이럴 때 System Feature를 확인하여 카메라를 지원하는지 확인할 수 있습니다.
예제 코드는 kotlin으로 작성되었습니다.
PackageManager.hasSystemFeature()
hasSystemFeature(String featureName)
는 인자로 전달된 Feature가 정의되어있는지 결과를 boolean으로 리턴합니다.
public abstract boolean hasSystemFeature(@NonNull String featureName);
다음과 같이 디바이스에 카메라 Feature가 정의되어있는지 확인할 수 있습니다.
if (packageManager.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
Log.d("Test", "Camera is available in this device")
}
다음과 같이 true
를 리턴하면 이 디바이스는 카메라 Feature가 정의되어있고, 실제로 카메라가 디바이스에 지원된다는 것을 의미합니다.
11-15 11:13:04.280 5002 5002 D Test : Camera is available in this device
FEATURE_WATCH
는 SmartPhone에 정의되어있지 않고, Watch device에만 정의되어있습니다. 따라서 이 Feature로 이 디바이스가 Watch인지 SmartPhone인지 구분할 수 있습니다.
if (packageManager.hasSystemFeature(PackageManager.FEATURE_WATCH)) {
Log.d("Test", "It's a watch device")
}
Feature 종류
Android에서 정의한 Feature는 Framework 코드인 PackageManager.java
에 정의되어있습니다.
정의된 내용은 Android developer - PackageManager에서 확인하실 수 있습니다.
위 사이트에서 이런식으로 보이는데 코드에서 PackageManager.FEATURE_LOCATION_NETWORK
처럼 사용할 수 있습니다.
public static final String FEATURE_LOCATION_NETWORK
Constant Value: "android.hardware.location.network"
PackageManager.getSystemAvailableFeatures()
getSystemAvailableFeatures()
는 현재 디바이스에 정의된 모든 Feature를 FeatureInfo[]
배열로 리턴합니다.
public abstract FeatureInfo[] getSystemAvailableFeatures();
다음과 같이 모든 Feature의 이름과 버전 정보를 출력할 수 있습니다.
val featureInfoArray = packageManager.systemAvailableFeatures
for (feature: FeatureInfo in featureInfoArray) {
Log.d("Test", "name: ${feature.name}, version: ${feature.version}")
}
결과는 다음과 같습니다. 내용을 보시면 디바이스가 Touchscreen을 지원하는지도 Feature로 정의되어 있습니다.
11-15 11:13:04.281 5002 5002 D Test : name: android.software.adoptable_storage, version: 0
11-15 11:13:04.281 5002 5002 D Test : name: android.hardware.sensor.accelerometer, version: 0
11-15 11:13:04.281 5002 5002 D Test : name: android.hardware.faketouch, version: 0
11-15 11:13:04.281 5002 5002 D Test : name: android.software.backup, version: 0
11-15 11:13:04.282 5002 5002 D Test : name: android.hardware.touchscreen, version: 0
11-15 11:13:04.282 5002 5002 D Test : name: android.hardware.touchscreen.multitouch, version: 0
....
11-15 11:13:04.283 5002 5002 D Test : name: android.hardware.location, version: 0
11-15 11:13:04.283 5002 5002 D Test : name: android.hardware.vulkan.level, version: 1
11-15 11:13:04.283 5002 5002 D Test : name: android.software.secure_lock_screen, version: 0
11-15 11:13:04.283 5002 5002 D Test : name: android.hardware.telephony, version: 0
11-15 11:13:04.283 5002 5002 D Test : name: android.software.file_based_encryption, version: 0
이 메소드는 API 24 이상에서 제공합니다.
hasSystemFeature(String featureName, int version)
hasSystemFeature(featureName)
와 다르게, version 정보도 인자로 전달합니다. Feature를 등록할 때 version도 함께 설정할 수 있습니다.
어떤 버전 이상의 Feature가 등록되어있는지 확인할 때 이 메소드를 사용할 수 있습니다.
/**
* Check whether the given feature name and version is one of the available
* features as returned by {@link #getSystemAvailableFeatures()}. Since
* features are defined to always be backwards compatible, this returns true
* if the available feature version is greater than or equal to the
* requested version.
*
* @return Returns true if the devices supports the feature, else false.
*/
public abstract boolean hasSystemFeature(@NonNull String featureName, int version);
예를 들어, 위에서 FEATURE_VULKAN_HARDWARE_LEVEL
는 version이 1로 설정되어 있는 것을 확인하였습니다.
만약 version 2를 지원하는 디바이스가 있고, 버전마다 다른 API를 호출해야 한다면 이 메소드를 사용하여 구분할 수 있습니다.
11-15 11:13:04.283 5002 5002 D Test : name: android.hardware.vulkan.level, version: 1
다음과 같이 버전에 따라서 다른 동작을 하도록 할 수 있습니다.
if (packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL, 1)) {
Log.d("Test", "FEATURE_VULKAN_HARDWARE_LEVEL >= 1")
}
if (packageManager.hasSystemFeature(PackageManager.FEATURE_VULKAN_HARDWARE_LEVEL, 2)) {
Log.d("Test", "Has FEATURE_VULKAN_HARDWARE_LEVEL >= 2")
}
실행해보면, 이 디바이스는 version 1을 지원하기 때문에 아래와 같이 출력됩니다.
11-15 11:34:32.375 5606 5606 D Test : FEATURE_VULKAN_HARDWARE_LEVEL >= 1
이 메소드는 API 24 이상에서 제공합니다.
adb shell로 feature 확인
adb shell pm has-feature [feature name]
으로 어떤 피쳐가 디바이스에 정의되어있는지 확인할 수 있습니다. Feature의 String을 입력해야 합니다.
$ adb shell pm has-feature android.hardware.vulkan.level
true
$ adb shell pm has-feature android.hardware.location
true
디바이스에 정의된 모든 Feature를 확인하고 싶다면 adb shell pm list features
명령어를 사용하시면 됩니다.
$ adb shell pm list features
feature:reqGlEsVersion=0x20000
feature:android.hardware.audio.output
feature:android.hardware.bluetooth
feature:android.hardware.bluetooth_le
feature:android.hardware.camera
feature:android.hardware.camera.any
feature:android.hardware.camera.ar
feature:android.hardware.camera.autofocus
feature:android.hardware.camera.capability.manual_post_processing
feature:android.hardware.camera.capability.manual_sensor
feature:android.hardware.camera.capability.raw
feature:android.hardware.camera.concurrent
feature:android.hardware.camera.flash
feature:android.hardware.camera.front
feature:android.hardware.camera.level.full
feature:android.hardware.faketouch
feature:android.hardware.fingerprint
feature:android.hardware.location
feature:android.hardware.vulkan.level=1
....
버전이 0이라면 버전 정보는 생략되며, 0을 초과하면 아래와 같이 feature_name=1
처럼 버전이 표시됩니다.
feature:android.hardware.vulkan.level=1
Related Posts
- Android 14 - 사진/동영상 파일, 일부 접근 권한 소개
- Android - adb push, pull로 파일 복사, 다운로드
- Android 14 - 암시적 인텐트 변경사항 및 문제 해결
- Jetpack Compose - Row와 Column
- Android 13, AOSP 오픈소스 다운로드 및 빌드
- Android 13 - 세분화된 미디어 파일 권한
- Android 13에서 Notification 권한 요청, 알림 띄우기
- Android 13에서 'Access blocked: ComponentInfo' 에러 해결
- 에러 해결: android gradle plugin requires java 11 to run. you are currently using java 1.8.
- 안드로이드 - 코루틴과 Retrofit으로 비동기 통신 예제
- 안드로이드 - 코루틴으로 URL 이미지 불러오기
- Android - 진동, Vibrator, VibrationEffect 예제
- Some problems were found with the configuration of task 에러 수정
- Query method parameters should either be a type that can be converted into a database column or a List
- 우분투에서 Android 12 오픈소스 다운로드 및 빌드
- Android - ViewModel을 생성하는 방법
- Android - Transformations.map(), switchMap() 차이점
- Android - Transformations.distinctUntilChanged() 소개
- Android - TabLayout 구현 방법 (+ ViewPager2)
- Android - 휴대폰 전화번호 가져오는 방법
- Android 12 - Splash Screens 알아보기
- Android 12 - Incremental Install (Play as you Download) 소개
- Android - adb 명령어로 bugreport 로그 파일 추출
- Android - adb 명령어로 App 데이터 삭제
- Android - adb 명령어로 앱 비활성화, 활성화
- Android - adb 명령어로 특정 패키지의 PID 찾기
- Android - adb 명령어로 퍼미션 Grant 또는 Revoke
- Android - adb 명령어로 apk 설치, 삭제
- Android - adb 명령어로 특정 패키지의 프로세스 종료
- Android - adb 명령어로 screen capture 저장
- Android - adb 명령어로 System 앱 삭제, 설치
- Android - adb 명령어로 settings value 확인, 변경
- Android 12 - IntentFilter의 exported 명시적 선언
- Android - adb 명령어로 공장초기화(Factory reset)
- Android - adb logcat 명령어로 로그 출력