ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Android] Android 14: Broadcast Receiver와 Foreground Service 유형 정책 변경
    Android 2024. 5. 2. 02:42
    반응형

    배경

    기존에 Broadcast Receiver와 Foreground Service를 사용하는 앱이라면 신경 써주어야 하는 정책적인 변경점이 하나 생겼는데요. 최근에 Android 14가 나오고 SDK가 34 이상으로 올라감에 따라 해당 버전 값으로 올리게 되면 정책이 변경됨에 따라 처리해주어야 할 것이 많아졌습니다. 기존에는 권한 정도만 하나 올려주고, 버전 별로 사용에 다른 분기 처리 정도만 해주면 되었지만, 이게 뭔가 좀 더 바뀌었습니다.

     

    만약 아래와 같이 추가 선언을 하지 않는다? Broadcast Receiver의 경우 이제 아래와 같은 Exception이 발생하면서 앱이 죽어버리고 Foreground Service의 경우 그냥 서비스가 실행이 되지 않습니다...

    java.lang.SecurityException:

     

     

    동작 변경사항: Android 14 이상을 타겟팅하는 앱  |  Android Developers

    Android 14 이상을 타겟팅하는 앱에 영향을 미치는 Android 14의 변경사항을 알아봅니다.

    developer.android.com

    구글님께서 Android 14를 타겟팅하는 앱은 아래의 가이드를 참고해서 정책을 적용하라고 친절하게 문서까지 만들어 주셨습니다. 앱이 죽는 것만은 막아야 되니까 구글님이 하라고 하는대로 해도록 하죠. 한번 살펴봅시다.

     

     

     

     

     

    Broadcast Receiver를 사용하는 경우

    registerReceiver를 호출할 때 다른 앱과 통신을 해야하는 지에 대한 값을 명시적으로 나타내야하는 것 같습니다. 아래와 같이 코드를 변경해 주어야 합니다.

    이 때 외부와 통신을 하냐 안 하냐에 따라 RECEIVER_EXPORTED 를 사용할 것인지 RECEIVER_NOT_EXPORTED를 사용할 것인지 결정해 주어야 합니다.

    // 기존에는 아래와 같이 사용하고 있었다면
    registerReceiver(receiver, intentFilter)
    // 이제는 이렇게 해주어야 합니다.
    if (Build.VERSION.SDK_INT == 34 && this.applicationInfo.targetSdkVersion <= 34) {
    	registerReceiver(receiver, intentFilter, Context.RECEIVER_EXPORTED)
    } else {
    	registerReceiver(receiver, intentFilter)
    }

     

    동작 변경사항: Android 14 이상을 타겟팅하는 앱  |  Android Developers

    Android 14 이상을 타겟팅하는 앱에 영향을 미치는 Android 14의 변경사항을 알아봅니다.

    developer.android.com

    반응형

     

     

    Foreground Service를 사용하는 경우

    이 경우엔 해주어야 할 것이 더 많아집니다. 권한도 추가해야 되고, 타입도 추가해야 하고, startForeground 메서드 파라미터도 추가해야 합니다. 차근차근 살펴봅시다.

     

     

     

    AndroidManifest.xml 선언하기

    <manifest ...>
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
        <application ...>
          <service
              android:name=".MyMediaPlaybackService"
              android:foregroundServiceType="mediaPlayback"
              android:exported="false">
          </service>
        </application>
    </manifest>

     

    앱이 어떤 목적으로 Foreground Service를 사용하냐에 따라 달라집니다. 기존에는 android.permission.FOREGROUND_SERVICE 정도만 추가하면 되었지만, 이제 세부적인 기능에 대한 권한을 따로 추가해주어야 합니다. 주의할 것은 그렇다고 android.permission.FOREGROUND_SERVICE를 삭제하면 안됩니다. 구버전의 안드로이드는 해당 권한을 사용하니까요.

     

    권한 종류도 되게 많습니다. 맨 아래의 링크에 좀 더 자세하게 적혀있지만, 일단 눈에 띄는 유형들은 아래와 같습니다. 정말이지 무지막지하게 많네요.

    <manifest ...>
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_CAMERA" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_DATA_SYNC" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_HEALTH" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_LOCATION" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PROJECTION" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MICROPHONE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_PHONE_CALL" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_REMOTE_MESSAGING" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_TYPE_SHORT_SERVICE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SYSTEM_EXEMPTED" />
      
        <application ...>
          <service
              android:name=".MyMediaPlaybackService"
              android:foregroundServiceType="mediaPlayback"
              android:exported="false">
          </service>
        </application>
    </manifest>

     

     

     

    AndroidManifest.xml 파일에 서비스 등록하기

    사실 위에 이미 적어두긴 했지만, service를 등록할 때 예전과 달리 하나 추가해주어야 하는 속성이 생겼습니다. foregroundServiceType을 추가해야하는 것인데요. 아무래도 대체 왜 이 앱이 해당 Foreground Service를 어떤 목적으로 사용하는 지 사용자들에게 명시적으로 공개를 하기 위해서 추가하는 것인가 봅니다. 만약 MEDIA_PLAYBACK을 위해서 사용한다면 권한을 추가함에 더해 android:foregroundServiceType을 아래와 같이 적어주어야 합니다.

    <manifest ...>
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
    
        <application ...>
          <service
              android:name=".MyMediaPlaybackService"
              android:foregroundServiceType="mediaPlayback"
              android:exported="false">
          </service>
        </application>
    </manifest>

     

     

     

    Foreground Service를 시작할 때 타입 넘겨주기

    여기에 더해 startForeground를 할 때 권한에서 지정해주었던 타입에 맞춰서 새로운 상수를 함께 넘겨주어야 합니다. 아래와 같이 말이죠. 만약 모두에 적용하지 않고 혹시나를 위해 버전 별로 처리를 하고 싶다면 버전 별 분기 처리를 해주면 될 것입니다.

    // 요렇게 해도 되고
    startForeground(1, notification, FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
    // 요렇게 해도 됩니다.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK)
    } else {
        startForeground(1, notification)
    }

     

     

     

    예시 하나만 더 봅시다

    다른 애들은 타입 추가만 하면 되는데, SpeicalUse를 사용할 경우엔 아주 조오오금 다릅니다. 이 친구는 다른 애들과 같이 뭔가 명시적인 동작을 위해 사용하는 것이 아닌, 구글에서 정한 타입 외에 개발자가 사용하는 용도가 따로 있다면 사용하는 친구입니다.

    AndroidManifest.xml 파일에 아래와 같이 추가를 하는데, property에 android:name과 android:value를 추가해야 합니다. 이 때 android:value에 들어가는 값은, 진짜로 뭘 위해서 사용하는 지 말 그대로 설명을 적으라는 겁니다. "explanation_for_special_use"를 그대로 사용하는 게 아니에요! (그대로 사용해도 별 문제는 없을 것 같지만..) 파라미터 사용 방법은 다른 녀석들과 다르지 않습니다. 

    <manifest ...>
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
      <uses-permission android:name="android.permission.FOREGROUND_SERVICE_SPECIAL_USE" />
        <application ...>
          <service 
          	android:name="fooService" 
            android:foregroundServiceType="specialUse">
     	  	<property 
            	android:name="android.app.PROPERTY_SPECIAL_USE_FGS_SUBTYPE"
          		android:value="explanation_for_special_use"/>
    		</service>
        </application>
    </manifest>
    // 요렇게 해도 됩니다.
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
        startForeground(1, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_SPECIAL_USE)
    } else {
        startForeground(1, notification)
    }
     

    포그라운드 서비스 유형은 필수 항목임  |  Android Developers

    The Android 15 Beta is now available. Try it out today and let us know what you think! 이 페이지는 Cloud Translation API를 통해 번역되었습니다. 포그라운드 서비스 유형은 필수 항목임 컬렉션을 사용해 정리하기 내 환

    developer.android.com

     

     

     

     

    구글 플레이 콘솔에 업로드할 때

    여기서 끝나지 않았습니다. 구글 플레이 콘솔에 앱을 업로드하고 검토를 넣을 때 Foreground Service에 대한 선언을 해주어야 합니다.

    아마 검토를 넣을 때 빨갛게 에러 표시가 나면서 선언을 아직 안했다 어쩌구... 나올텐데, Foreground Service를 사용하는 방법에 대한 동영상 링크와 설명을 추가해서 검토를 넣으면 됩니다. 아래에서는 '정책' > '앱 콘텐츠' 에서 하라고 나와있긴 한데, 업로드할 때 해당 에러가 발생해서 바로 인지할 수 있으니까 일단 신경쓰지 말고 검토 넣어보세요! (어차피 이 때 안하면 검토 안됨 ㅎㅎ)

     

    혹시 만약에 google paly console API를 사용해서 자동 배포 및 검수를 하고 있는데 아래와 같은 에러 메세지가 노출된다면, 이걸 수동으로 안해서 그런 것입니다. API로 정책을 선언하는 방법이 있는 진 모르겠지만..

    Api Error: Invalide request - You must let us know whether tour app uses any Foreground Service permissions.?

     

    포그라운드 서비스 사용 선언하기

    Android 14 이상을 타겟팅하는 앱을 개발할 때는 Play Console의 앱 콘텐츠 페이지('정책' > '앱 콘텐츠')에서 새로운 선언을 통해 사용 중인 모든 포그라운드 서비스 유형을 선언해야 합니다. 이 과정에

    playacademy.exceedlms.com

     

    반응형
Designed and Written by keykat.