안녕하세요. 안드로이드 스튜디오에서 알람 앱을 개발 중인데, 평소 테스트 시에는 잘 울리지만 밤새 폰을 두었다가 아침(예: 7시)이 되면 알람이 울리지 않는 현상이 발생합니다. 기기는 갤럭시 S25 울트라이며, 배터리 최적화 제외, 알람 권한 등은 모두 허용 상태입니다.
코드는 AlarmManager.setAlarmClock을 사용하고 있고, 리시버에서 WakeLock을 잡고 포그라운드 서비스를 실행하는 구조입니다. 혹시 삼성 기기 특성이나 코드상에서 Doze 모드를 뚫지 못하는 부분이 있는지 고수님들의 조언 부탁드립니다.ㅜㅜ
간단한 팁이라도 부탁드려요 ㅠ
1. AndroidManifest.xml (권한 및 컴포넌트 설정)
xml
<uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" />
<uses-permission android:name="android.permission.USE_EXACT_ALARM" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
<uses-permission android:name="android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK" />
<uses-permission android:name="android.permission.USE_FULL_SCREEN_INTENT" />
<uses-permission android:name="android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS" />
<application ...>
<receiver android:name=".AlarmReceiver"
android:exported="true"
android:directBootAware="true" /> <!-- 다이렉트 부트 지원 -->
<service android:name=".AlarmPlaybackService"
android:foregroundServiceType="mediaPlayback"
android:exported="false" />
</application>
2. 알람 설정 부분 (MainActivity 내부)
java
private void setAlarm(int requestCode, String msg, long triggerAtMillis) {
AlarmManager am = (AlarmManager) mContext.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(mContext, AlarmReceiver.class);
intent.putExtra("msg", msg);
intent.putExtra("id", requestCode);
intent.addFlags(Intent.FLAG_RECEIVER_FOREGROUND); // 포그라운드 리시버 플래그
int flags = PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE;
PendingIntent sender = PendingIntent.getBroadcast(mContext, requestCode, intent, flags);
// 화면 깨우기용 PendingIntent
Intent showIntent = new Intent(mContext, MainActivity.class);
showIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);
PendingIntent showPendingIntent = PendingIntent.getActivity(mContext, requestCode, showIntent, flags);
try {
// setAlarmClock 사용 (Doze 모드에서도 울려야 함)
AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(triggerAtMillis, showPendingIntent);
am.setAlarmClock(alarmClockInfo, sender);
} catch (SecurityException se) {
// 권한 예외 처리 로직...
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, triggerAtMillis, sender);
}
}
3. AlarmReceiver.java (리시버)
java
public class AlarmReceiver extends BroadcastReceiver {
private static PowerManager.WakeLock sStaticWakeLock;
@Override
public void onReceive(Context context, Intent intent) {
// 1. 웨이크락 획득 (CPU가 잠들지 않게)
acquireStaticWakeLock(context);
// 2. 포그라운드 서비스 시작 시도
Intent serviceIntent = new Intent(context, AlarmPlaybackService.class);
serviceIntent.putExtras(intent.getExtras());
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
try {
ContextCompat.startForegroundService(context, serviceIntent);
} catch (Exception e) {
// 예외 발생 시 백업 노티피케이션 띄움
}
} else {
context.startService(serviceIntent);
}
}
private static void acquireStaticWakeLock(Context context) {
// WakeLock 획득 로직 (PARTIAL_WAKE_LOCK, 60초 타임아웃)
}
}
4. AlarmPlaybackService.java (서비스)
java
public class AlarmPlaybackService extends Service {
@Override
public void onCreate() {
super.onCreate();
// 리시버에서 잡은 WakeLock 해제 시도
AlarmReceiver.releaseStaticWakeLock();
// 서비스 자체 WakeLock 획득 (10분)
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
serviceWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Alarmgo:ServiceWakeLock");
serviceWakeLock.acquire(10 * 60 * 1000L);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
// [중요] 5초 이내에 startForeground 호출 필수
Notification notification = buildNotification(...);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
startForeground(notificationId, notification, ServiceInfo.FOREGROUND_SERVICE_TYPE_MEDIA_PLAYBACK);
} else {
startForeground(notificationId, notification);
}
// 미디어 재생 및 진동 시작...
return START_STICKY;
}
}
안드로이드 원래 조옷같이 알림씹는 버그있습니다. 삼성공식알람앱조차 가끔 알란십힘