앱의 UI와 별도로 사용자에게 앱과 관련한 정보를 보여주는 기능
알림을 터치하여 해당 앱을 열 수 있다
보통 단말기 상단 부분에 표시되고, 앱 아이콘의 배지로도 표시(Android 8.0부터)
Android 8.0이상의 경우는 알림을 만들기 전에 알림 채널을 먼저 만들어야함
알림 채널은 알림을 그룹하여 알림 활성화나 방식을 변경 할 수 있음
현재 앱이 실행 중인 안드로이드 버전을 확인하여 8.0이상인 경우만 채널 생성
private val myNotificationID = 1
private val channelID = "default"
private fun createNotificationChannel() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) { // Android 8.0
val channel = NotificationChannel(channelID, "default channel",
NotificationManager.IMPORTANCE_DEFAULT)
channel.description = "description text of this channel."
val notificationManager = getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
notificationManager.createNotificationChannel(channel)
}
}
setSmallIcon() : 작은 아이콘
setContentTitle() : 제목
setContentText() : 세부텍스트
Notification객체를 반환
private val myNotificationID = 1
private fun showNotification() {
val builder = NotificationCompat.Builder(this, channelID)
.setSmallIcon(R.mipmap.ic_launcher)
.setContentTitle("title")
.setContentText("notification text")
.setPriority(NotificationCompat.PRIORITY_DEFAULT)
NotificationManagerCompat.from(this).notify(myNotificationID, builder.build())
}
NotificationChannel
NotificationCompat.Builder(this,channelID).setPriority(NotificationCompat.PRIORITY_DEFAULT)
긴 텍스트은 어떻게 들어갈까?
그림 넣으면?
버튼 시작
알림 생성과 등록
알림을 터치하면 어떻게 될까?
알림은 사라지고, SecondActivity가 실행됨
SecondActivity가 실행 된 상태에서 Back이나 Up을 누르면 MainActivity가 나옴
사실 MainActivity가 이미 백스택에 있기 때문에 TaskStackBuilder로 백스택을 조작하지 않아도 동일하게 동작
백스택에 없는 다른 액티비티를 SecondActivity의 parentActivity로 하면 달라짐
activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout
xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<Button
android:id="@+id/notificationButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="알림 보내기"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>
두번째 Activity생성
File > New > Activity > Empty Activity
Activity Name : SecondActivity
activity_second.xml 에 “두번째 액티비티” 문구의 TextView 추가
MainActivity.kt
class MainActivity : AppCompatActivity() {
private val binding by lazy { ActivityMainBinding.inflate(layoutInflater) }
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(binding.root)
binding.notificationButton.setOnClickListener{
notification()
}
}
fun notification(){
val manager = getSystemService(NOTIFICATION_SERVICE) as NotificationManager
val builder: NotificationCompat.Builder
if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.O){
// 26 버전 이상
val channelId="one-channel"
val channelName="My Channel One"
val channel = NotificationChannel(
channelId,
channelName,
NotificationManager.IMPORTANCE_DEFAULT
).apply {
// 채널에 다양한 정보 설정
description = "My Channel One Description"
setShowBadge(true)
val uri: Uri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION)
val audioAttributes = AudioAttributes.Builder()
.setContentType(AudioAttributes.CONTENT_TYPE_SONIFICATION)
.setUsage(AudioAttributes.USAGE_ALARM)
.build()
setSound(uri, audioAttributes)
enableVibration(true)
}
// 채널을 NotificationManager에 등록
manager.createNotificationChannel(channel)
// 채널을 이용하여 builder 생성
builder = NotificationCompat.Builder(this, channelId)
}else {
// 26 버전 이하
builder = NotificationCompat.Builder(this)
}
val bitmap = BitmapFactory.decodeResource(resources, R.drawable.flower)
val intent = Intent(this, SecondActivity::class.java)
intent.flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_ACTIVITY_CLEAR_TASK
val pendingIntent = PendingIntent.getActivity(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE)
// 알림의 기본 정보
builder.run {
setSmallIcon(R.mipmap.ic_launcher)
setWhen(System.currentTimeMillis())
setContentTitle("새로운 알림입니다.")
setContentText("알림이 잘 보이시나요.")
setStyle(NotificationCompat.BigTextStyle()
.bigText("이것은 긴텍스트 샘플입니다. 아주 긴 텍스트를 쓸때는 여기다 하면 됩니다.이것은 긴텍스트 샘플입니다.
아주 긴 텍스트를 쓸때는 여기다 하면 됩니다.이것은 긴텍스트 샘플입니다. 아주 긴 텍스트를 쓸때는 여기다 하면 됩니다."))
setLargeIcon(bitmap)
// setStyle(NotificationCompat.BigPictureStyle()
// .bigPicture(bitmap)
// .bigLargeIcon(null)) // hide largeIcon while expanding
addAction(R.mipmap.ic_launcher, "Action", pendingIntent)
}
manager.notify(11, builder.build())
}
}
안드로이드에서 알림(Notification)은 사용자에게 정보를 전달하는 중요한 수단. 안드로이드 12(API 레벨 33)부터, 알림을 보내기 위한 권한 시스템에 변화가 생김. 개발자는 이제 알림을 보내기 위해 POST_NOTIFICATIONS 권한을 앱의 매니페스트 파일에 명시적으로 추가해야함
AndroidManifest.xml
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp">
<!-- API 33 이상을 위한 알림 권한 추가 -->
<uses-permission android:name="android.permission.POST_NOTIFICATIONS" />
...
</manifest>
이 변경은 사용자의 프라이버시를 강화하고, 앱이 사용자의 동의 없이 알림을 보내는 것을 방지하기 위함. API 레벨 33 이상에서 앱을 개발하거나 업데이트할 때는 매니페스트에 이 권한을 추가해야 하며, 사용자는 앱 설치 후 처음 알림을 수신할 때 이 권한을 부여할지 결정하는 대화상자를 볼 수 있음.
앱이 실행 중일 때 사용자에게 알림 권한을 요청하기 위해, 다음과 같은 코드를 사용 가능
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU) {
if (!NotificationManagerCompat.from(this).areNotificationsEnabled()) {
// 알림 권한이 없다면, 사용자에게 권한 요청
val intent = Intent(Settings.ACTION_APP_NOTIFICATION_SETTINGS).apply {
putExtra(Settings.EXTRA_APP_PACKAGE, packageName)
}
startActivity(intent)
}
}
이 코드는 사용자의 기기가 API 33 이상인지 확인한 후, 알림이 활성화되어 있는지를 검사하고, 권한이 없을 경우 설정 화면으로 사용자를 안내. 알림 권한 요청은 사용자 경험을 고려하여 적절한 시점에 수행해야 하며, 사용자가 알림의 가치를 이해할 수 있도록 설득력 있는 메시지를 제공해야함