반응형
안드로이드13에서 Notification에 대해 바뀐점
- POST_NOTIFICATIONS (Notification Permission) 은 Target SDK API 33 이상부터 추가 가능
- Target SDK API 32 이하의 앱이 Android 13 디바이스에 설치되면 Notification Channel을 등록할 때 자동으로 Notification 권한 요청 팝업이 나옴
- Target SDK API 33 이상의 앱이 Android 13 디바이스에 설치되면 Notification 권한요청을 개발자가 원하는 타이밍에 노출 가능
- Target SDK API 33 이상의 앱이 Android 12 이하 디바이스에 설치되면 기존과 동일하게 Notification 권한 요청 없이 사용 가능
- Target SDK API 32 앱을 33으로 업데이트 시 기존 알림 권한 동의 상태라면 업데이트 이후 기본으로 허용이지만 예외 있음
- 기기에따라 자동으로 허용되지 않고 다시 한 번 권한을 얻어야하는 경우가 있음
- 그렇기 때문에 Notification 권한이 허가되어 있는지 한 번 확인하는 작업을 넣기를 권장함
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
Notification 권한 허용 팝업에 대한 주의 사항
- API 32 이하 앱의 경우, 시스템이 자동으로 퍼미션 팝업을 띄웠을 때, 사용자가 Don't allow 버튼을 한번 누르면, 앱이 재시작해도 팝업이 발생하지 않습니다.
- API 33 이상 앱의 경우, 앱이 퍼미션 팝업을 띄웠을 때, 사용자가 Don't allow 버튼을 두 번 누르기 전까지 퍼미션 팝업을 계속 띄울 수 있습니다.
- 사용자가 Don't allow 버튼을 눌러서 더 이상 팝업을 띄울 수 없다면 사용자가 직접 앱 설정에 들어가서 권한을 허가해줘야합니다.
Notification 권한 요청이 필요한 앱이라고 등록하기
AndroidManifest.xml
<manifest ...>
<uses-permission android:name="android.permission.POST_NOTIFICATIONS"/>
<application ...>
...
</application>
</manifest>
- AndroidManifest.xml에 위 권한을 추가한다.
- Sync proejct with gradle files를 실시한다
compileSdk 33 로 변경하기
- 앱 단위의 build.gradle의 compileSdk을 33으로 변경해야한다
- 똑같이 targetSdk도 33으로 변경이 필요하다
android {
compileSdk 33
defaultConfig {
applicationId "com.example.selftest"
minSdk 23
targetSdk 33
versionCode 1
versionName "1.0"
testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
}
Notification 정의 하기
- Notification의 Channel 정의 및 Builder 정의하기
- SDK 26 이상 버전부터는 Channel을 정의해야만 Notification을 사용할 수 있다
- Builder를 통해 Notification을 보낸다
fun makeAlarmNotification(context: Context, messageBody: String) {
Timber.d("make notification")
// notification 클릭 시 MainActivity를 열게 한다
val intent = Intent(context, MainActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_CLEAR_TASK or Intent.FLAG_ACTIVITY_NEW_TASK
val pendingIntent = PendingIntent.getActivity(
context, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE
)
// notification의 channel id를 정의한다
val channelId = "channel1"
val channelName = "channel name"
// notification를 정의한다
val notificationBuilder = NotificationCompat.Builder(context, channelId)
.setSmallIcon(R.drawable.ic_bottom_menu_search)
.setContentTitle("notification title")
.setContentText(messageBody)
.setAutoCancel(false) // 전체 삭제해도 안되게하기
.setSound(null)
.setContentIntent(pendingIntent)
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
.setOngoing(true) // 알람이 계속 뜬 상태로 있게하기
// 정의한 내용과 channel을 사용하여 notification을 생성한다
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
// Android SDK 26 이상에서는 notification을 만들 때 channel을 지정해줘야 한다
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
)
notificationManager.createNotificationChannel(channel)
}
// notification 띄우기
notificationManager.notify(100, notificationBuilder.build())
}
Notification 권한 얻기
안드로이드13 이상에서 Notification을 출력하기 위해서는 권한을 요구하고
권한을 얻어야만 출력할 수 있다
Notification의 권한은 다음과 같은 방법으로 얻을 수 있다.
FirstFragment.kt
버튼을 눌렀을 때 Notification 권한 요청이 나오게 한다
class FirstFragment : Fragment() {
companion object {
const val DENIED = "denied"
const val EXPLAINED = "explained"
}
private var binding: FragmentFirstBinding by autoCleared()
// 권한 요청용 Activity Callback 객체 만들기
private val registerForActivityResult = registerForActivityResult(ActivityResultContracts.RequestMultiplePermissions()) { permissions ->
val deniedPermissionList = permissions.filter { !it.value }.map { it.key }
when {
deniedPermissionList.isNotEmpty() -> {
val map = deniedPermissionList.groupBy { permission ->
if (shouldShowRequestPermissionRationale(permission)) DENIED else EXPLAINED
}
map[DENIED]?.let {
// 단순히 권한이 거부 되었을 때
}
map[EXPLAINED]?.let {
// 권한 요청이 완전히 막혔을 때(주로 앱 상세 창 열기)
}
}
else -> {
// 모든 권한이 허가 되었을 때
}
}
}
override fun onCreateView(
inflater: LayoutInflater, container: ViewGroup?,
savedInstanceState: Bundle?
): View {
binding = FragmentFirstBinding.inflate(inflater, container, false)
return binding.root
}
override fun onViewCreated(view: View, savedInstanceState: Bundle?) {
super.onViewCreated(view, savedInstanceState)
binding.button.setOnClickListener {
val action = FirstFragmentDirections.actionFirstFragmentToThirdFragment()
findNavController().navigate(action)
}
// 버튼을 클릭했을 때 Notification 권한 요청하기
binding.freeButton.setOnSingleClickListener {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
registerForActivityResult.launch(
arrayOf(Manifest.permission.POST_NOTIFICATIONS)
)
}
makeAlarmNotification(requireContext(), "notification")
}
}
}
위 방법은 Fragment 뿐 아니라 Activity에서도 똑같이 사용할 수 있다
요약
- 기존의 앱의 경우에는 Notification Channel을 등록할 때 자동으로 권한을 요구하는 창이 뜬다
- 단, 이 단계에서 허락하지 않을 경우 두 번 다시 권한을 요구하지 못한다
- 새롭게 SDK 33 이상을 Target으로 지정했다면 반드시 권한을 요구하는 기능을 넣어야한다
반응형
'안드로이드(kotlin)' 카테고리의 다른 글
안드로이드 OutOfMemoryError: Java heap space 오류 해결 방법 (0) | 2023.02.04 |
---|---|
안드로이드 라이브러리 만들고 jitpack으로 배포하기 (0) | 2023.01.29 |
registerForActivityResult 사용 방법과 startActivityForResult가 Deprecated된 이유 (2) | 2023.01.07 |
리사이클러뷰의 생명주기 분석 및 메모릭의 원인 (0) | 2023.01.05 |
Navigation을 사용한 화면 이동 시 라이프사이클 변화 (0) | 2022.12.24 |
"이 포스팅은 쿠팡 파트너스 활동의 일환으로, 이에 따른 일정액의 수수료를 제공받습니다."
댓글