이 페이지에서는 시계에 관한 알림을 만드는 방법을 설명합니다. 또한 연결된 스마트폰에서 시계에 연결된 각 알림에 관해 추가 콘텐츠를 제공하는 방법을 설명합니다.
시계의 알림은 스마트폰의 알림과 동일한 구조입니다. 또한 사용자에게 최적의 환경을 제공하기 위해 Wear OS by Google은 웨어러블 관련 기능을 알림에 추가하기 위한 API를 제공합니다.
앱에서 내보내는 각 알림은 알림 스트림에 카드로 나타납니다.

그림 1. 스마트폰과 시계에 표시된 동일한 알림
시계와 스마트폰 모두 알림의 소스가 될 수 있습니다. NotificationCompat.Builder
클래스를 사용하여 웨어러블 기기용 알림을 만듭니다. 이 클래스를 사용하여 알림을 만들면 시스템에서 알림을 올바르게 표시합니다.
참고: RemoteViews
를 사용하는 알림에서는 맞춤 레이아웃이 제거되어, 웨어러블에는 텍스트와 아이콘만 표시됩니다. 그러나 시계에서 실행되는 웨어러블 앱을 만들어 맞춤형 카드 레이아웃을 사용하는 맞춤형 알림을 만들 수 있습니다.
일반적으로 모든 알림은 스마트폰에서 시계로 연결됩니다. 하지만 다음과 같은 경우에는 알림이 연결되지 않습니다.
Notification.Builder.setLocalOnly(boolean)
을 사용하여 설정된 '로컬 전용' 알림Notification.Builder.setOngoing(boolean)
또는Notification.FLAG_ONGOING_EVENT
를 사용하여 설정된 지속적 알림Notification.FLAG_NO_CLEAR
를 사용하여 설정된 지울 수 없는 알림- 상대 웨어러블 앱에서 알림 브리지를 사용하지 않는 알림
필요한 클래스 가져오기
필요한 패키지를 가져오려면 build.gradle
파일에 다음 줄을 추가합니다.
implementation 'androidx.core:core:1.2.0'
이제 프로젝트가 필요한 패키지에 액세스할 수 있으므로 지원 라이브러리에서 필요한 클래스를 가져옵니다.
Kotlin
import androidx.core.app.NotificationCompat import androidx.core.app.NotificationManagerCompat import androidx.core.app.NotificationCompat.WearableExtender
자바
import androidx.core.app.NotificationCompat; import androidx.core.app.NotificationManagerCompat; import androidx.core.app.NotificationCompat.WearableExtender;
알림 빌더로 알림 만들기
Jetpack Core 라이브러리를 사용하면 작업 버튼과 아이콘과 같은 최신 알림 기능을 사용하여 알림을 만들면서 Android 1.6(API 수준 4) 이상과의 호환성을 그대로 유지할 수 있습니다.
참고: Android 8.0(API 수준 26)부터는 표시하고자 하는 각 알림 유형에 관해 알림 채널을 만들어야 합니다.
알림을 만들려면 다음 단계를 따르세요.
NotificationCompat.Builder
인스턴스를 생성합니다.Kotlin
val notificationId = 1 // The channel ID of the notification. val id = "my_channel_01" // Build intent for notification content val viewPendingIntent = Intent(this, ViewEventActivity::class.java).let { viewIntent -> viewIntent.putExtra(EXTRA_EVENT_ID, eventId) PendingIntent.getActivity(this, 0, viewIntent, 0) } // Notification channel ID is ignored for Android 7.1.1 // (API level 25) and lower. val notificationBuilder = NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent)
자바
int notificationId = 001; // The channel ID of the notification. String id = "my_channel_01"; // Build intent for notification content Intent viewIntent = new Intent(this, ViewEventActivity.class); viewIntent.putExtra(EXTRA_EVENT_ID, eventId); PendingIntent viewPendingIntent = PendingIntent.getActivity(this, 0, viewIntent, 0); // Notification channel ID is ignored for Android 7.1.1 // (API level 25) and lower. NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent);
- 알림 ID가 있는 알림 객체를
notify()
에 전달하여 알림을 생성합니다.Kotlin
NotificationManagerCompat.from(this).apply { notify(notificationId, notificationBuilder.build()) }
자바
// Get an instance of the NotificationManager service NotificationManagerCompat notificationManager = NotificationManagerCompat.from(this); // Issue the notification with notification manager. notificationManager.notify(notificationId, notificationBuilder.build());
스마트폰에 이 알림이 표시되면 사용자는 setContentIntent()
메서드로 지정된 PendingIntent
를 알림 터치를 통해 호출할 수 있습니다. 이 알림이 웨어러블에 나타나면 알림 스트림에도 나타납니다. 연결된 알림의 경우 사용자는 알림을 클릭하여 확장된 알림을 보고 열기 작업과 같은 정의된 작업을 트리거할 수 있습니다. 대개 이러한 작업이 이루어지면 전화 앱에서 활동이 열립니다.
확장된 알림 구성
확장된 알림은 각 알림에 관한 실질적인 추가 콘텐츠 및 작업을 제공합니다. 알림에 관한 추가 콘텐츠 페이지 및 작업을 지정하면, 확장된 알림 내에서 사용자가 이를 이용할 수 있습니다. 확장된 각 알림은 Wear OS용 머티리얼 디자인을 따르므로 사용자에게 앱과 같은 환경이 제공됩니다.
확장된 알림의 첫 번째 작업에 RemoteInput
(예: 답장 작업)이 있으면 setChoices()
로 설정한 선택 사항이 확장된 알림의 첫 번째 작업 아래에 표시됩니다.
사용자는 다음 중 하나가 참일 경우 알림을 탭하여 확장된 알림을 볼 수 있습니다.
- 알림이 페어링된 스마트폰에서 앱에 의해 생성되어 Wear에 연결됩니다.
- 알림에
contentIntent
가 없습니다.
참고: setColor()
메서드로 알림에 관해 설정한 앱 관련 배경색은 알림을 확장할 경우에만 표시됩니다.
확장된 알림의 권장사항
확장된 알림을 사용할 시기를 결정하려면 다음 지침을 따르세요.
- 페어링된 스마트폰에서 Wear 기기에 연결된 모든 알림은 확장된 알림을 사용합니다.
-
Wear에서 로컬로 실행되는 앱을 통해 알림이 생성되는 경우,
setContentIntent()
를 호출하여 알림의 터치 타겟이 앱 내에서 알림 ID가 있는 알림 객체를 시작하도록 해야 합니다. Wear에서 로컬로 실행되는 앱에 의해 생성된 알림에 관해서는 확장된 알림을 사용하지 않는 것이 좋습니다.
확장된 알림 추가
확장된 알림을 사용하면 알림에 관해 추가 콘텐츠 및 작업을 포함할 수 있습니다. 앱의 알림에서 제공할 세부정보의 수준을 선택할 수 있습니다. 그러나 알림에 포함할 세부정보의 양을 신중하게 조정해야 합니다.

