Android 14 주요 항목 요약

mhyun, Park·2023년 10월 7일
0

2023년 10월 4일, Google에서 Android 14를 출시하였다. Android 14는 개발 생산성을 향상시키면서 사용자를 위한 성능, 개인 정보 보호, 맞춤화를 더욱 향상했다고 하는데 주요 항목으로 어떤 항목들이 있는지 알아보도록 하자.

Android 14 기능 및 변경사항 목록

1. 성능 및 효율성

1-1) Freezing cached applications

Android 14 이전에는 캐시된 App을 제한없이 실행할 수 있었지만, Android 14 이후부터는 캐시 된 App을 곧바로 Freezing 시켜 불필요하게 CPU를 점유하지 않도록 유지할 수 있다. 이로인해 전반적인 CPU cycle을 최대 50% 줄일 수 있었으며 Foreground Service, JobSchduler, WorkManager와 같은 Android App Lifecycle 이외에서 동작하는 App의 Background 작업은 허용되지 않는다.

1-2) Optimized broadcasts

캐싱된 App의 Freezing 상태를 더 오래 유지하기 위해 App이 context 기반 BroadcastReceiver를 수신하는 방법을 조정했다. Freezing 된 App이 캐싱 상태에서 나올 때만 BroadcastReceiver를 전달받아 처리할 수 있도록 최적화할 수 있으며 BATTERY_CHANGED와 같은 일부 반복적인 context 기반 BroadcastReceiver은 App이 캐시 상태를 벗어나기전에 하나의 BroadcastReceiver로 병합될 수 있다.

이러한 Android14 최적화 기능들은 전반적인 App launch 시간을 단축할 수 있었으며 App 코드 크기를 평균 9.3% 줄이는 최적화 기능을 더해 Device RAM 관리에 더 적합한 환경을 만들었다.

2. Customization

2-1) Bigger fonts with non-linear scailing

Android 14부턴 비선형적으로 글꼴을 200%까지 확장할 수 있는데, 비선형 확장을 통해 큰 텍스트가 작은 텍스트와 같은 속도로 증가하지 않도록 작업할 수 있다. 해당 기능 적용을 위한 모든 Text 크기 단위는 sp (Scaled Pixel)여야하며 TypedValue.applyDimensionTypedValue.deriveDimension 을 활용하여 비선형 크기를 조정할 수 있다.

2-2) Per-app language preferences

LocalManager를 통해서 App의 LocalConfig를 동적으로 얻어와 업데이트할 수 있다.
LocalManager.getApplicationLocales를 통해 현재 App이 UI하고 있는 언어를 알 수 있으며 LocalManager.setOverrideLocalConfig를 통해 App의 언어를 동적으로 최적화할 수 있다.

2-3) Regional preferences

Android System 설정에서 사용자가 선호하는 지역 설정을 할 수 있으며 App에선 이러한 설정 정보를 읽어올 수 있을 뿐만아니라 ACTION_LOCALE_CHANGED BroadcastReceiver를 등록하여 지역 설정 변경 event를 처리할 수 있다.

2-4) Grammatical Inflection

App 자체 refacotring 없이 문법적 성별을 가진 언어에 대해 지원할 수 있는 기능이 생기게 되었다.
해당 기능이 추가된 배경에는 약 30억 명의 사용자가 성별이 지정된 언어를 사용하고 있지만, 일반적으로 많은 언어에서 남성형 문법적 성별을 기본 성별 언어로 사용하고 있기 때문이라고 한다.

예시)

  • 남성형 형식: 'Vous êtes abonné à...' (영어: '...을(를) 구독하고 있습니다.')
  • 여성형 형식: 'Vous êtes abonnée à...' (영어: '...을(를) 구독하고 있습니다.')
  • 굴절이 나타나지 않는 중성적 문구: 'Abonnement à...activé' (영어: '... 구독 사용 설정됨')

사용자가 문법적 성별을 설정한 후에는 GrammaticalInflectionManager.setRequestedApplicationGrammaticalGender 를 통해 App에 적용할 수 있다.

// Set app's grammatical gender to feminine
val gIM = mContext.getSystemService(GrammaticalInflectionManager::class.java)
gIM.setRequestedApplicationGrammaticalGender(Configuration.GRAMMATICAL_GENDER_FEMININE)

// Get app's grammatical gender
val grammaticalGender = gIM.getApplicationGrammaticalGender()

3. New media capabilities

3-1) Ultra HDR for images

Android 14부터는 10bit 이미지에 대한 지원을 추가하여 Camera sensor에서 더 많은 정보를 유지하하여 생생한 색감과 높은 대비를 표현할 수 있게된다. 이러한 신규 ImageFormat은 Ultra HDR Format로 명칭되었으며 Android Window 에서도 활용할 수 있게되기에 더 생동감있는 사진 역시 Viewer에서 경험할 수 있게된다.

cf) 10bit still ImageFormat - JPEG_R

3-2) Zoom, Focus, Postview and more in Camera Extensions

Camera Extensions을 통해 App이 더 긴 처리 사진 처리를 할 수 있도록 지원했으며 향상 된 저조도 촬영과 배경 Blur 기능 그리고 final image 전에 draft image를 보여주어 UX를 개선시킬 수 있는 feature를 지원한다. (Samsung Camera에 이미 예전부터 있는 기능인데..ㅎ)

3-3) Lossless USB audio

AudoMixerAttributes를 통해 USB 연결된 headset에서 무손실 audio format을 지원한다고 한다.

4. Improving productivity

