개요
이 튜토리얼에서는 안드로이드의 AlarmManager(알람 매니저)를 사용하여 지정한 시간에 서비스(Service)를 자동으로 시작하는 방법을 알아봅니다. AlarmManager는 앱이 실행 중이 아니더라도 특정 시점에 작업을 예약 실행할 수 있게 해주는 강력한 시스템 서비스입니다.
전체 흐름은 다음과 같습니다. 버튼을 누르면 PendingIntent가 생성되고, AlarmManager가 3초 후에 서비스를 시작하도록 예약합니다. 별도의 버튼으로 예약된 알람을 취소할 수도 있습니다.
1단계: 새 프로젝트 만들기
Android Studio를 열고 File → New Project를 선택한 뒤, 필요한 정보를 모두 입력하여 새 프로젝트를 생성합니다.
2단계: 레이아웃 작성 (activity_main.xml)
res/layout/activity_main.xml 파일에 아래 코드를 추가합니다. 서비스 시작용 버튼과 취소용 버튼 두 개를 배치합니다.
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="https://schemas.android.com/apk/res/android"
android:id="@+id/activity_main"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="16sp"
android:orientation="vertical"
android:gravity="center_horizontal">
<Button
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:id="@+id/btnStartService"
android:text="Start Service Alarm"
android:layout_marginTop="30dp"/>
<Button
android:id="@+id/btnStopService"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginTop="10dp"
android:text="Cancel Service"/>
</LinearLayout>3단계: MainActivity 구현
src/MainActivity.java에 아래 코드를 작성합니다. 핵심 로직은 다음과 같습니다.
- PendingIntent.getService(): 서비스를 실행하기 위한 지연 인텐트를 생성합니다.
- Calendar: 현재 시간 기준 3초 후를 알람 발동 시각으로 설정합니다.
- alarmManager.set(): RTC_WAKEUP 모드로 알람을 등록하여, 기기가 절전 상태여도 깨워서 실행합니다.
package app.com.sample;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Intent;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.Calendar;
public class MainActivity extends AppCompatActivity {
Button btnStart, btnStop;
PendingIntent pendingIntent;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
btnStart = findViewById(R.id.btnStartService);
btnStop = findViewById(R.id.btnStopService);
btnStart.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent myIntent = new Intent(MainActivity.this, MyAlarmService.class);
pendingIntent = PendingIntent.getService(MainActivity.this, 0, myIntent, 0);
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
Calendar calendar = Calendar.getInstance();
calendar.setTimeInMillis(System.currentTimeMillis());
calendar.add(Calendar.SECOND, 3);
assert alarmManager != null;
alarmManager.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), pendingIntent);
Toast.makeText(MainActivity.this, "Starting Service Alarm", Toast.LENGTH_LONG).show();
}});
btnStop.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
assert alarmManager != null;
alarmManager.cancel(pendingIntent);
Toast.makeText(MainActivity.this, "Service Cancelled", Toast.LENGTH_LONG).show();
}
});
}
}4단계: MyAlarmService 클래스 생성
새 자바 클래스 MyAlarmService.java를 만들고 아래 코드를 추가합니다. 서비스 생명주기(onCreate(), onStart(), onDestroy() 등)가 호출될 때마다 토스트 메시지로 확인할 수 있도록 구성했습니다.
import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.widget.Toast;
public class MyAlarmService extends Service {
@Override
public void onCreate() {
Toast.makeText(this, "MyAlarmService.onCreate()", Toast.LENGTH_LONG).show();
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
Toast.makeText(this, "MyAlarmService.onBind()", Toast.LENGTH_LONG).show();
return null;
}
@Override
public void onDestroy() {
super.onDestroy();
Toast.makeText(this, "MyAlarmService.onDestroy()", Toast.LENGTH_LONG).show();
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
Toast.makeText(this, "MyAlarmService.onStart()", Toast.LENGTH_LONG).show();
}
@Override
public boolean onUnbind(Intent intent) {
Toast.makeText(this, "MyAlarmService.onUnbind()", Toast.LENGTH_LONG).show();
return super.onUnbind(intent);
}
}5단계: AndroidManifest.xml 설정
androidManifest.xml에 아래처럼 서비스를 반드시 등록해야 합니다. 서비스를 매니페스트에 선언하지 않으면 런타임 오류가 발생합니다.
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="https://schemas.android.com/apk/res/android" package="app.com.sample">
<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=".MyAlarmService" />
</application>
</manifest>앱 실행 및 결과 확인
실제 안드로이드 기기를 컴퓨터에 연결한 상태에서 프로젝트를 실행해 보겠습니다. Android Studio 툴바의 Run 아이콘을 클릭하고, 목록에서 연결된 모바일 기기를 선택하세요. 앱이 실행되면 기본 화면이 표시됩니다.




참고 사항
API 31(Android 12) 이상을 타겟팅하는 경우, PendingIntent 생성 시 가변성 플래그를 명시적으로 지정해야 합니다. 예를 들어 PendingIntent.getService(this, 0, myIntent, PendingIntent.FLAG_IMMUTABLE)처럼 작성하세요. 또한 정확한 알람이 필요하다면 SCHEDULE_EXACT_ALARM 권한 선언이 필요할 수 있습니다.
반복 작업이나 백그라운드 데이터 동기화가 목적이라면 최신 Android 개발에서는 WorkManager 사용이 권장되니, 용도에 맞게 선택하는 것이 좋습니다.