85일차(1)/Android App(49) : Notification(2)
- 알림Notification 띄우기 / 자동,수동 삭제 방법
- 이전 예제에서 만든 자동으로 사라지는 알림 창 코드 복습!
- 알림 창을 클릭하면 어떤 액티비티가 활성화되면서 알림이 사라진다.
(DetailActivity 로 이동하도록 함)
[ 알림을 띄우기 위해서 필요한 작업 ]
1. 알림 채널을 만들어야 한다.
2. 사용자가 직접 알림을 허용하도록 유도해야 한다.
3. AndroidManifest.xml에 알림 pemission 설정이 있어야 한다.
- 알림 띄우기 버튼을 클릭하면, 알림 권한이 켜져있는지 꺼져있는지 확인해서 꺼져있으면 켜도록 요청했다.
- 채널은 최초에 한번만 만들면 된다.
- 이전에 만든 코드로는 알림을 띄울때마다 매번 채널을 생성하게 되므로,
onCreate() 메소드 if문 안으로 위치를 옮겨서 확인 후 채널을 생성하게 한다.
- 채널이 동작하는지 확인하려면?
- 가상기기에서 앱을 삭제하고 새로 install하면 알림권한 확인 창부터 다시 뜬다.
notification
- MainActivity 에서 알림 띄우기 버튼을 눌러서 알림을 띄우고,
알림센터에서 해당 알림을 클릭하면 DetailActivity가 활성화된다.
- 그럼 MainActivity는 지금 onStop 되어있을까?
→ 아니다. 만약 그렇다면 백버튼을 누르면 돌아가야하는데 지금은 백버튼을 누르면 기본화면으로 간다.
- 이 intent에다가 이런 설정을 넣었기 때문에,
DetailActivity가 기존에 떠 있는 Activity 위에 쌓인 것이 아니고, 새로운 태스크에서 실행되었다.
- 알림을 실행했을때 실행할 액티비티 정보를 담고있는 인텐트를 PendingIntent 객체에 담고,
알림을 띄울 때 이 PendingIntent 를 같이 전달하는 구조이다.
** 수동 취소되는 알림 만들기
MainActivity
package com.example.step21notification;
import android.Manifest;
import android.app.Notification;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.os.Build;
import android.os.Bundle;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Toast;
import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.app.NotificationCompat;
import androidx.core.app.NotificationManagerCompat;
/*
알림을 띄우기 위해서 필요한 작업
1. 알림 채널을 만들어야 한다.
2. 사용자가 직접 알림을 허용하도록 유도해야 한다.
3. AndroidManifest.xml에 알림 pemission 설정이 있어야 한다.
*/
public class MainActivity extends AppCompatActivity {
//알림 체널의 이름 정하기
public static final String CHANNEL_NAME = "com.example.step21notification.MY_CHANNEL";
//필요한 필드
EditText inputMsg;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
inputMsg = findViewById(R.id.inputMsg);
//Auto Cancel 버튼을 눌렀을때 동작
Button notiBtn = findViewById(R.id.notiBtn);
notiBtn.setOnClickListener(v -> {
makeAutoCancelNoti();
});
//수동 취소 버튼을 눌렀을때 동작
Button notiBtn2=findViewById(R.id.notiBtn2);
notiBtn2.setOnClickListener(v -> {
makeManualCancelNoti();
});
//만일 알림이 가능하지 않다면(알림 채널이 만들어져 있지 않다면)
if(!NotificationManagerCompat.from(this).areNotificationsEnabled()){
//알림 채널을 만든다.
createNotificationChannel();
}
}
//수동으로 취소하는 알림을 띄우는 메소드
public void makeManualCancelNoti(){
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
//권한이 필요한 목록을 배열에 담는다.
String[] permissions={Manifest.permission.POST_NOTIFICATIONS};
//배열을 전달해서 해당 권한을 부여하도록 요청한다.
ActivityCompat.requestPermissions(this,
permissions,
0); //요청의 아이디
return;
}
//입력한 문자열을 읽어온다.
String msg = inputMsg.getText().toString();
//createNotificationChannel();
//알림을 클릭했을때 활성화시킬 액티비티 정보를 담고 있는 Intent 객체
Intent intent = new Intent(this, DetailActivity.class);
//액티비티를 실행하는데 새로운 태스크에서 실행되도록 한다(기존에 onStop() 에 머물러 있다면 제거하고 새로 시작)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
//intent에 msg라는 키값으로 String type을 담는다. 새로 시작된 액티비티에서 읽어낼 수 있다.
intent.putExtra("msg", msg);
//알림의 아이디 얻어내기 (값이 겹치지않게)
int currentId = (int) (System.currentTimeMillis() / 1000);
intent.putExtra("notiId", currentId);
//인텐트 전달자 객체
PendingIntent pendingIntent = PendingIntent.getActivity(this, currentId, intent, PendingIntent.FLAG_MUTABLE);
//띄울 알림을 구성하기
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_NAME)
.setSmallIcon(android.R.drawable.star_on) //알림의 아이콘
.setContentTitle("알림을 취소해 주세요!") //알림의 내용
.setContentText(msg) //알림의 내용
.setPriority(NotificationCompat.PRIORITY_DEFAULT) //알림의 우선순위
.setContentIntent(pendingIntent) //인텐트 전달
.setAutoCancel(false); //자동 취소되는 알림인지 여부
//알림 만들기
Notification noti=builder.build();
//알림 매니저를 이용해서 알림을 띄운다.
NotificationManagerCompat.from(this).notify(currentId, noti);
}
//자동으로 취소하는 알림을 띄우는 메소드
public void makeAutoCancelNoti(){
if (ActivityCompat.checkSelfPermission(this, android.Manifest.permission.POST_NOTIFICATIONS) != PackageManager.PERMISSION_GRANTED) {
//권한이 필요한 목록을 배열에 담는다.
String[] permissions={Manifest.permission.POST_NOTIFICATIONS};
//배열을 전달해서 해당 권한을 부여하도록 요청한다.
ActivityCompat.requestPermissions(this,
permissions,
0); //요청의 아이디
return;
}
//입력한 문자열을 읽어온다.
String msg = inputMsg.getText().toString();
//createNotificationChannel();
//알림을 클릭했을때 활성화시킬 액티비티 정보를 담고 있는 Intent 객체
Intent intent = new Intent(this, DetailActivity.class);
//액티비티를 실행하는데 새로운 태스크에서 실행되도록 한다(기존에 onStop() 에 머물러 있다면 제거하고 새로 시작)
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_CLEAR_TASK);
//intent에 msg라는 키값으로 String type을 담는다. 새로 시작된 액티비티에서 읽어낼 수 있다.
intent.putExtra("msg", msg);
//알림의 아이디 얻어내기 (값이 겹치지않게)
int currentId = (int) (System.currentTimeMillis() / 1000);
//인텐트 전달자 객체
PendingIntent pendingIntent = PendingIntent.getActivity(this, currentId, intent, PendingIntent.FLAG_MUTABLE);
//띄울 알림을 구성하기
NotificationCompat.Builder builder = new NotificationCompat.Builder(this, CHANNEL_NAME)
.setSmallIcon(android.R.drawable.ic_btn_speak_now) //알림의 아이콘
.setContentTitle("얘들아 나야~") //알림의 내용
.setContentText(msg) //알림의 내용
.setPriority(NotificationCompat.PRIORITY_DEFAULT) //알림의 우선순위
.setContentIntent(pendingIntent) //인텐트 전달
.setAutoCancel(true); //자동 취소되는 알림인지 여부
//알림 만들기
Notification noti=builder.build();
//알림 매니저를 이용해서 알림을 띄운다.
NotificationManagerCompat.from(this).notify(currentId, noti);
}
//앱의 사용자가 알림을 직접 관리 할수 있도록 알림 채널을 만들어야한다.
public void createNotificationChannel(){
//알림 채널을 지원하는 기기인지 확인해서
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
//알림 채널을 만들기
//셈플 데이터
String name="삼성카드";
String text="테스트!";
//알림 채널 객체를 얻어내서
NotificationChannel channel=
new NotificationChannel(CHANNEL_NAME, name, NotificationManager.IMPORTANCE_DEFAULT);
//채널의 설명을 적고
channel.setDescription(text);
//알림 매니저 객체를 얻어내서
NotificationManager notiManager=(NotificationManager)getSystemService(Context.NOTIFICATION_SERVICE);
//알림 채널을 만든다.
notiManager.createNotificationChannel(channel);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode){
case 0:
//권한을 부여 했다면
if(grantResults[0] == PackageManager.PERMISSION_GRANTED){
//자동 취소 알림 띄우기
makeAutoCancelNoti();
}else{//권한을 부여 하지 않았다면
Toast.makeText(this, "알림을 띄울 권한이 필요합니다.",
Toast.LENGTH_SHORT).show();
}
break;
}
}
}
- 버튼에 onClickListener를 지정하고,
수동으로 취소하는 알림을 띄울 makeManualCancelNoti() 메소드 생성
- 자동 취소 메소드를 복사해와서 일부 수정해주기!
- 알림의 아이디를 얻어와서 전달해주기
이 아이디를 DetailActivity에 전달한다. putExtra() 로 intent에 담으면 된다.
- 자동취소되는 알림인지 여부를 false로 바꾸기
- setSmallIcon() 메소드에서 알림 아이콘을 다른 것으로 바꾸어 볼 수 있다.
- 알림을 클릭해서 Detail Activity로 이동했음에도 불구하고, 알림창에 알림이 여전히 남아 있다.
- 블루투스로 음악을 들을 때 음악 어플리케이션을 꺼도 알림창에는 여전히 음악을 제어할 수 있는 기능이 남아있다.
- 알림창에 그런 제어 기능을 가지고있는 알림들은 항상 띄워놓고 필요할 때마다 들어가봐야 할 수 있다.
ex) 알람 남은시간 확인 등이 알림에서 줄어들고 있는 것 등등...
- 이런 알림의 경우 사용자가 일부러 취소(제거)하지 않는 이상 남아있는다.
- DetailActivity에 수동으로 알림을 제거하는 버튼 추가
activity_detail.xml
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout 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="com.example.step21notification.DetailActivity"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:textSize="20sp"
android:id="@+id/textView"/>
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="알림 삭제하기"
android:id="@+id/cancelBtn"/>
</LinearLayout>
DetailActivity
package com.example.step21notification;
import android.content.Intent;
import android.os.Bundle;
import android.widget.Button;
import android.widget.TextView;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.NotificationManagerCompat;
public class DetailActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_detail);
//전달된 intent 객체
Intent intent = getIntent();
//intent 객체에 "msg"라는 키값으로 전달된 문자열 얻어내기
String msg=intent.getStringExtra("msg");
//TextView에 출력해보기
TextView textView=findViewById(R.id.textView);
textView.setText(msg);
Button cancelBtn=findViewById(R.id.cancelBtn);
cancelBtn.setOnClickListener(v -> {
//Intent 객체에 담긴 알림의 아이디 얻어내기
int notiId=intent.getIntExtra("notiId", 0);
//알림의 아이디를 이용해서 알림 취소하기
NotificationManagerCompat.from(this).cancel(notiId);
});
}
}
- getStringExtra() 로 MainActivity에서 intent 객체에 넣었던 문자열을 읽어온다.
- getIntExtra() : 메소드에 디폴트 값이 없을 경우, 처음에 들어갈 디폴트값을 넣어주어야 한다.(에러 방지용)
- notiId를 이용해서 해당 아이디를 가지고 있는 알림을 취소한다!
- 수동 알림을 띄우고,
- 들어가서 알림 삭제하기 버튼을 누르면 알림의 별 아이콘이 사라진다.
'국비교육(22-23)' 카테고리의 다른 글
86일차(1)/Android App(51) : mp3 파일 재생 예제 / MediaPlayer(서버) (0) | 2023.02.10 |
---|---|
85일차(2)/Android App(50) : Service / Binder 객체로 mp3파일 재생하기 (0) | 2023.02.10 |
84일차(2)/Android App(48) : Notification(1) (0) | 2023.02.09 |
84일차(1)/Android App(47) : Content Provider (0) | 2023.02.08 |
83일차(1)/Android App(46) : 전화걸기 기능 구현 (0) | 2023.02.07 |