안드로이드에서 5분마다 알림 표시하기
이 튜토리얼에서는 안드로이드 앱에서 일정한 간격으로 자동으로 알림(Notification)을 표시하는 방법을 단계별로 살펴봅니다. 백그라운드 서비스(Service)와 Timer, Handler를 조합하면 앱이 화면에 없어도 알림을 계속 발생시킬 수 있습니다.
1단계 — 새 프로젝트 생성
Android Studio에서 File ⇒ New Project 메뉴로 이동한 뒤, 새 프로젝트 생성에 필요한 정보를 모두 입력하고 프로젝트를 만듭니다.
2단계 — res/layout/activity_main.xml 작성
레이아웃 파일에 아래 코드를 추가합니다. 화면 가운데에는 버튼이 하나 배치되어 있으며, 이 버튼을 누르면 액티비티가 종료되고 그 이후부터는 서비스가 알림을 대신 표시하게 됩니다.
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="https://schemas.android.com/apk/res/android"
xmlns:tools="https://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16dp"
tools:context=".MainActivity">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_centerInParent="true"
android:onClick="closeApp"
android:text="close App for notification" />
</RelativeLayout>
3단계 — src/MainActivity 작성
메인 액티비티에 다음 코드를 추가합니다. 핵심은 onStop()입니다. 앱이 화면에서 사라지는 순간 알림 서비스가 시작되도록 처리했습니다.
package app.tutorialspoint.com.notifyme;
import android.content.Intent;
import android.os.Bundle;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
@Override
protected void onStop() {
super.onStop();
startService(new Intent(this, NotificationService.class));
}
public void closeApp(View view) {
finish();
}
}
4단계 — src/NotificationService 작성
실제로 알림을 주기적으로 생성하는 서비스 클래스입니다. Timer와 TimerTask로 반복 작업을 예약하고, Handler를 통해 알림을 생성합니다. 안드로이드 8.0(오레오) 이상에서는 알림 채널(Notification Channel) 생성 코드도 함께 포함되어 있습니다.
package app.tutorialspoint.com.notifyme;
import android.app.NotificationChannel;
import android.app.NotificationManager;
import android.app.Service;
import android.content.Intent;
import android.os.Handler;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
import android.util.Log;
import java.util.Timer;
import java.util.TimerTask;
public class NotificationService extends Service {
public static final String NOTIFICATION_CHANNEL_ID = "10001";
private final static String default_notification_channel_id = "default";
Timer timer;
TimerTask timerTask;
String TAG = "Timers";
int Your_X_SECS = 5;
@Override
public IBinder onBind(Intent arg0) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.e(TAG, "onStartCommand");
super.onStartCommand(intent, flags, startId);
startTimer();
return START_STICKY;
}
@Override
public void onCreate() {
Log.e(TAG, "onCreate");
}
@Override
public void onDestroy() {
Log.e(TAG, "onDestroy");
stopTimerTask();
super.onDestroy();
}
// TimerTask 내부에서 실행하기 위해 Handler를 사용합니다.
final Handler handler = new Handler();
public void startTimer() {
timer = new Timer();
initializeTimerTask();
timer.schedule(timerTask, 500000, Your_X_SECS * 1000);
}
public void stopTimerTask() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
public void initializeTimerTask() {
timerTask = new TimerTask() {
public void run() {
handler.post(new Runnable() {
public void run() {
createNotification();
}
});
}
};
}
private void createNotification() {
NotificationManager mNotificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getApplicationContext(), default_notification_channel_id);
mBuilder.setContentTitle("My Notification");
mBuilder.setContentText("Notification Listener Service Example");
mBuilder.setTicker("Notification Listener Service Example");
mBuilder.setSmallIcon(R.drawable.ic_launcher_foreground);
mBuilder.setAutoCancel(true);
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
int importance = NotificationManager.IMPORTANCE_HIGH;
NotificationChannel notificationChannel = new NotificationChannel(NOTIFICATION_CHANNEL_ID, "NOTIFICATION_CHANNEL_NAME", importance);
mBuilder.setChannelId(NOTIFICATION_CHANNEL_ID);
assert mNotificationManager != null;
mNotificationManager.createNotificationChannel(notificationChannel);
}
assert mNotificationManager != null;
mNotificationManager.notify((int) System.currentTimeMillis(), mBuilder.build());
}
}
알림 주기 조절 팁: timer.schedule(timerTask, 500000, Your_X_SECS * 1000)에서 두 번째 인수는 첫 알림까지의 지연 시간, 세 번째 인수는 반복 주기(밀리초 단위)입니다. 예제 코드에서는 Your_X_SECS = 5로 설정되어 있어 5초마다 알림이 표시됩니다. 실제로 5분 간격으로 알림을 받으려면 이 값을 300으로 변경하세요(300 × 1000 = 300,000밀리초 = 5분).
5단계 — AndroidManifest.xml 작성
매니페스트 파일에 진동(VIBRATE) 권한과 알림 서비스를 등록합니다. 서비스가 매니페스트에 선언되어 있어야 액티비티가 종료된 후에도 백그라운드에서 계속 동작할 수 있습니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android"
package="app.tutorialspoint.com.notifyme">
<uses-permission android:name="android.permission.VIBRATE" />
<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>
<service
android:name=".NotificationService"
android:label="@string/app_name">
<intent-filter>
<action android:name="app.tutorialspoint.com.notifyme.NotificationService" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</service>
</application>
</manifest>
앱 실행 및 결과 확인
이제 애플리케이션을 실행해 보겠습니다. 실제 안드로이드 모바일 기기가 컴퓨터에 연결되어 있다고 가정합니다. Android Studio에서 프로젝트의 액티비티 파일 중 하나를 연 뒤, 툴바의 Run(실행) 아이콘을 클릭하세요. 실행 옵션에서 연결된 모바일 기기를 선택하면, 기기의 기본 화면과 함께 앱이 구동되는 것을 확인할 수 있습니다.
버튼을 눌러 앱을 닫은 이후에도 서비스는 백그라운드에서 계속 실행되며, 설정한 주기마다 알림이 도착하는 것을 볼 수 있습니다.