추가 콘텐츠 포함
확장된 알림에 추가 텍스트를 표시하려면 BigTextStyle
을 사용합니다.
확장된 알림에서 이미지를 추가하려면 BigPictureStyle
을 사용하면 됩니다. 확장된 알림에서 이미지를 두 개 이상 추가하려면 BigPictureStyle
과 함께 addPage()
메서드를 사용합니다.
기본 작업
확장된 알림에는 기본 작업이 한 개 포함됩니다. setContentAction()
을 사용하여 다른 작업을 지정하지 않는 한 이것이 알림의 첫 번째 작업입니다.
추가 작업
추가 작업을 지정하려면 addAction()
또는 addActions()
를 사용합니다.
확장된 알림의 작업 창에는 사용 가능한 모든 작업이 포함됩니다.
알림 작업 추가
setContentIntent()
로 정의한 기본 콘텐츠 작업 외에도 PendingIntent
를 addAction()
메서드에 전달하여 다른 작업을 추가할 수 있습니다.
예를 들어 다음 코드는 위와 동일한 알림 유형을 표시하지만, 지도에 이벤트 위치를 표시하는 작업을 추가합니다.
Kotlin
// Build an intent for an action to view a map val mapIntent = Intent(Intent.ACTION_VIEW) // The channel ID of the notification. val id = "my_channel_01" val mapPendingIntent = Intent(Intent.ACTION_VIEW).let { mapIntent -> mapIntent.data = Uri.parse("geo:0,0?q=" + Uri.encode(location)) PendingIntent.getActivity(this, 0, mapIntent, 0) } val notificationBuilder = NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent)
자바
// Build an intent for an action to view a map Intent mapIntent = new Intent(Intent.ACTION_VIEW); // The channel ID of the notification. String id = "my_channel_01"; Uri geoUri = Uri.parse("geo:0,0?q=" + Uri.encode(location)); mapIntent.setData(geoUri); PendingIntent mapPendingIntent = PendingIntent.getActivity(this, 0, mapIntent, 0); NotificationCompat.Builder notificationBuilder = new NotificationCompat.Builder(this, id) .setSmallIcon(R.drawable.ic_event) .setContentTitle(eventTitle) .setContentText(eventLocation) .setContentIntent(viewPendingIntent) .addAction(R.drawable.ic_map, getString(R.string.map), mapPendingIntent);
스마트폰에서는 작업이 알림에 첨부된 추가 버튼으로 나타납니다. 웨어러블 기기에서는 작업이 콘텐츠 텍스트 뒤의 확장된 알림에 나타납니다. 사용자가 작업을 탭하면 관련된 인텐트가 스마트폰에서 호출됩니다.
팁: 알림에 '답장' 작업이 포함된 경우(예: 메시징 앱의 경우) 웨어러블에서 직접 음성 입력 답장을 사용하도록 설정하여 동작을 개선할 수 있습니다. 자세한 내용은 알림 작업으로서 음성 입력 추가를 참조하세요.
인라인 작업 추가

