Android P에서 달라지는 Behavior와 Features를 간단하게 살펴보자



개인 광고 영역

지난 글에서 Android P Preview 설치 및 달라진 UI에 대해서 살펴보았다. 이번 글에서는 Android P에서 달라지는 동작과 새로운 feature를 정리해보려고 한다.

Android P에서 많은 부분이 추가되었고, 수정되었다. 그중 바로 백그라운드 제한은 OS 업데이트 때마다 강화시키고 있는 부분이다. 큰 이유야 사용자의 배터리를 최대한 절약하기 위해서이고, 백그라운드에서 위험한 기능을 제한하기 위함인데 아래와 같은 제한이 추가되었다.

아래 내용은 Android P에서 동작하는 모든 앱에 영향을 미친다.

  • 앱의 마이크와 카메라를 백그라운드 접근할 수 없다.
  • 가속도계와 자이로스코프를 이용할 경우 연속적인 데이터를 받을 수 없다.
  • 센서의 on-change, on-shot에 대한 정보를 수신할 수 없다.

이번 글은 아래 글을 참고하여 작성하였으며, 필자 기준으로 정리하면 좋을 부분을 정리하였다.


연락처와 관련한 변경사항

Call Log에 대한 접근 변경 - Android P에서 동작하는 모든 앱에 영향

Android P부터는 CALL_LOG, READ_CALL_LOG, WRITE_CALL_LOG, and PROCESS_OUTGOING_CALLS 접근 권한을 CALL_LOG라는 새로운 그룹 퍼미션으로 변경하였는데 기존 퍼미션을 그룹 퍼미션으로 변경한 이유는 사용자에게 명확한 관리를 유도하기 위함이라 한다. 권한을 허용하지 않을 경우 SecurityException이 발생한다.

전화번호를 가져올 수 있는 Permissions 정보 변경 - Android P에서 동작하는 모든 앱에 영향

앞으로 연락처와 전화 상태를 가져오기 위해서는 READ_CALL_LOG 퍼미션을 추가해야 한다.

이 중 PHONE_STATE intent action를 이용하는 경우와 onCallStateChanged()를 이용하는 경우, 그리고 수신/발신에 대한 정보를 획득해야 할 경우 아래의 조건에 따라야 한다.

  • PHONE_STATE intent action를 통해 연락처 정보를 받아오는 경우, 기존에 사용하던 READ_PHONE_STATE와 함께 READ_CALL_LOG도 추가해야 한다. 이 2개의 권한을 획득하지 못하면 더 이상 정보를 획득할 수 없다.
  • onCallStateChanged()를 이용하는 경우에는 READ_CALL_LOG permission만 있어도 정보를 획득할 수 있으며, 더 이상 READ_PHONE_STATE를 필요로 하지 않는다.
  • 수신/발신 전화에 대한 정보를 획득할 경우 PHONE_STATE_CHANGED 권한 외에, READ_CALL_LOG를 추가해야 PhoneStateListener로부터 정보를 획득할 수 있다.


Wi-Fi 관련 변경 사항

Wi-Fi Location - Android P에서 동작하는 모든 앱에 영향

Wi-Fi 스캔 관련 퍼미션이 아래와 같이 추가되었다.

Wi-Fi 제한 - Android P에서 동작하는 모든 앱에 영향

Android P부터는 아래의 메서드 이용 시 개인 정보 관련 및 위치 정보를 수집할 수 없다고 한다. 특히 Wi-Fi 브로드캐스트로부터 얻을 수 있던 정보인 SSIDs, BSSIDs, 연결 정보 등은 더 이상 제공받을 수 없지만, 이러한 정보가 정말 필요로 할 경우에는 WifiManager(Android N부터는 Application Context를 이용해야 한다)의 getConnectionInfo()를 이용할 수 있다고 한다.(다만 제공하는 정보가 완벽하지 않을 수 있으며, 자세한 정보는 WifiManager API 문서를 참고하길 바란다.)

  • WifiManagergetScanResults()getConnectionInfo()
  • WifiP2pManagerdiscoverServices()addServiceRequest()
  • NetworkStateChange을 통한 broadcast

실내에서 Wi-Fi를 통한 위치 확인

Wi-Fi RTT(Round-Trip-Time)라고도 불리는 IEEE 802.11mc Wi-Fi 프로토콜을 Android P부터 제공한다. 이를 이용하면 실내에서 위치 확인을 할 수 있다. 당연하게도 하드웨어에서 기능을 제공해야 하며, 이러한 기능은 현재 위치 활성화(설정 > 시스템 > 위치정보 활성화) 상태여야 하는데, ACCESS_FINE_LOCATION 권한을 얻어야 가능하다.

자세한 내용은 Android P features - rtt 참고


화면 관련 - Android P에서 동작하는 모든 앱에 영향

안드로이드 화면 관련 부분이 수정되었다고 한다. 눈에 보이는 부분이 크지 않겠지만 좀 더 유동적인 대응을 해야 한다고 한다. Behavior changes의 Screen rotation changes)을 참고하면 더 많은 정보를 확인할 수 있다.