4-1) OpenJDK 17 Update

Android 14부터는 Java 17 지원을 하게 된다. 이에따라 다음과 같은 주요 개선 사항들을 통해 개발 생산성을 향상시킬 수 있다.

  • Text Block : 멀티 라인 문자열을 단순화하여 처리할 수 있게 되었다
// JAVA 17 이전
String multilineText = "Java 17이전 Text Block을 사용하여, \n" +
                       "멀티 라인 문자열을 쉽게 작성할 수 있다네요\n" +
                       "들여쓰기와 줄바꿈이 자동으로 처리됩니다.\n";
                      
// JAVA 17 이후
String multilineText = """
                        Java 17이전 Text Block을 사용하여
                        멀티 라인 문자열을 쉽게 작성할 수 있습니다.
                        들여쓰기와 줄바꿈이 자동으로 처리됩니다.
                       """;
  • Record : kotlin data class와 같이 boliler plate code가 존재하지 않는 DTO 객체를 지원한다.
public record Person(String name, String age, String gender) {

    // getter, setter, toString, equals, hashcode 가 모두 자동 구현되어 있다.
    // 필요에 따라 해당 method를 재정의하거나 신규 method를 추가하여 운용할 수 있다.
    
    @Override
    public String toString() {
        return "Person{" +
                "override_name='" + name + '\'' +
                ", override_age='" + age + '\'' +
                ", override_gender='" + gender + '\'' +
                '}';
    }

	public boolean isMan() {
        return this.gender == "man";
    }
}
  • instanceof의 패턴 일치 : 추가 변수 없이 객체를instanceof에 특정 유형이 있는 것으로 취급할 수 있다.
    // Java 8
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Student) {
            Student student = (Student) obj;
            if (this.studentNumber == student.studentNumber) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }
    
    // Java 17
    @Override
    public boolean equals(Object obj) {
        if (obj instanceof Student student) {
            if (this.studentNumber == student.studentNumber) {
                return true;
            } else {
                return false;
            }
        }
        return false;
    }
  • 봉인 클래스 : 확장하거나 구현할 수 있는 클래스와 인터페이스를 제한할 수 있다.
// 1. Parent의 자식 class는 Child 허용한다.
public sealed class Parent permits Child {
	...
}

// 2. Child는 non-sealed 키워드로 다음과 같이 상속 봉인을 해제하거나
public non-sealed class Child extends Parent {
	...
}

// 3. sealed 키워드를 사용해서 또 다른 봉인 클래스로 선언할 수 있다.
public sealed class Child extends Parent permit GrandChild {
	...
}

// 4. final 키워드를 사용하면 기존과 마찬가지로 아무도 상속받을 수 없게된다.
public final class Child extends Parent {
	...
}

5. 개인정보 보호 및 보안

5-1) Partial access to photos and videos

사용자가 선택한 사진 및 동영상에만 App 접근 권한을 부여할 수 있다.
사용자는 App과 Media를 보다 편안하게 공유할 수 있으며 개발자는 아래 권한을 통해 지원할 수 있으며

  • READ_MEDIA_IMAGES
  • READ_MEDIA_VIDEO
  • READ_MEDIA_VISUAL_USER_SELECTED

Google은 자기네들이 만든 PhotoPicker를 이용하면 migration 없이 편히 지원할 수 있으니 이를 사용하라고 대놓고 광고하고 있다.

5-2) Safer dynamic code loading

Android 14부터는 동적으로 load된 파일(DEX, JAR, APK...) 을 읽기 전용으로 표시한 후 사용해야 한다.

val jar = File("DYNAMICALLY_LOADED_FILE.jar")
val os = FileOutputStream(jar)
os.use {
    // Set the file to read-only first to prevent race conditions
    jar.setReadOnly()
    // Then write the actual file content
}
val cl = PathClassLoader(jar, parentClassLoader)

5-3) Safer implicit intents

Android 14를 target하는 App대헤선 아래 기존과 같은 방식으로 암시적 인텐트를 내부 앱 구성요소로 보내는 경우 Exception을 발생시킨다. 이러한 변경 사항은 악성 앱이 앱의 내부 구성 요소에서 사용하도록 의도된 암시적 인텐트를 가로채는 것을 방지한다고 한다.

<activity
    android:name=".AppActivity"
    android:exported="false">
    <intent-filter>
        <action android:name="com.example.action.APP_ACTION" />
        <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</activity>

// Throws an exception when targeting Android 14.
context.startActivity(Intent("com.example.action.APP_ACTION"))

Exception을 발생시키지 않기 위해선, 다음과 같이 자신의 context.packageName을 포함한 명시적 인텐트로 보내야 한다.

// This makes the intent explicit.
val explicitIntent = Intent("com.example.action.APP_ACTION").apply {
    package = context.packageName
}
context.startActivity(explicitIntent)
profile
Android Framework Developer

2개의 댓글

comment-user-thumbnail
2023년 12월 14일

안녕하세요 항상 잘보고있습니다.
안드로이드 14 관련하여 궁금한게 있습니다
저희 서비스에서 bindService()를 이용하여 다른앱에 바인드 하는데
처음 시도에는 앱 호출이 안되고 두번째 바인드를 해야지 호출이 되는데
말씀해주신 Freezing cached applications와 관련이 있을까요??
앱 배터리 최적화와 연관이 있는걸로 보여서 배터리 최적화를 끄면 이런 현상은 보이지 않아서
14버전의 버그로 보입니다만..
혹시 아시면 공유 부탁드리겠습니다..!

1개의 답글