Skip to content

안드로이드 백그라운드 위치 권한 요청 심사 관련 개발 상세 가이드

앞서 설명한 내용들의 세부 설명으로 loplat SDK (v2.1.1.6.4 이상) 탑재 시 알아야할 개발 사항들과 기타 주의사항들이 포함되어 있습니다.

아래의 모든 Plengi 설정 api 들은 반드시 Application.onCreate()에서 호출해야 합니다.

  • 백그라운드 위치 정보 액세스 내용 공개 :

    • (방안1) 앱 자체적으로 ‘위치권한- 항상 허용' 을 받는 기능을 구현할 수 있습니다.

    자체 구현할 경우 아래의 내용을 모두 구현해야 합니다.

    1. 심사를 위한 UI와 현재 위치 권한 레벨에 맞는 추가 권한 요청 로직을 방안2의 내용을 참고하여 직접 구현해야 합니다.
      자세한 내용은 안드로이드 개발자 사이트를 확인 부탁드립니다. https://developer.android.com/training/location/permissions

    2. 로플랫이 제공하는 항상허용 프롬프트를 사용하지 않도록 아래와 같이 Application.onCreate()에서 Plengi.disableFeatureBgLocationReviewUX(true)를 선언해야 합니다.

// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
Plengi plengi = Plengi.getInstance(context);
plengi.disableFeatureBgLocationReviewUX(true);
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
val plengi = Plengi.getInstance(context)
plengi.disableFeatureBgLocationReviewUX(true)
  • (방안2) loplat SDK에서 제공되는 '위치권한-항상 허용 프롬프트'를 사용하여 '위치권한-항상 허용' 을 받을 수 있습니다.

방안2의 장점

방안2는 Android11에서도 지속적인 위치 수집에 대한 대응이 포함되어 있습니다. 사용자가 위치 권한을 앱 사용중으로 하더라도 위치 항상허용을 설명을 통해 독려할 수 있고 사용자가 위치 권한을 항상 허용으로 하지 않고 알림을 닫더라도 지속적인 위치 수집이 가능합니다. 또한 심사에 필요한 UI를 쉽게 추가하는 API를 제공하며 상황에 맞게 위치 권한을 요청하는 프롬프트가 미리 구현되어 있습니다.

loplat SDK ‘위치권한-항상허용 프롬프트’ (아래 이미지)

방안2 적용 시 각 프롬프트 상세 및 커스터마이즈 방법 설명

프롬프트 1. loplat SDK가 백그라운드 위치 권한 액세스에 대한 알림을 아래와 같이 출력합니다.

  • 알림의 Icon, Title (주변 혜택 찾기 서비스 알림), Text (눌러서 알림 설정 > 알림 OFF 하기) 를 변경하려면 Plengi.setDefaultNotificationInfo 를 호출해야 합니다. 알림의 앱 이름은 loplat이 아닌 loplat SDK가 탑재될 앱의 이름으로 출력됩니다.
1
2
3
4
5
6
7
8
9
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
Plengi plengi = Plengi.getInstance(context);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    plengi.setDefaultNotificationInfo(
        R.drawable.noti_small_icon,
        R.string.noti_title,
        R.string.noti_text
    );
}
1
2
3
4
5
6
7
8
9
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
val plengi = Plengi.getInstance(context)
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    plengi.setDefaultNotificationInfo(
        R.drawable.noti_small_icon,
        R.string.noti_title,
        R.string.noti_text
    )
}
  • 해당 알림자체를 Custom 하려면 사용할 알림을 생성한 뒤 Plengi.setDefaultNotificationInfo() 를 호출해야합니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
// 알림부터 시작되는 전체 플로우를 customizing
Intent intent = new Intent(context, 알림 클릭  보여줄 액티비티.class);
PendingIntent contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE);

Plengi plengi = Plengi.getInstance(context);

/* NotificationCompat.Builder의 두 번째 param 값은 반드시 
Plengi.getDefaultNotificationChannelId() 를 사용해 주세요. */
Notification notification = new NotificationCompat.Builder(this, plengi.getDefaultNotificationChannelId())
    .setContentTitle("알림 제목")
    .setContentText("알림 내용")
    .setContentIntent(contentIntent)
    ...

    .build();

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    plengi.setDefaultNotificationInfo(notification);
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
// 알림부터 시작되는 전체 플로우를 customizing
val intent = Intent(context: Context, 알림 클릭  보여줄 액티비티.class)
val contentIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_MUTABLE)

val plengi = Plengi.getInstance(context)

/* NotificationCompat.Builder의 두 번째 param 값은 반드시 
Plengi.getDefaultNotificationChannelId() 를 사용해 주세요 */
val notification = NotificationCompat.Builder(this, plengi.getDefaultNotificationChannelId())
         .setContentTitle("알림 제목")
         .setContentText("알림 내용")    
         .setContentIntent(contentIntent)
         ...
         
         .build()

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {      
    plengi.setDefaultNotificationInfo(notification)
}