크게 사용자에게 보이는 화면인데 아래와 같이 화면 고정 상태에서도 System bar(내비게이션 바) 부분 오른쪽에 아이콘이 추가로 나타나며, 이를 통해 화면 회전을 시켜준다. 화면 회전을 강제로 막지 않은 경우더라도 실제 사용자가 아래와 같이 회전을 시킬 수 있으므로 이에 따른 대응을 해야 한다.

rotate-changes


FLAG_ACTIVITY_NEW_TASK 적용 - Android P에서 동작하는 모든 앱에 영향

Android N부터 Activity/Fragment가 아닌 곳에서 startActivity()를 호출할 경우 intent에 FLAG_ACTIVITY_NEW_TASK를 추가해야 한다.

startActivity(Intent(this, SampleActivity::class.java).apply {
  addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
})

이러한 조치는 Android P가 아닌 Android N 이전의 가이드이지만, Android 내부 버그로 인해 강제하지 못했다. 하지만 Android P부터는 FLAG_ACTIVITY_NEW_TASK을 적용하지 않을 경우 Activity 실행을 하지 않고, Android Logcat을 통해 오류 로그를 확인할 수 있다.


Display Cutout 지원

아이폰 X에서는 notch라 불리는 부분이 있는데 Android P에서도 이러한 부분을 추가하였다. 이름은 Notch가 아닌 Cutout이라 불린다. Android라고 이러한 부분을 피하지는 못하는 듯하고, 결국 하드웨어적인 이슈를 해결하기 전까지는 이러한 UI를 벗어나지는 못해 보인다. Cutout은 3 가지 옵션을 제공하는데 아래와 같다.

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT : 필요에 따라 Cutout을 알아서 사용한다.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_SHORT_EDGES : Cutout에서도 데이터를 표시한다.
  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER : Cutout 영역을 사용하지 않는다.

이러한 옵션은 Activity를 상속받은 클래스에서 아래와 같이 적용할 수이다.

window.attributes.layoutInDisplayCutoutMode =
 WindowManager.LayoutParams.LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER

Android P 개발자 옵션 > Drawing > Simulate a display with a cutout에서 옵션 4 가지를 활성화해볼 수 있다.

  • None : 적용하지 않음
  • Corner display cutout : 오른쪽 코너에 적용
  • Double display cutout : 상/하단에 대한 Cutout 적용
  • Tall display cutout : 상단에 Cutout 적용

android-cutout

개발자 옵션에서는 Cutout의 3 가지 타입을 적용해볼 수 있다. 실제 기기에서는 더 다양한 방식으로 Cutout이 적용될 것 같은데 흔하겐 아이폰X의 노치 형태를 볼 수 있어 보인다. 아래 샘플은 개발자 옵션 샘플 중 Tall display cutout 적용 상태로 테스트한 것이다.

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_DEFAULT : Cutout 영역을 Android Default로 처리한 상태이며, 가로로 누었을 때 아래와 같다. default인 경우 화면 방향에 따라서 Cutout 영역의 사용이 조금씩 다르게 보인다.

android-cutout-default

android-cutout-short_edges

  • LAYOUT_IN_DISPLAY_CUTOUT_MODE_NEVER : Cutout 영역을 사용하지 않게 된다. 이 경우 Cutout에서는 시계만 노출되거나, 아무것도 보이지 않을 수 있다.

android-cutout-never


Notifications

사용자에게 가장 많은 변화가 일어나는 영역인데, Android O에서 Notification Channels을 추가하여 사용자에게 채널 별 알림 설정을 유도할 수 있게 되었다. Android P에서는 좀 더 사용성을 높이기 위한 개선을 하였는데 그중 Andorid 7.0 (API level 24)부터 Reply이 생겼는데 이러한 Reply에 대한 강화를 하였다.

  • 대화 참가자를 구분하기 위한 지원 : Notification에서 사용할 새로운 Person 객체를 추가하였다. 이 객체를 통해 사용자 정보(사진, URI 등)를 간단하게 입력할 수 있으며, 참가자를 구분할 수 있다. API 24에 추가된 Notification.MessagingStyle.Message를 이용하거나, 또는 addMessage()를 이용하여 Person 객체를 쉽게 적용할 수 있다.
  • 메시지에 사진 지원 : Andorid P부터는 메시지에 사진을 지원하는데 setData()에 이미지 주소를 추가할 수 있다. 다음과 같은 샘플 코드를 확인할 수 있다.
// create new Person
val sender = Person()
  .setName(name)
  .setUri(uri)
  .setIcon(null)
  .build()
// create new Message
val message = Message("Picture Sample", time, sender)
  .setData("image", imageUri)
