본문 바로가기

나의 플랫폼/안드로이드

[Android] AlarmManager를 이용한 Schedule 관리

336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

우선, 미리 말씀을 드리겠습니다.


제가 테스트 해 본 결과, AlarmManager는 최소 5초 이상은 지정을 해야 합니다.

구글 에서는 10초 이상을 권장 하더라구요.

1초마다 지정을 할 경우는 5초마다 불러오게 됩니다.


그리고 도즈 모드에서는 적어도 10분 걸릴 수도 있다고 합니다.


그럼 만들어본 로직은 AlarmManager를 Repeat를 쓰지 않고 아래 형태로 호출하도록 하였습니다.


private void startAlram(Context context, PendingIntent pendingIntent, int delay) {

// AlarmManager 호출
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

// 1분뒤에 AlarmOneMinuteBroadcastReceiver 호출 한다.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
manager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);
} else {
manager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);
}
}


딜레이 시간에 따라 pendingIntent를 호출 하도록 만든 함수 입니다.

여기서 PendingIntent에는 BroadCastReceiver를 등록 시켰습니다.



public void startOneMinuteAlram(Context context) {

// AlarmOneMinuteBroadcastReceiver 초기화
Intent alarmIntent = new Intent(context, AlarmOneMinuteBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);

// 1분뒤에 AlarmOneMinuteBroadcastReceiver 호출 한다.
startAlram(context, pendingIntent, ONE_MINUES);
}

public void startFiveSecondAlram(Context context) {
// AlarmOneSecondBroadcastReceiver 초기화
Intent alarmIntent = new Intent(context, AlarmFiveSecondBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);

// 1초 뒤에 AlarmOneMinuteBroadcastReceiver 호출 한다.
startAlram(context, pendingIntent, FIVE_SECOND);
}

startOneMinuteAlarm은 1분 딜레이를 준 알람이 되는 것이고,

startFiveSecodeAlarm은 5초 딜레이를 준 알람이 됩니다.


이 함수를 자유롭게 부를 수 있도록 AlarmUtils 클래스에 묶었습니다.


package com.example.gorchg.alarmscheduler;

import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.Build;

import com.example.gorchg.alarmscheduler.receiver.AlarmOneMinuteBroadcastReceiver;
import com.example.gorchg.alarmscheduler.receiver.AlarmFiveSecondBroadcastReceiver;

/**
* Created by Ch on 2016-05-13.
*/
public class AlarmUtils {
private final static int FIVE_SECOND = 5 * 1000;
private final static int ONE_MINUES = 60 * 1000;

private static AlarmUtils _instance;

public static AlarmUtils getInstance() {
if (_instance == null) _instance = new AlarmUtils();
return _instance;
}

public void startOneMinuteAlram(Context context) {

// AlarmOneMinuteBroadcastReceiver 초기화
Intent alarmIntent = new Intent(context, AlarmOneMinuteBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);

// 1분뒤에 AlarmOneMinuteBroadcastReceiver 호출 한다.
startAlram(context, pendingIntent, ONE_MINUES);
}

public void startFiveSecondAlram(Context context) {
// AlarmOneSecondBroadcastReceiver 초기화
Intent alarmIntent = new Intent(context, AlarmFiveSecondBroadcastReceiver.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, alarmIntent, 0);

// 1초 뒤에 AlarmOneMinuteBroadcastReceiver 호출 한다.
startAlram(context, pendingIntent, FIVE_SECOND);
}

private void startAlram(Context context, PendingIntent pendingIntent, int delay) {

// AlarmManager 호출
AlarmManager manager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);

// 1분뒤에 AlarmOneMinuteBroadcastReceiver 호출 한다.
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
manager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
manager.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);
} else {
manager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + delay, pendingIntent);
}
}
}


AlarmOneMinuteBroadcastReceiver 와  AlarmFiveSecondBroadcastReceiver 는 AlarmBraodCastReciever를 상속 받습니다.


package com.example.gorchg.alarmscheduler.receiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import com.example.gorchg.alarmscheduler.Constants;

