[Android] 알림 (Notification) 정리

Minjun Kim·2023년 8월 23일
0

Android

목록 보기
21/47
post-thumbnail

📝 스파르타코딩클럽의 '내일배움캠프' 지급 강좌를 정리한 글 입니다.


❗ Android 8.0 이상부터는 '알림 채널' 을 이용해서 알림을 만들어야 한다.

📚 알림 채널 이란?

알람을 그룹하여 알람 활성화나 방식을 변경할 수 있다.

Android 8.0(API 수준 26) 이상 적용이기 때문에 안드로이드 버전을 확인하여 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 버전 체크
        	// 채널 생성 - 채널 ID, 이름, 중요도가 들어간다
			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)
		}
	}

📚 알림 생성

1. NotificationCompat.Builder 객체에서 알림에 대한 UI 정보와 작업을 지정

  • setSmallIcon() : 작은 아이콘
  • setContentTitle() : 제목
  • setContentText() : 세부 텍스트

2. NotificationCompat.Builder.build() 호출

  • Notification 객체를 반환

3. NotificationManagerCompat.notify() 를 호출해서 시스템에 Notification 객체를 전달

  • showNotification()
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())
}

📌 알림 중요도

  1. 채널 중요도(Android 8.0이상)
  • NotificationChannel
    - channelID, "defaultchannel", NotificationManager.IMPORTANCE_DEFAULT
  1. 알림 우선순위(Android 7.1이하)
  • NotificationCompat.Builder(this,channelID).setPriority(NotificationCompat.PRIORITY_DEFAULT)

🧩 중요도 순위

중요도설명중요도(Android 8.0 이상)우선순위(Android 7.1 이하)
긴급알림음이 울림, 헤드업 알림 표시IMPORTANCE_HIGHPRIORITY_HIGH
높음알림음이 울림IMPORTANCE_DEFAULTPRIORITY_DEFAULT
중간알림음이 없음IMPORTANCE_LOWPRIORITY_LOW
낮음알림음이 없음, 상태 표시줄에 표시 안됨IMPORTANCE_MINPRIORITY_MIN

📚 알림 확장뷰 - 긴 텍스트

builder.setStyle(
			NotificationCompat.BigTextStyle()
				.bigText(resources.getString(R.string.long_notification_body))
		)


📚 알림 확장뷰 - 이미지

val bitmap = BitmapFactory.decodeResource(resources, R.drawable.android.test)
		val builder = NotificationCompat.Builder(this, channelID)
			.setSmallIcon(R.mipmap.ic_launcher)
			.setLargeIcon(bitmap)
			.setContentTitle("Notification Title")
			.setContentText("Notification body")
			.setPriority(NotificationCompat.PRIORITY_DEFAULT)
			.setStyle(
				NotificationCompat.BigPictureStyle()
					.bigPicture(bitmap)
					.bigLargeIcon((null))   // hide largeIcon while expanding
			)


📚 알림 확장뷰 - 버튼 추가

알림에 버튼을 추가하고 버튼을 누르면 Intent로 Activity나 Broadcast를 시작한다.

  • Action 버튼을 누르면 TextActivity가 시작된다.
val intent = Intent(this, TestActivity::class.java)
val pendingIntent = PendingIntent.getActivity(this, 0, intent, 0)
val builder = NotificationCompat.Builder(this, channelID)
	.setSmallIcon(R.mipmap.ic_launcher)
	.setLargeIcon(bitmap)
	.setContentTitle("Notification Title")
	.setContentText("Notification body")
	.setPriority(NotificationCompat.PRIORITY_DEFAULT)
	.addAction(R.drawable.android_test, "Action", pendingIntent)
NotificationManagerCompat.from(this).notify(myNotificationID, builder.build())


📚 알림 확장뷰 - 프로그래스바 추가

val builder = NotificationCompat.Builder(this, channelID)
	.setSmallIcon(R.mipmap.ic_launcher)
	.setContentTitle("Progress")
	.setContentText("In progress")
	.setProgress(100, 0, false)
	.setPriority(NotificationCompat.PRIORITY_DEFAULT)
NotificationManagerCompat.from(this).notify(myNotificationID, builder.build())

Thread {    // 스레드로 프로그래스바 업데이트
	for (i in (1..100).step(10)) {
		Thread.sleep(1000)
		builder.setProgress(100, i, false)
		NotificationManagerCompat.from(this)
			.notify(myNotificationID, builder.build())
	}
	builder.setContentText("Complete")
		.setProgress(0, 0, false)    // max = 0 이면 프로그래스바 사라짐
	NotificationManagerCompat.from(this)
		.notify(myNotificationID, builder.build())  // 같은 ID로 notify
}.start()


📚 알림에 액티비티 연결

알림을 터치하면 SecondActivity가 시작, 이때 MainActivity 위에 SecondActivity가 있는 백스택을 생성

  • AndroidManifest.xml
<activity
	android:name=".SecondActivity"
    android:parentActivityName=".MainActivity" />

  • PendingIntent 생성하고 알림 등록
val intent = Intent(this, SecondActivity::class.java)
val pendingIntent = with(TaskStackBuilder.create(this)) {
	addNextIntentWithParentStack(intent)
	getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT)
}
val builder = NotificationCompat.Builder(this, channelID)
	.setSmallIcon(R.mipmap.ic_launcher)
	.setContentTitle("Notification Title")
	.setContentText("Notification body")
	.setPriority(NotificationCompat.PRIORITY_DEFAULT)
    .setContentIntent(pendingIntent)
    .setAutoCancel(true)	// auto remove this notification when user touches it
NotificationManagerCompat.from(this).notify(myNotificationID, builder.build())
  • 알림을 터치 -> SecondActivity로 Intent -> 뒤로 가기 -> MainActivity로 이동

🧩 실습 예제

  • 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_second.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=".SecondActivity">

    <TextView
        android:id="@+id/textView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="두 번째 액티비티"
        android:textColor="#FF0000"
        android:textSize="25sp"
        android:textStyle="bold"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintEnd_toEndOf="parent"
        app:layout_constraintStart_toStartOf="parent"
        app:layout_constraintTop_toTopOf="parent" />
</androidx.constraintlayout.widget.ConstraintLayout>


  • MainActivity.kt
package com.example.test

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()
		}
	}

	@SuppressLint("NotificationPermission")
	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.img6)
		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())
	}
}
profile
응애 나 아기 뉴비

0개의 댓글