인라인 작업을 사용하면 사용자는 알림 스트림 카드 내에서 알림에 관한 작업을 수행할 수 있습니다. Wear에서 인라인 작업은 알림의 하단에 표시되는 추가 버튼으로 나타납니다.
인라인 작업은 선택사항이지만, 사용자가 알림 스트림 카드에서 콘텐츠를 본 이후(확장된 알림으로 이동하지 않고) 알림으로 작업할 가능성이 있는 경우에는 인라인 작업을 사용하는 것이 좋습니다. 알림에서 인라인 작업을 사용하는 좋은 사용 사례로는 문자 메시지에 답장, 피트니스 활동 중지, 이메일 메시지 보관 등이 있습니다.
하나의 알림은 하나의 인라인 작업만 제공할 수 있습니다. 인라인 작업을 알림에서 추가 버튼으로 표시하려면 setHintDisplayActionInline()
메서드를 true로 설정합니다. 사용자가 인라인 작업을 탭하면 시스템은 알림 작업에 지정된 인텐트를 호출합니다.
다음 코드 스니펫은 작업을 인라인으로 표시하기 위한 힌트를 추가하며, addAction
메서드를 사용하여 알림에 인라인 작업을 추가합니다.
Kotlin
//Wear OS requires a hint to display the reply action inline. val actionExtender = NotificationCompat.Action.WearableExtender() .setHintLaunchesActivity(true) .setHintDisplayActionInline(true) wearableExtender.addAction(actionBuilder.extend(actionExtender).build())
자바
//Wear OS requires a hint to display the reply action inline. Action.WearableExtender actionExtender = new Action.WearableExtender() .setHintLaunchesActivity(true) .setHintDisplayActionInline(true); wearableExtender.addAction(actionBuilder.extend(actionExtender).build());
알림에 웨어러블 관련 기능 추가
알림에 웨어러블 관련 기능(예: 웨어러블 알림에서 앱 아이콘 숨기기 또는 사용자가 음성 입력으로 텍스트 응답을 지정하도록 허용)을 추가해야 하는 경우 NotificationCompat.WearableExtender
클래스를 사용하여 옵션을 지정할 수 있습니다.
이 API를 사용하려면 다음 단계를 따르세요.
WearableExtender
의 인스턴스를 만들고 알림에 관해 웨어러블 관련 옵션을 설정합니다.NotificationCompat.Builder
의 인스턴스를 만들고 이 과정에서 앞서 설명한 것처럼 원하는 알림 속성을 설정합니다.-
알림에서
extend()
를 호출하고WearableExtender
를 전달합니다. 이렇게 하면 웨어러블 옵션이 알림에 적용됩니다. build()
를 호출하여 알림을 만듭니다.
참고: 프레임워크의 NotificationManager
를 사용하는 경우 NotificationCompat.WearableExtender
의 일부 기능이 작동하지 않으므로 NotificationCompat
를 사용해야 합니다.
사용자의 기기 전반에서 알림의 닫기(취소)를 동기화할 수 있습니다. 닫기를 동기화하려면 setDismissalId()
메서드를 사용합니다. setDismissalId()
메서드를 호출할 때 각 알림과 관련해 전역적으로 고유한 ID를 문자열 형태로 전달합니다. 알림이 닫히면, 시계 및 연결된 스마트폰에서 동일한 닫기 ID가 있는 다른 모든 알림도 닫힙니다. 닫기 ID를 가져오려면 getDismissalId()
를 사용합니다.
참고: setBackground()
메서드는 Wear 2.0에서 지원되지 않습니다. 이미지가 포함된 알림에는 NotificationCompat.BigPictureStyle
을 사용할 수 있습니다.
setHintHideIcon()
메서드도 Wear 2.0에서 지원되지 않습니다.
웨어러블 전용 작업 지정
웨어러블에서 수행할 수 있는 작업과 스마트폰에서 수행할 수 있는 작업을 다르게 하려면 WearableExtender.addAction()
을 사용합니다. 이 메서드로 작업을 추가하면 웨어러블에는 NotificationCompat.Builder.addAction()
으로 추가된 다른 작업이 표시되지 않습니다. WearableExtender.addAction()
으로 추가된 작업은 웨어러블에만 표시되고 스마트폰에는 표시되지 않습니다.
알림 작업으로 음성 입력 추가
음성 작업은 웨어러블 환경의 중요한 부분입니다. 음성 입력을 지원하는 작업을 만들려면 알림 작업에 추가할 수 있는 RemoteInput.Builder
의 인스턴스를 만듭니다.
이 클래스의 생성자는 시스템이 음성 입력의 키로 사용하는 문자열을 수락합니다. 나중에 전화 앱에서 입력 텍스트를 검색하는 데 이 문자열을 사용합니다.

