https://webnautes.tistory.com/665
[1] https://developer.android.com/training/notify-user/build-notification?hl=ko
[2] https://stackoverflow.com/questions/43093260/notification-not-showing-in-oreo
[3] https://stackoverflow.com/questions/47368187/android-oreo-notification-crashes-system-ui
오레오(Oreo API 26) 이상부터는 채널을 추가해야 노티피케이션을 사용할 수 있다는 것을 알게되어 포스트를 수정합니다.
안드로이드 폰에서 사용하는 운영체제 버전에 따라 실행결과가 다릅니다.
1. 노티피케이션 동작 설명
2. 전체 소스코드
3. 관련 포스트
4. 참고
|
2015.02.19 - 최초작성
2016.10.22
2019.08.13 - 오레오를 위한 코드 추가
1. 노티피케이션 동작 설명
실행시키면 노티피케이션을 발생시키는 버튼을 보여줍니다.
버튼을 터치할 때마다 변수 count 값을 증가시켜주도록 했습니다.
최종적으로 노티피케이션에 의해 전달되는 값은 마지막에 전달한 값이 되는 걸 확인하기 위해서 입니다.
3번 터치한 후 결과를 보겠습니다.
![Y3IA4BP---9_aJtV1-K-xG3jBeZNZucL2MUez-1-cZIxqtQcSAropc-KOnAQ8UAusMQ_ztQd_9HYO_3otIMtJuJkVr_BaQuzfM_P5Mb2YRf5O3dzsx3-w_E_h4CsxuDLVupNvp5C Y3IA4BP---9_aJtV1-K-xG3jBeZNZucL2MUez-1-cZIxqtQcSAropc-KOnAQ8UAusMQ_ztQd_9HYO_3otIMtJuJkVr_BaQuzfM_P5Mb2YRf5O3dzsx3-w_E_h4CsxuDLVupNvp5C](https://lh3.googleusercontent.com/Y3IA4BP---9_aJtV1-K-xG3jBeZNZucL2MUez-1-cZIxqtQcSAropc-KOnAQ8UAusMQ_ztQd_9HYO_3otIMtJuJkVr_BaQuzfM_P5Mb2YRf5O3dzsx3-w_E_h4CsxuDLVupNvp5C)
노티피케이션 우선순위가 충분히 높다면 아래처럼 헤드업(heads-up) 알림이 보입니다. 이때 터치해도 됩니다.
우선순위가 높지 않으면 헤드업 알림이 보이지 않고 다음 단계에 보이는 스크린샷처럼 아이콘만 보여줍니다.
참고로 에뮬레이터에서도 헤드업 알림이 보이지 않습니다.
![iH7zn7E_G9VsOnkT3m8OXxoE2Ocr5F8sKjw0KVs6AL5UwOJezfG3J7alLxeL-CtEHJilgr_TtpE-GGqj-bnO1Z-yhICsNZfefQ4eHJ52k2MydxjRS0PeJ0xYMT2aiXvAiILTEx1M iH7zn7E_G9VsOnkT3m8OXxoE2Ocr5F8sKjw0KVs6AL5UwOJezfG3J7alLxeL-CtEHJilgr_TtpE-GGqj-bnO1Z-yhICsNZfefQ4eHJ52k2MydxjRS0PeJ0xYMT2aiXvAiILTEx1M](https://lh3.googleusercontent.com/iH7zn7E_G9VsOnkT3m8OXxoE2Ocr5F8sKjw0KVs6AL5UwOJezfG3J7alLxeL-CtEHJilgr_TtpE-GGqj-bnO1Z-yhICsNZfefQ4eHJ52k2MydxjRS0PeJ0xYMT2aiXvAiILTEx1M)
왼쪽 위에 작은 아이콘으로 알림이 도착한 것을 알려줍니다.
![Qdvbr1HaRwwAmzPfhkzcsed2_g7fmdKIFPJeHpnrAsGg3Fu3r2wje18VP3_GKLv7z0Yo8FVm6KBPDWIS0LdXzs9-_r52V857gK7LAw69nLUHPk1MjtMvxngnLYTLMFd8YVdQpF6x Qdvbr1HaRwwAmzPfhkzcsed2_g7fmdKIFPJeHpnrAsGg3Fu3r2wje18VP3_GKLv7z0Yo8FVm6KBPDWIS0LdXzs9-_r52V857gK7LAw69nLUHPk1MjtMvxngnLYTLMFd8YVdQpF6x](https://lh4.googleusercontent.com/Qdvbr1HaRwwAmzPfhkzcsed2_g7fmdKIFPJeHpnrAsGg3Fu3r2wje18VP3_GKLv7z0Yo8FVm6KBPDWIS0LdXzs9-_r52V857gK7LAw69nLUHPk1MjtMvxngnLYTLMFd8YVdQpF6x)
상태바를 아래로 드래그하면 자세한 알림 정보를 볼 수 있습니다.
알림을 터치해주면 다른 액티비티로 넘어가도록 했습니다. 이 때 변수 count 값을 전달합니다.
![87-3YbcOmCEgoY6HT6zrz55N0NLSitQymyhsWaOOGlBuYvPyThRT1TeC2nyzrOZykKvMO7ORXi4-nqZcp7sZ2MgAp1DJGkTqigRAdrD9WqhY7JuDuLcPz0t9UsAxEKycmLd1vxJH 87-3YbcOmCEgoY6HT6zrz55N0NLSitQymyhsWaOOGlBuYvPyThRT1TeC2nyzrOZykKvMO7ORXi4-nqZcp7sZ2MgAp1DJGkTqigRAdrD9WqhY7JuDuLcPz0t9UsAxEKycmLd1vxJH](https://lh3.googleusercontent.com/87-3YbcOmCEgoY6HT6zrz55N0NLSitQymyhsWaOOGlBuYvPyThRT1TeC2nyzrOZykKvMO7ORXi4-nqZcp7sZ2MgAp1DJGkTqigRAdrD9WqhY7JuDuLcPz0t9UsAxEKycmLd1vxJH)
새로운 액티비티가 실행되면서 앞에서 버튼을 터치한 횟수를 보여줍니다.
앞에서 3번 터치해서 3이 보입니다.
변수 count의 마지막 값만 사용자가 볼 수 있다는 것을 알 수 있습니다.
즉 알림이 여러개 와도 마지막에 온 알림에 해당하는 정보만 볼 수 있도록 구현되어 있습니다.
![OUJSilA20SofN2moCPug9JYJIHK9XCGSxVPjdryhOi9iT3bkdE51x6mXF0RHT-1wZRqo6cy3I6bsJAHeUjEt7yLUXaYad-rsJdp132PwvoLLl7cnVwhNRa699vGTyuMkpLOtQicC OUJSilA20SofN2moCPug9JYJIHK9XCGSxVPjdryhOi9iT3bkdE51x6mXF0RHT-1wZRqo6cy3I6bsJAHeUjEt7yLUXaYad-rsJdp132PwvoLLl7cnVwhNRa699vGTyuMkpLOtQicC](https://lh6.googleusercontent.com/OUJSilA20SofN2moCPug9JYJIHK9XCGSxVPjdryhOi9iT3bkdE51x6mXF0RHT-1wZRqo6cy3I6bsJAHeUjEt7yLUXaYad-rsJdp132PwvoLLl7cnVwhNRa699vGTyuMkpLOtQicC)
앱 정보에서 다음처럼 등록한 알림 채널을 볼 수 있고.. 사용자가 수정도 가능합니다.
앱 알림을 선택합니다.
![RKdNEjNwJRhnxu2hi6HHa-0YNn0dEmc3Shko8ANCwIXsTggUiDLpwN0R1vL9AezitUqYr7Xi3i0H4aX5fNDH35p4hOZcKEi6jJ5O9IB0ODRUGhCIgzVqunQCOvuthBtebimJOA7F RKdNEjNwJRhnxu2hi6HHa-0YNn0dEmc3Shko8ANCwIXsTggUiDLpwN0R1vL9AezitUqYr7Xi3i0H4aX5fNDH35p4hOZcKEi6jJ5O9IB0ODRUGhCIgzVqunQCOvuthBtebimJOA7F](https://lh3.googleusercontent.com/RKdNEjNwJRhnxu2hi6HHa-0YNn0dEmc3Shko8ANCwIXsTggUiDLpwN0R1vL9AezitUqYr7Xi3i0H4aX5fNDH35p4hOZcKEi6jJ5O9IB0ODRUGhCIgzVqunQCOvuthBtebimJOA7F)
노티페케이션 채널이(오타가 났네요..) 코드에서 추가한 채널입니다.
해당 채널을 터치하면.
![GElnMBh0NNOLkchm5RauDh6tOITEXYulrkEsjvicTDGfp4CnKa0d8qRVD5pAB2NF8QaHLUIPNJEwUm5dEQvEaKk3zS9EDg3LlPkBw3OFqVkJU1NXrLnHja_yJ5T-v0DID_5697na GElnMBh0NNOLkchm5RauDh6tOITEXYulrkEsjvicTDGfp4CnKa0d8qRVD5pAB2NF8QaHLUIPNJEwUm5dEQvEaKk3zS9EDg3LlPkBw3OFqVkJU1NXrLnHja_yJ5T-v0DID_5697na](https://lh3.googleusercontent.com/GElnMBh0NNOLkchm5RauDh6tOITEXYulrkEsjvicTDGfp4CnKa0d8qRVD5pAB2NF8QaHLUIPNJEwUm5dEQvEaKk3zS9EDg3LlPkBw3OFqVkJU1NXrLnHja_yJ5T-v0DID_5697na)
채널에서 변경가능한 값들을 보여줍니다.
![PGkjtDRhQOz9lsEbZE6PzkADQhXzii1MmT1VTh5qBi88tZlgOAHK9OqegJEWR6cMrwDYWohWhQ8fzGXRoAw38K0uufPXz4TH0HGyLAZYLuL4TtzWUT5XFMC8XmwkX5oesSg3uXoK PGkjtDRhQOz9lsEbZE6PzkADQhXzii1MmT1VTh5qBi88tZlgOAHK9OqegJEWR6cMrwDYWohWhQ8fzGXRoAw38K0uufPXz4TH0HGyLAZYLuL4TtzWUT5XFMC8XmwkX5oesSg3uXoK](https://lh4.googleusercontent.com/PGkjtDRhQOz9lsEbZE6PzkADQhXzii1MmT1VTh5qBi88tZlgOAHK9OqegJEWR6cMrwDYWohWhQ8fzGXRoAw38K0uufPXz4TH0HGyLAZYLuL4TtzWUT5XFMC8XmwkX5oesSg3uXoK)
2. 전체 소스코드
API 29와 androidx를 사용하여 작성하였습니다.
build.gradle
노티피케이션을 사용하기 위해 필요한 패키지를 설치해줍니다.
dependencies { implementation fileTree(dir: 'libs', include: ['*.jar']) implementation 'androidx.appcompat:appcompat:1.1.0-rc01' implementation 'androidx.constraintlayout:constraintlayout:1.1.3' testImplementation 'junit:junit:4.12' androidTestImplementation 'androidx.test:runner:1.2.0' androidTestImplementation 'androidx.test.espresso:espresso-core:3.2.0' implementation "androidx.core:core:1.0.2" } |
AndroidManifest.xml
노트피케이션 결과를 보여줄 액티미티를 매니페스트에 추가해줍니다.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="com.tistory.webnautes.notificationexample">
<application android:allowBackup="true" android:icon="@mipmap/ic_launcher" android:label="@string/app_name" android:roundIcon="@mipmap/ic_launcher_round" android:supportsRtl="true" android:theme="@style/AppTheme"> <activity android:name=".MainActivity"> <intent-filter> <action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity>
<activity android:name=".ResultActivity" android:parentActivityName=".MainActivity" > </activity> </application>
</manifest> |
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:text="노티피케이션 발생시키기" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="20dp" android:id="@+id/button" />
</androidx.constraintlayout.widget.ConstraintLayout> |
result_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:text="" android:layout_width="wrap_content" android:layout_height="wrap_content" app:layout_constraintLeft_toLeftOf="parent" app:layout_constraintRight_toRightOf="parent" app:layout_constraintTop_toTopOf="parent" android:layout_marginTop="20dp" android:id="@+id/textView" />
</androidx.constraintlayout.widget.ConstraintLayout> |
MainActivity.java
노티피케이션이 구현된 자바코드입니다.
package com.tistory.webnautes.notificationexample;
import androidx.appcompat.app.AppCompatActivity; import androidx.core.app.NotificationCompat;
import android.app.NotificationChannel; import android.app.NotificationManager; import android.app.PendingIntent; import android.content.Context; import android.content.Intent; import android.graphics.BitmapFactory; import android.os.Build; import android.os.Bundle; import android.view.View; import android.widget.Button;
public class MainActivity extends AppCompatActivity {
public static final String NOTIFICATION_CHANNEL_ID = "10001"; private int count = 0;
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main);
Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View arg0) {
// 버튼을 누를때마다 count 를 증가시며 최근에 보낸 노티피케이션만 사용자의 탭 대기중인지 테스트 count++; NotificationSomethings(); } }); }
public void NotificationSomethings() {
NotificationManager notificationManager = (NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
Intent notificationIntent = new Intent(this, ResultActivity.class); notificationIntent.putExtra("notificationId", count); //전달할 값 notificationIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TASK) ; PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, NOTIFICATION_CHANNEL_ID) .setLargeIcon(BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher_foreground)) //BitMap 이미지 요구 .setContentTitle("상태바 드래그시 보이는 타이틀") .setContentText("상태바 드래그시 보이는 서브타이틀") // 더 많은 내용이라서 일부만 보여줘야 하는 경우 아래 주석을 제거하면 setContentText에 있는 문자열 대신 아래 문자열을 보여줌 //.setStyle(new NotificationCompat.BigTextStyle().bigText("더 많은 내용을 보여줘야 하는 경우...")) .setPriority(NotificationCompat.PRIORITY_DEFAULT) .setContentIntent(pendingIntent) // 사용자가 노티피케이션을 탭시 ResultActivity로 이동하도록 설정 .setAutoCancel(true);
//OREO API 26 이상에서는 채널 필요 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
builder.setSmallIcon(R.drawable.ic_launcher_foreground); //mipmap 사용시 Oreo 이상에서 시스템 UI 에러남 CharSequence channelName = "노티페케이션 채널"; String description = "오레오 이상을 위한 것임"; int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel channel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, channelName , importance); channel.setDescription(description);
// 노티피케이션 채널을 시스템에 등록 assert notificationManager != null; notificationManager.createNotificationChannel(channel);
}else builder.setSmallIcon(R.mipmap.ic_launcher); // Oreo 이하에서 mipmap 사용하지 않으면 Couldn't create icon: StatusBarIcon 에러남
assert notificationManager != null; notificationManager.notify(1234, builder.build()); // 고유숫자로 노티피케이션 동작시킴
}
} |
ResultActivity.java
노티피케이션 결과 전달 받은 숫자를 보여주는 역활을 합니다.
package com.tistory.webnautes.notificationexample;
import android.app.NotificationManager; import android.content.Context; import android.os.Bundle; import android.widget.TextView;
import androidx.annotation.Nullable; import androidx.appcompat.app.AppCompatActivity;
public class ResultActivity extends AppCompatActivity {
@Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.result_main);
String text = "전달 받은 값은"; int id = 0;
Bundle extras = getIntent().getExtras(); if (extras == null) { text = "값을 전달 받는데 문제 발생"; } else id = extras.getInt("notificationId");
TextView textView = (TextView) findViewById(R.id.textView); textView.setText(text + " " + id);
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
//노티피케이션 제거 notificationManager.cancel(id); } } |