프롬프트 2. loplat SDK생성한 백그라운드 위치 권한 액세스에 대한 알림을 클릭하면 아래와 같은 화면을 출력합니다.

  • 위치 권한 변경’ 버튼을 클릭하면 **백그라운드 위치 정보 액세스 내용 공개**를 위한 대화상자를 출력합니다.
  • '알림 설정변경' 버튼을 통해 알림을 OFF할 수 있고 OFF한 경우에도 위치 권한이 있다면 지속적인 위치 획득이 가능합니다.
  • 대화상자의 안내 문구 (안드로이드 정책에 따른 위치 기반 ... … 설정에서 알림을 해제할 수 있습니다.) 를 변경하려면 Plengi.setDefaultNotificationChannel() 를 호출해야 합니다.
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
Plengi plengi = Plengi.getInstance(context);

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    plengi.setDefaultNotificationChannel(
        // Loplat SDK의 기본 값을 사용하려면 0
        R.string.channel_name,
        // Loplat SDK의 기본 값을 사용하려면 0
        R.string.channel_description,
        // Loplat SDK의 기본 값을 사용하려면 0
        R.string.guide_description
    );
}
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
val plengi = Plengi.getInstance(context)

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    plengi.setDefaultNotificationChannel(
        // Loplat SDK의 기본 값을 사용하려면 0
        R.string.channel_name,
        // Loplat SDK의 기본 값을 사용하려면 0
        R.string.channel_description,
        // Loplat SDK의 기본 값을 사용하려면 0
        R.string.guide_description
    )
}
  • 대화상자의 Title(설정 변경 안내), 버튼(위치 권한 변경, 알림 설정 변경) 들은 변경이 불가능 합니다.

프롬프트 3. 백그라운드 위치 정보 액세스 내용 공개를 위한 대화상자를 아래와 같이 출력합니다.

기본 대화상자 Custom Layout 대화상자
  • loplat SDK가 기본적으로 제공하는 대화상자가 아닌 Custom Layout을 사용하길 원한다면 Plengi.setBackgroundLocationAccessDialogLayout()을 아래와 같이 Application.onCreate()에서 선언해야 합니다.
1
2
3
4
5
6
7
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
Plengi plengi = Plengi.getInstance(context);

// 백그라운드 위치 심사를 위한 Prompt dialog layout
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    plengi.setBackgroundLocationAccessDialogLayout(R.layout.custom_dialog)
}
1
2
3
4
5
6
7
// Plengi 설정 api들(커스텀 알림 설정,PlengiListener)은 반드시 Application.onCreate()에서 호출해야 합니다.
val plengi = Plengi.getInstance(context)

// 백그라운드 위치 심사를 위한 Prompt dialog layout
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
    plengi.setBackgroundLocationAccessDialogLayout(R.layout.custom_dialog)
}
  • Custom Layout을 사용할 경우 위 Custom Layout 대화상자 이미지와 같이 출력됩니다. "취소 / 확인" 버튼을 제외한 Layoutset 해주시면 됩니다. 이미지는 필수가 아니며 자사 캐시플레이스 앱의 경우 가독성을 높이기 위하여 추가했습니다.
  • Custom Layout을 사용할 경우 문구에는 아래과 같은 요소들이 포함되어야 합니다.
    1. '위치' 라는 용어
    2. '백그라운드'/'앱이 닫힐 때'/'항상 사용 중'/'앱이 사용되지 않을 때' 중 하나를 사용하여 사용의 성격이 백그라운드에 있다는 것을 표현 ex) "이 앱을 사용하고 있지 않을 때도"
    3. 백그라운드에서 위치를 사용하는 모든 기능 목록 ex) "주변 혜택을 사용자에게 알려주기 위해"
    4. 사용 허용 범위를 광고로 확장하는 경우 다음 문구를 포함해야 합니다. '이 데이터는 광고를 제공/광고 기능을 지원/광고를 지원하기 위해서도 사용됩니다.' ex) "이 데이터는 광고를 제공하기 위해서도 사용 됩니다."

프롬프트 4. 백그라운드 위치 권한을 요청합니다.

2. 구글 플레이 스토어에서 설명해야 하는 사항

구글 플레이 스토어 앱 정보에서 백그라운드 위치 정보 액세스 내용 표기 :

  • 앱 설명에 백그라운드 위치 정보 액세스를 명확히 표시해야 합니다.
    ex) 캐시플레이스는 사용자의 현재 위치를 기반으로 매장 정보 수집 안내 및 혜택 알림을 제공하기 위해 앱이 닫혀있을 때나 사용되지 않을 때도 위치 데이터를 수집합니다. 또한 이 데이터는 광고를 지원하기 위해서도 사용됩니다.

  • 휴대전화 스크린샷에 백그라운드 위치 정보 액세스 관련 앱 스크린샷을 추가해야 합니다.

    (확대 이미지)

3. 구글 플레이 심사시 제공해야 하는 사항