예를 들어 음성 입력 메시지의 맞춤 라벨을 제공하는 RemoteInput
객체를 만드는 방법은 다음과 같습니다.
Kotlin
// Key for the string that's delivered in the action's intent const val EXTRA_VOICE_REPLY = "extra_voice_reply" ... val remoteInput = resources.getString(R.string.reply_label).let { replyLabel -> RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .build() }
자바
// Key for the string that's delivered in the action's intent private static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; String replyLabel = getResources().getString(R.string.reply_label); RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .build();
사전 정의된 텍스트 응답 추가

음성 입력을 허용하는 것 외에도 사용자가 빠른 응답을 위해 선택할 수 있는 최대 5개의 텍스트 응답을 제공할 수 있습니다. setChoices()
를 호출하고 이 인수에 문자열 배열을 전달합니다.
예를 들어, 리소스 배열에서 몇 가지 응답을 정의할 수 있습니다.
res/values/strings.xml
<?xml version="1.0" encoding="utf-8"?> <resources> <string-array name="reply_choices"> <item>Yes</item> <item>No</item> <item>Maybe</item> </string-array> </resources>
그런 다음 문자열 배열을 확장하여 RemoteInput
에 추가합니다.
Kotlin
// Key for the string that's delivered in the action's intent const val EXTRA_VOICE_REPLY = "extra_voice_reply" ... val remoteInput = resources.getString(R.string.reply_label).let { replyLabel -> resources.getStringArray(R.array.reply_choices).let { replyChoices -> RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(replyChoices) .build() } }
자바
public static final String EXTRA_VOICE_REPLY = "extra_voice_reply"; ... String replyLabel = getResources().getString(R.string.reply_label); String[] replyChoices = getResources().getStringArray(R.array.reply_choices); RemoteInput remoteInput = new RemoteInput.Builder(EXTRA_VOICE_REPLY) .setLabel(replyLabel) .setChoices(replyChoices) .build();
음성 입력을 문자열로 받기
답장 작업의 인텐트에서 선언한 활동에서 텍스트로 변환된 사용자의 메시지를 받으려면 getResultsFromIntent()
를 호출하고 '답장' 작업의 인텐트를 전달합니다.
이 메서드는 텍스트 응답이 포함된 Bundle
을 반환합니다.
그러면 Bundle
을 쿼리하여 응답을 가져올 수 있습니다.
참고: 음성 입력은 ClipData
로 저장되므로 Intent.getExtras()
를 사용하여 음성 결과를 가져오지 마세요. getResultsFromIntent()
메서드를 사용하면 ClipData
를 직접 처리하지 않고도 문자 시퀀스를 편리하게 수신할 수 있습니다.
다음 코드는 인텐트를 수락하고 음성 응답을 반환하는 메서드를 보여줍니다. 이 메서드는 이전 예제에 사용된 EXTRA_VOICE_REPLY
키에 의해 참조됩니다.
Kotlin
/** * Obtain the intent that started this activity by calling * Activity.getIntent() and pass it into this method to * get the associated voice input string. */ private fun getMessageText(intent: Intent): CharSequence? = RemoteInput.getResultsFromIntent(intent)?.run { getCharSequence(EXTRA_VOICE_REPLY) }
자바
/** * Obtain the intent that started this activity by calling * Activity.getIntent() and pass it into this method to * get the associated voice input string. */ private CharSequence getMessageText(Intent intent) { Bundle remoteInput = RemoteInput.getResultsFromIntent(intent); if (remoteInput != null) { return remoteInput.getCharSequence(EXTRA_VOICE_REPLY); } return null; }
Kotlin
// Create an intent for the reply action val actionPendingIntent = Intent(this, ActionActivity::class.java).let { actionIntent -> PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT) } // Create the action val action = NotificationCompat.Action.Builder( R.drawable.ic_action, getString(R.string.label), actionPendingIntent ).build() // Build the notification and add the action via WearableExtender var notification = NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(NotificationCompat.WearableExtender().addAction(action)) .build()
자바
// Create an intent for the reply action Intent actionIntent = new Intent(this, ActionActivity.class); PendingIntent actionPendingIntent = PendingIntent.getActivity(this, 0, actionIntent, PendingIntent.FLAG_UPDATE_CURRENT); // Create the action NotificationCompat.Action action = new NotificationCompat.Action.Builder(R.drawable.ic_action, getString(R.string.label), actionPendingIntent) .build(); // Build the notification and add the action via WearableExtender Notification notification = new NotificationCompat.Builder(context) .setSmallIcon(R.drawable.ic_message) .setContentTitle(getString(R.string.title)) .setContentText(getString(R.string.content)) .extend(new WearableExtender().addAction(action)) .build();
독립 실행형 웨어러블 앱에서 알림 시작
독립 실행형 시계 앱에서 알림을 만드는 것은 연결된 알림을 만드는 것과 다르지 않습니다. 독립 실행형 Wear 앱에서 오는 알림은 연결된 알림과 모양은 유사하지만 동작은 약간 다릅니다. contentIntent
가 설정되지 않았거나 페어링된 스마트폰에서 알림이 연결된 경우 알림을 탭하면 확장된 알림이 열립니다.
반면 알림이 독립 실행형 시계 앱에서 발생하는 경우 알림을 탭하면 contentIntent
가 실행되어 Wear 앱이 열립니다. 독립 실행형 앱에서 알림을 만들고 확장된 알림 동작을 모방하는 방법을 알아보려면 Wear 알림 샘플을 참조하세요.
기본적으로 알림은 연결된 스마트폰의 앱에서 페어링된 시계로 연결됩니다. 독립 실행형 시계 앱을 빌드하고 동반 스마트폰 앱을 가지고 있는 경우, 이 두 앱이 중복 알림을 만들 수 있습니다. 중복 알림 문제를 처리하는 방법에 관한 자세한 내용은 알림을 위한 연결 모드를 참조하세요.