/**
* Created by Ch on 2016-05-13.
*/
public class AlarmBraodCastReciever extends BroadcastReceiver {
public static boolean isLaunched = false;

@Override
public void onReceive(Context context, Intent intent) {
isLaunched = true;

// 현재 시간을 화면에 보낸다.
saveTime(context);
}

private void saveTime(Context context) {
long currentTime = System.currentTimeMillis();
Intent intent = new Intent(Constants.INTENTFILTER_BROADCAST_TIMER);
intent.putExtra(Constants.KEY_DEFAULT, currentTime);
context.sendBroadcast(intent);
}
}


기본적으로 onReceive를 받으면 현재 시간을 INTENTFILTER_BROADCAST_TIMER IntentFilter를 가진 BroadCastReceiver로 보냅니다.

이 IntentFilter는 MainActivity에서 받아 TextView에 현재 시간을 뿌리게 됩니다.


package com.example.gorchg.alarmscheduler.receiver;

import android.content.Context;
import android.content.Intent;
import android.util.Log;

import com.example.gorchg.alarmscheduler.AlarmUtils;

import java.util.Date;

/**
* Created by Ch on 2016-05-13.
*/
public class AlarmFiveSecondBroadcastReceiver extends AlarmBraodCastReciever{

@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context,intent);

// 알람 스타트
AlarmUtils.getInstance().startFiveSecondAlram(context);

Log.d(getClass().getName(),"time second : "+new Date().toString());
}
}

 AlarmFiveSecondBroadcastReceiver 는 간단합니다. 알람 스타트 함수를 호출 시켜 주고 로그만 출력 하였습니다.


package com.example.gorchg.alarmscheduler;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.widget.TextView;

import com.example.gorchg.alarmscheduler.receiver.AlarmBraodCastReciever;

import java.util.Date;

public class MainActivity extends AppCompatActivity {

private TextView textView;
private int count;

private BroadcastReceiver mTimeReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
count++;
long time = intent.getLongExtra(Constants.KEY_DEFAULT,0);
if (time > 0) {
Date date = new Date(time);
textView.setText(date.toString()+"\n"+"call count : "+count);
}
}
};

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);

textView = (TextView) findViewById(R.id.txt_timer);
Date date = new Date();
textView.setText(date.toString());


if (!AlarmBraodCastReciever.isLaunched) {
AlarmUtils.getInstance().startFiveSecondAlram(this);
AlarmUtils.getInstance().startOneMinuteAlram(this);
}
}

@Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
}

@Override
protected void onResume() {
super.onResume();

registerReceiver(mTimeReceiver,new IntentFilter(Constants.INTENTFILTER_BROADCAST_TIMER));
}

@Override
protected void onPause() {
super.onPause();

unregisterReceiver(mTimeReceiver);
}
}

MainActivity는 AlarmManager에서 받은 현재 시간을 TextView에 뿌리는 것으로 모든 작업이 끝납니다.

isLaunched 변수는 AlarmManager가 한번만 실행 되도록 하기 위한 플래그 값입니다.


<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.gorchg.alarmscheduler">

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
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>

<receiver android:name=".receiver.AlarmOneMinuteBroadcastReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".receiver.AlarmFiveSecondBroadcastReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>

</manifest>

마지막으로 AndroidMenifest.xml에 두 알람 리시버를 지정합니다.

부팅이 처음 일어날때 실행하도록, Intentfilter를 지정 하였습니다.


결과 화면 입니다.



카운트가 5초마다 올라갑니다.

카운트가 12가 되었을 때, 토스트 팝업 창이 출력이 되는 화면 입니다.


테스트 용으로 만들어 보았습니다.

참고하세요.


문의 사항이 있으시면 언제든지 댓글 달아주세요.



## Repeat를 이용한 함수도 추가했습니다.


public void startRepeat(Context context, long delay) {
Intent alramIntent = new Intent(context, AlarmBraodCastReciever.class);
alramIntent.putExtra("name","Repeat");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1001, alramIntent, PendingIntent.FLAG_CANCEL_CURRENT);

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), delay, pendingIntent);
}


github : https://github.com/gorchg/AlarmScheduler