데모영상 제공 :

  • 데모 영상에는 아래 항목들이 모두 포함되어 있어야 합니다.
    • foregrouns service notification이 나타난 장면
    • RunTime Prompt
    • 사용자에게 표시되는 명시적인 인앱 공개 백그라운드 위치 권한 액세스 대화상자
    • 백그라운드에서 활성화 되는 기능 (Loplat X의 캠페인 기능)
  • 권장 동영상 길이는 30초 이내입니다. YouTube 링크가 선호되는 동영상 형식이지만 mp4나 다른 일반적인 동영상 파일 형식으로 연결되는 클라우드 스토리지 링크도 지원됩니다. (자사 캐시플레이스 데모 영상)

구글 플레이 콘솔 → 메인메뉴 → 정책 → 앱 콘텐츠 → 민감한 권한 및 API → 관리 → 위치 정보 액세스 권한 :

  • 이 설정에서 정책 준수 선택에 따라 심사가 진행됩니다. ‘아니요’ 설정할 경우 백그라운드 위치 권한 액세스 여부와는 상관없이 승인 일정 내에는 심사 전과 동일하게 앱 업데이트가 가능합니다. '' 로 설정하여 심사를 진행할 경우 아래와 같은 질문에 답변 및 데모 영상을 확인할 수 있는 링크를 제공해야 합니다.

  • 2가지 질문에 대해 답변해야 합니다.

    • 앱의 주요 목적은 무엇인가요?

      예시 답변 : 캐시플레이스는 지오펜싱을 활용하여 사용자의 현재 위치를 기반으로 다양한 혜택과 광고를 제공하며, 편의점, 카페, 음식점 등등 사용자 주변에 있는 다양한 오프라인 매장의 데이터를 수집하고, 사용자에게 수집한 매장마다 일정 리워드를 제공하는 앱입니다. 캐시플레이스를 이용하기 위해선 카카오톡 서비스에 계정이 있고 대한민국에 위치하고 있어야 합니다. 사용자는 현재 위치 주변, 원하는 매장에 들어가 매장 중앙에서 사진 2장을 찍어 해당 매장을 수집 완료할 수 있습니다.

    • 앱에 백그라운드 위치 정보 액세스 권한이 필요한 이유는 무엇인가요?

      예시 답변 : 캐시플레이스 어플리케이션은 지오펜싱과 유사한 방식으로 사용자의 위치를 주기적으로 확인하여 특정 매장 방문 여부를 인식하고, 해당 매장에 적합한 혜택이나 광고를 사용자에게 제공합니다. 예를 들어 캐시플레이스 사용자가 앱을 사용하고 있지 않을 때도 특정 브랜드의 매장에 입장 했을 때 해당 매장에서 이용할 수 있는 포인트 상품들 혹은 진행 중인 행사나 이벤트들을 알림으로 알려줍니다. 캐시플레이스 앱을 사용 중이지 않을 때도 사용자의 위치에 맞는 정확한 혜택 및 광고를 제공하기 위해서 백그라운드 위치 정보 액세스 권한이 필요합니다.

  • 데모 영상의 링크를 추가합니다.

구글 플레이 콘솔 테스트 계정 사용자 인증 정보 제공

앱에 로그인 화면이 있고 크롤러가 로그인 프로세스 또는 로그인 후 제공되는 콘텐츠를 테스트하도록 하려면 계정 사용자 인증 정보를 제공해야 합니다.

  • 참고: 사용자 인증 정보는 표준 Android 위젯을 사용하는 Android 앱에만 자동으로 삽입할 수 있습니다. OpenGL을 사용하여 맞춤 컨트롤을 렌더링하는 앱 또는 웹 기반의 인증 절차로 WebView를 사용하는 앱에는 사용자 인증 정보를 사용할 수 없습니다.

(Android 14 이상을 타켓팅하는 경우) 구글 플레이 콘솔 → 메인메뉴 → 정책 → 앱 콘텐츠 → 포그라운드 서비스 권한 -> 관리 :

loplat SDK는 foreground_service_location 권한을 사용하고 있고, 구글 플레이 정책에 따라 앱 배포 시 foreground service를 어떻게 사용하는지 설명하는 영상을 첨부해야 합니다. (정책 문서)

다음 내용은 안드로이드 개발자 사이트에서 안내하고 있는 내용과 영상 첨부 방법입니다.

if the app targets API level 34 or higher, it must request the appropriate permission type for the kind of work the foreground service will be doing. 
Each foreground service type has a corresponding permission type.
For example, if an app launches a foreground service that uses the camera, you must request both the FOREGROUND_SERVICE and FOREGROUND_SERVICE_CAMERA permissions.
These are all normal permissions, so the system grants them automatically if they're listed in the manifest.

  • ‘백그라운드 위치 정보 업데이트 > 기타’를 선택하고 데모 영상의 링크를 추가합니다.


참조

‘위치-계속 유지 및 다시 묻지 않음’ 권한에 대한 프롬프트(Android 10 이하)

사용자가 ‘위치-항상 허용' 권한 요청 시 "계속 유지 및 다시 묻지 않음" 권한을 선택한 경우, 이를 예외처리하여 ‘위치-항상 허용’ 권한이 필요한 상황에 앱의 설정화면으로 이동할 수 있게끔 가이드 합니다.