val style = Notification.MessagingStyle(getUser())
    .addMessage("Check this out!", 0, sender)
    .addMessage(message)
  • 노티피케이션에서 Reply을 할 수 있지만, 사용자의 실수로 노티피케이션이 쉽게 닫힐 수 있다. 이 경우 EXTRA_REMOTE_INPUT_DRAFT API을 이용하여 메시지를 이어서 작성하도록 유도 가능하다.
  • 그룹대화 식별 가능 : setGroupConversation()을 이용하여 그룹대화를 식별할 수 있다.
  • 사용자 액션 지정 : 사용자가 읽음, 삭제, 표시(Mark), 답장을 지정할 수 있는데 setSemanticAction()을 이용하여 이를 처리할 수 있다.
  • Smart 한 답장 기능 : 메시지의 구문에 따라서 추천 단어를 지원한다. 이를 통해 빠른 답장을 할 수 있는 기능을 제공하는데 setChoices() API을 활용할 수 있다.

채널 설정, 알림, 방해 금지 모드

원문 : Channel settings, broadcasts, and Do Not Disturb

Android O에서 Notification Channels이 추가되었는데 Android P부터는 이러한 Channels 설정을 단순화할 수 있다.


Multi-camera 지원 및 카메라 업데이트

Android P부터 정식으로 듀얼 카메라에 접근할 수 있는 API을 제공한다. 이를 통해 한 대의 카메라로는 할 수 없었던 기능을 구현할 수 있는데 매끄러운 확대 축소, bokeh, stereo vision 등을 REQUEST_AVAILABLE_CAPABILITIES_LOGICAL_MULTI_CAMERA 통해 사용할 수 있다.


Bitmap과 drawables의 ImageDecoder

Android P에 ImageDecoder가 추가되었다. 기존에 사용하던 BitmapFactoryBitmapFactory.Options대신 사용해야 한다.

이미지 디코더를 통해 PNG, JPG, WEBP, GIF, HEIF에 대한 인코딩을 하고, Drawable, Bitmap을 제공받을 수 있는데 아래와 같이 접근할 수 있다.

File file = new File(...);
ImageDecoder.Source source = ImageDecoder.createSource(file);
Drawable drawable = ImageDecoder.decodeDrawable(source);

이미지의 사이즈도 간단하게 조절할 수 있는데 아래와 같이 람다 표현식으로 사용할 수도 있고, Android Jetpack의 KTX을 활용할 수도 있다.

Drawable drawable = ImageDecoder.decodeDrawable(source, (decoder, info, src) -> {
      decoder.setTargetSampleSize(2);
  });


Text

Android P에는 새로운 text 관련 기능을 제공하는데, 더 자세한 내용은 Google Developer - What’s new for text in Android P을 참고할 수 있다

  • PrecomputedText이 추가되었다. 이 PrecomputedText는 렌더링 이전에 필요한 정보를 미리 캐시하여 빠른 렌더링이 가능한데 아래와 같이 TextView를 활용할 수 있다.
static void asyncSetText(TextView textView, final String longString, Executor bgExecutor) {
    // construct precompute related parameters using the TextView that we will set the text on.
    final PrecomputedText.Params params = textView.getTextMetricsParams();
    final Reference textViewRef = new WeakReference<>(textView);
    bgExecutor.submit(() -> {
        TextView textView = textViewRef.get();
        if (textView == null) return;
        final PrecomputedText precomputedText = PrecomputedText.create(longString, params);
        textView.post(() -> {
            TextView textView = textViewRef.get();
            if (textView == null) return;
            textView.setText(precomputedText);
        });
    });
}
  • Magnifier을 추가하였는데 아래 그림과 같다.

unnamedimage2

  • Smart Linkify는 Machine learning을 이용하여 텍스트의 일부 항목을 식별하고 작업을 제안하여 TextClassifier의 기능을 향상시켰다.

smart_linkifyimage3


Android backups

Android P에서는 Android Backup에 클라이언트 측 보안을 적용할 수 있다. 이렇게 암호화하는 경우에는 복원 시 PIN 또는 패턴을 입력해야 한다. 이 새로운 기능의 기술 정보는 Google Cloud Key Vault Service 정보를 참고할 수 있다.

조건부 백업 규칙에 포함할 수 있는데 새로운 requireFlags을 추가해야 하는데 옵션은 아래와 같다.

  • clientSideEncryption : 클라이언트 측에서 암호화 사용
  • deviceToDeviceTransfer : 기기 간 파일 전송에서 암호화 사용

XML에 암호화 부분을 추가하면 이전 Android 버전에서 백업이 동작하지 않으므로, 이전 버전과 비교하여 Android P의 대체 리소스를 제공해야 한다. 아래는 Android P 백업 관련 규칙에 요구 사항을 추가한 코드이다.

<?xml version="1.0" encoding="utf-8"?>
<full-backup-content>
    <include domain="sharedpref" path="." requireFlags="clientSideEncryption"/>
</full-backup-content>


마무리

몇 가지 변경사항을 정리해보았다. 더 많은 정보가 변경되었으므로 아래 링크를 통해 추가 확인해보길 바란다.



About Taehwan

My name is Taehwan Kwon. I have developed Android for 6 years and blog has been active for eight years.

Comments