AlarmManager가 여러 장치에서 작동하지 않음


85

내 앱은 AlarmManager를 사용하며 4 년 전부터 작동하고 있습니다. 그러나 일부 장치에서 실패하기 시작했습니다.

코드가 옳다고 확신합니다 (WakefulBroadcastReceiver를 사용하고 있으며 Doze가있는 장치에 대해 setExactAndAllowWhileIdle을 사용하고 있습니다) .Nexus 장치에서 완벽하게 작동하기 때문에 일부 제조업체 (Huawei, Xiaomi ...)의 장치에서는 실패합니다.

예를 들어 화웨이 기기에는 앱을 종료하는 일종의 배터리 관리자가 있으며 앱이 종료되면 예약 된 알람이 취소됩니다. 따라서 Huawei 배터리 관리자에서 앱을 "보호됨"으로 설정하면 문제가 해결됩니다.

그러나 최근에 Xiaomi, Samsung (새로운 "Smart Manager"와 관련이있을 수 있습니까?)과 같은 더 많은 장치에서 작동하지 않는 것으로 나타났습니다.이 동작이 표준이되고있는 것 같습니다 : 백그라운드 앱을 종료하는 것입니다.

누구든지 그것에 대해 알고 있습니까? 경보가 울리도록 할 방법이 있습니까?

편집 :이 문제는 다른 제조업체에서 추가 한 "배터리 세이버"로 인해 발생합니다. 자세한 정보 : https://dontkillmyapp.com/


8
제조업체는 전력 소비에 대해 앱을 비난하고 있으며 코어가 적은 CPU에 비해 ​​더 많은 배터리를 소모하는 Octa- 코어를 계속 마케팅하고 있습니다. 단순히 코어를 추가하면 휴대폰 속도가 빨라질 것이라고 생각합니까?
FrozenFire

1
@AviLevinshtein 아마도 당신의 질문을 오해했습니다. 내 활동에서 알람을 만들고 있습니다. 그런 다음 알람이 울리면 브로드 캐스트 수신기가 실행되고 마지막으로 WakefulIntentService (@commonsware의 클래스)가 실행됩니다.
Sergio Viudes

2
@JFValdes 나는 여전히 해결책을 찾고 있습니다. AlarmManager는 Vanilla Android가 설치된 기기에서 완벽하게 작동합니다. 문제는 제조업체가 Android 기능을 "향상"하려고하는데 AlarmManager가 망가 졌다는 것입니다. 제조업체는 자체 "배터리 세이버"를 구현해서는 안됩니다. 표준 잠자기 모드를 사용하면 AlarmManager가 완벽하게 작동합니다. 솔루션에 대한 ...
세르지오 Viudes

1
아직 해결책이 있습니까? 리마인더와 같은 다른 앱은 어떻게 작동합니까? 경보,하지 알림을위한에서 setalarm 아닌 다른 옵션이있을이
kv1dr

1
@SergioViudes 나는 또한 추적을 위해 Xiomi 장치와 동일한 문제에 직면하고 있습니다. 다음 설정을 수행하여 4 개의 장치 중 3 개 장치에서 올바르게 작동하는 것보다 배터리 절약 제한에서 내 앱을 차단하는 경우--> 배터리로 이동-> 전원-> 앱 배터리 세이버-> 앱 이제 선택 (배경 설정에 대한) 제한 없음은 배경 위치에 대한 옵션을 허용하지 않습니다
이므 란 칸 사이 피를

답변:


17

나는 이미 몇 주 동안 그것을 해결하려고 노력하고 있습니다. 나는 아무것도 찾지 못했다. 화웨이는 잠시 후 모든 경보를 죽입니다. 배터리 세이버의 보호 된 앱에 앱을 넣으면 도움이되지 않습니다. 그러나 알람, 시계 또는 달력과 같은 단어를 포함하도록 앱의 패키지 이름을 변경하면 다른 장치와 마찬가지로 절대적으로 정상적으로 작동합니다. Google이이 쓰레기에 대한 인증을 제공하는 방법을 이해할 수 없습니다. OEM은 이러한 방식으로 핵심 플랫폼을 수정해서는 안된다고 생각합니다. 나는 그들이 사용자가 그것을 사용하지 않을 때 얼마 후에 앱을 죽이는 자체 배터리 세이버를 가지고 있음을 이해합니다. 그러나 이것은 보호 된 앱에 대한 경보이기도합니다.

정확한 타이밍 알람에 대한 setAlarmClock ()도 도움이됩니다. 그러나 위젯 업데이트와 같은 생각에는 이것을 사용할 수 없습니다.

업데이트 : 패키지 이름 키워드에 의한 보호는 현재 Huawei 장치에서 이미 작동하지 않으며 2017 년에도 마찬가지였습니다.


저와 마찬가지로 Xiaomi, Oppo, Huawei 브랜드 에서이 문제를 해결할 방법이 없습니다. 그들은 때때로 배터리를 절약하기 위해 백그라운드 프로세스와 알람을 종료합니다.
Andi Susilo

1
화웨이 전화가 있는데 패키지 이름을 알람 / 캘린더로 변경해도 아무 효과가 없습니다. 이 전화 매니저로부터 보호 응용 프로그램 목록에서 응용 프로그램을 추가 우회하는 유일한 방법
인 Ashish Pardhiye

9

문제는 Smart Manager입니다. 삼성에는 때때로 특정 앱이 백그라운드에서 실행되지 않도록하는 배터리 관리자가 있습니다. 앱으로 돌아갈 때 "재개"를 시도했지만 응용 프로그램을 완전히 비활성화하거나 5 분마다 재개 할 수 있습니다 (삼성에 따라 다름).

이것은 삼성 관리자가 없기 때문에 안드로이드의 재고 버전에서 작동합니다. SM을 활성화하는 몇 가지 기능이있는 Android의 사용자 지정 버전을 설치할 수도 있습니다 (ROM에 따라 다름).


테스트 할 삼성 기기가 없어서 미쳐 가고 있습니다. 내 앱 사용자가 말하는 내용 만 알고 있습니다. 앱이 종료되어 AlarmManager가 작동하지 않는 것이 문제인지 알고 있습니까? 아니면 그 관리자 때문에 알람이 울릴 때 장치가 깨어날 수 없다는 것이 문제입니까?
Sergio Viudes

@SergioViudes 최근 많은 회사가 자체적으로 구현하고 있습니다. LG와 같이 삼성과 비슷하게 작동하는 것이 있는데 휴대폰에 하나가있을 수 있습니까? 문제는 알람이 아니라 알람 앱이 완전히 비활성화 된 상태로 푸시됩니다. Smart Manager는 필요하지 않은 임의의 앱이라고 생각합니다. 특정 앱이 지나갈 수 있으며 스마트 관리자가 일부 앱을 수락 할 수 있습니다.
SA

1
@SergioViudes 나는 삼성 전자를 테스트하고 있는데 그것으로부터 얻을 수있는 것이 많지 않다고 말할 수 있습니다. 스마트 관리자가 앱을 최적화 할 때 오류나 아무것도 없으면 강제 종료와 유사하게 죽습니다. 그래도 여전히 최근 앱 목록에 있습니다
Tim

고마워 Tim. "스마트"관리자에서 앱을 제외하지 않고도이 문제를 해결하는 것이 좋습니다.
Sergio Viudes 2016

xiaomi (miui), vivo 및 htc와 같은 장치는 자체적으로 판단하는 것으로 보이는 "신뢰할 수있는"앱 목록에있는 앱이 아닌 경우 기본적으로 모든 권한을 false로 설정합니다 (whatsapp, truecaller 등은 기본적으로 신뢰 됨). ). 이것은 코더 악몽이되고있다
desidigitalnomad

3

대부분의 최신 Android 기기에는 자동으로 배터리 절약 방법을 알아 내려고 시도하는 앱 또는 메커니즘이 함께 제공되며 그 결과 특정 타사 앱이 종료 될 수 있습니다. 이로 인해 예약 된 작업 및 작업이 제거 될 수 있습니다 (예 : 알람이 울리지 않음, 푸시 알림이 작동하지 않음 등). 대부분의 경우 이것은 Android의 배터리 절약 메커니즘과 완전히 독립적으로 발생합니다. 제 경우에는 일부 장치 모델을 감지 할 때 더 많은 배터리를 최적화 할 수 없었고 사용자를 시작 관리자로 리디렉션하여 내 애플리케이션을 허용 목록에 추가했습니다.

모든 모델에 대해이 링크에서 https://android-arsenal.com/details/1/6771 을 호출해야하는 인 텐트를 찾았습니다.


2

5.0 미만 장치에는 AlarmManager를 사용하고 5.0 이상 장치에는 JobScheduler를 사용하십시오. JobScheduler가 제조업체의 헛소리에 영향을받지 않을 것이라고 확신 할 수는 없지만 Android가 사람들을 AlarmManager에서 JobScheduler로 옮기려고한다는 점을 감안할 때 나에게는 훨씬 덜 보일 것입니다.

수정 : Google은 WorkManager 라는이 문제에 대한 자사 솔루션을 제공했습니다 . 여러 스케줄링 프레임 워크를 추상화하고 장치에 가장 적합한 프레임 워크를 사용합니다.


2
불행히도 AlarmManager 클래스와 달리 JobScheduler를 사용할 때 타이밍이 정확하지 않습니다. 내 응용 프로그램에서 타이밍 :( 정확해야
세르지오 Viudes

나는 그것을 시도했고 일부 최적화 프로그램 (적어도 삼성)은 화면이 꺼지면 JobScheduler에서 보류중인 모든 작업을 종료합니다. 그래서 그것은 또한 깨졌습니다. 이것은 5.0에서 발생합니다. 6.0으로 업데이트 한 후에는 정상적으로 작동합니다. 아직 다른 제조업체와 테스트 할 수 없었습니다.
Sloy

정확한 타이밍을 위해 백그라운드 서비스 또는 예약 된 서비스를 사용할 수 없습니다. 포 그라운드 서비스를 시도 할 수 있지만이 경우 사용자에 대한 지속적인 알림 (아마도 바람직하지 않음)이 생성되고 일부 전화기에는 포 그라운드 서비스를 자동으로 파괴하는 태스크 킬러가 내장되어 있습니다. WorkManager는 최상의 솔루션이지만 안타깝게도 정확한 타이밍을 제공하지 않습니다.

1

알람 을 설정하는 앱도 있습니다. 해결책은 api> = 21에서 AlarmManager.setAlarmClock () 을 사용하는 것입니다 . 이것은 잠자기 afaik의 영향을받지 않으며 시스템 트레이에 알람 시계 아이콘을 추가하는 추가 보너스가 있습니다.


답변 해 주셔서 감사합니다. 알람 시계 아이콘을 제거 할 수있는 방법이 있습니까?
세르지오 Viudes

불행히도 setAlarmClock은 때때로 작동하지 않습니다. 메모리가 부족한 Oreo 장치에서 테스트했습니다.
Boris Salimov

0

요즘 대부분의 새 전화기에는 설명했던 것과 동일한 기능을 수행하는 일종의 배터리 / 절전 관리자가 번들로 제공됩니다. duboosters와 clean masters를 세지 않습니다.

제대로 작동하려면 앱 / 플레이 스토어 목록에이 앱을 배터리 관리자 앱의 예외에 넣어야한다는 면책 조항이나 FAQ를 넣어야한다고 생각합니다.


다른 방법이 있어야합니다 ... 사용자는 면책 조항을 읽지 않습니다. 나는 삼성 폰 앱은 알람 관리기 ... 사용하는 것을 허용하지 않는 것을 생각할 수 없다
세르지오 Viudes

알람은 "제 시간에"발생하지 않지만 결국 발생합니다
Gavriel

이것은 (슬프게도) 가장 유용한 대답입니다. 더 나은 솔루션이 있었으면 좋겠지 만 하드웨어 제조업체는 완벽하게 작동하는 바닐라 Android를 손상시키고 있습니다.
까악 까악

0

나는 얼마 전에 AlarmManager 사용을 중단했습니다 ... 더 좋고 안정적인 대안

  1. 서비스 생성
  2. BOOT_COMPLETED에 대한 BroadcastReceiver 등록
  3. 수신자로부터 서비스를 시작하십시오.
  4. X 분마다 자체적으로 반복되는 서비스 내에서 새 핸들러를 시작합니다 ( Android-postDelayed () 호출을 사용하여 주기적으로 메서드 실행 ).
  5. 작업을 실행할 시간이되었는지 확인하십시오. now-실행 시간> 0 ( Java에서 두 날짜 간의 차이 기간을 찾는 방법은 무엇입니까? )
  6. 그렇다면 .. 작업을 실행하고 핸들러를 중지합니다.

그래 .. 고통 스럽지만 일은 끝났어.


3
제안 해 주셔서 감사합니다.하지만 AlarmManager를 사용하면 RAM이나 리소스를 소비하지 않기 때문에 이러한 접근 방식을 피하고 싶습니다. 그리고 앱이 종료되면 서비스가 중지됩니다.
세르지오 Viudes

나는이 접근법이 BOOLETPROOF라고 말하지 않았지만, 적어도 다른 API 버전으로 구성되어 있습니다. :)
ymz

안정적으로 작동하려면이 솔루션이 wake lock을 사용해야하며 이는 엄청난 양의 배터리를 소모합니다.
Paweł Nadolski

나는 당신이 이것에 맞다고 생각합니다. 유일한 질문은 : 무엇이 최악일까요-신뢰할 수없는 코드 또는 나쁜 성능? 어쨌든, 개인적 으로 어떤 경우에 적합한 잠금대한 대안 이 있다고 생각합니다 (예 : stackoverflow.com/questions/5346694/… )
ymz

0

BOOT_COMPLETED를 듣고 있습니까? 장치가 재부팅되면 알람을 다시 설정해야합니다.


예. 제가 말했듯이 알람은 2012 년부터 지금까지 작동했습니다. 장치가 재부팅되면 BOOT_COMPLETED 브로드 캐스트 수신기에서 알람을 다시 예약합니다.
Sergio Viudes

1
앱이 다시 작동하기 위해 재부팅을 요구하는 것은 해결책의 반도 아닙니다
Tim

1
@TimCastelijns 그건 내가 말하는 것이 전혀 아닙니다. 장치가 재부팅되면 알람 관리자로 설정된 모든 알람을 다시 설정해야합니다.
Tyler Pfaff

@TylerPfaff 예,하지만 기기 재시작은이 질문의 문제와 관련이 없습니다
Tim

0

이 기기에서 실행중인 Android 버전은 무엇입니까?

API 23부터 OS 자체는 한동안 사용하지 않으면 저전력 유휴 모드로 전환되며 해당 모드에서는 경보가 전달되지 않습니다. 그러나 앱에서 "배터리 사용량에 관계없이이 시간에 울리려면이 알람이 필요합니다"라고 명시 적으로 말할 수있는 방법이 있습니다. setAndAllowWhileIdle()및 라는 새로운 AlarmManager 메서드 setExactAndAllowWhileIdle().

귀하의 설명에서 이것이 특정 OEM 장치에서 문제의 특정 원인이 아닌 것처럼 들리지만 이는 Alarm Manager를 사용하는 모든 개발자가 알아야 할 사항입니다.

마지막으로, 알람 관리자의 많은 사용은 작업 스케줄러의 메커니즘을 사용하여 더 잘 해결됩니다. 이전 버전과의 호환성을 위해 Play 서비스 "GCM Network Manager"는 실제로 기능면에서 작업 스케줄러와 매우 유사합니다. 즉, 최신 버전의 Android에서 내부적으로 작업 스케줄러를 사용하며 클래스 이름에도 불구하고 반드시 네트워킹에 관한 것은 아닙니다.


Smart Manager가 설치된 삼성 기기에서 Lollipop을 실행하고 있습니다. 이미 Marshmallow 장치에 setExactAndAllowWhileIdle을 사용하고 있습니다. JobScheduler와 GCM을 살펴 보겠습니다. 어쨌든 문제가 알람이 울리지 않는지 또는 알람이 울릴 때 해당 장치가 깨어나지 않는지 모르겠습니다.
Sergio Viudes

0

앱을 죽이면 알람 관리자가 앱을 깨우지 못할 것이라고 생각합니다.

"강제 중지"하거나 앱을 비활성화하는 경우에만 알람 관리자로부터 콜백을받지 않습니다.

근본 원인은 다른 것일 수 있습니다.

또한 M ... setExactAndAllowWhileIdle은 조절을 수행합니다. 즉, 2 분마다 알람을 예약하면 트리거되지 않습니다. ..15 분이 필요합니다. .


1
답변 해 주셔서 감사합니다. 그러나 그렇지 않다면 Smart Manager에서 "배터리 최적화"가 비활성화되어있을 때 앱이 완벽하게 작동하는 이유는 무엇입니까?
Sergio Viudes

앱 관리자 예 device..if 뿌리에 응용 프로그램을 실행하는 것은 .. 너무 응용 프로그램을 비활성화 할 수 있습니다
rupesh 자이나교

아니요, 루팅 된 기기에서 실행하지 않습니다.
Sergio Viudes

@rupeshjain "즉, 2 분마다 알람을 예약하면 트리거되지 않습니다. ..15 분 창이 있어야합니다." 이것은 완전히 사실이 아니며 그것이 사실이라면 진짜 문제입니다. setExactAndAllowWhileIdle 메서드에 대한 Android 문서 내에서 예약 시간 제한을 정확히 읽을 수 있습니다. 특정 애플리케이션에 대해 이러한 경보가 울리는 빈도에 대한 제한이 있습니다. 정상적인 시스템 작동에서는 저전력 유휴 모드에서이 기간이 15 분 더 길어질 수있는 경우 약 1 분 이상 이러한 경보를 발송하지 않습니다.
eyadMhanna

0

Xiaomi의 경우 앱에 대해 AutoStart를 활성화해야 할 수 있습니다. 백그라운드 프로세스에 영향을 줄 수있는 Android 수정 목록 (일반적으로 휴대폰 제조업체에서 제공)을 시도하고 있습니다. 새로운 것이 있으면 여기에 답변을 추가하십시오 Android 작업 킬러 목록


0

앱 관리자의 자동 시작 관리자, vivo v5와 같은 일부 핸드셋에서 앱을 활성화해야합니다.

In vivo v5에서는 iManager-> App Manager-> Auto Start Manager에서이 메뉴를 찾을 수 있습니다. 여기에서 앱을 활성화하십시오.

그러면 앱이 종료되거나 닫히면 알람 / 알람 관리자가 알람을 트리거합니다.


0

나는 대답을 찾고 있었고 몇 시간 후에 이것을 발견했습니다.

https://stackoverflow.com/a/35220476/3174791

이력서에서는 앱이 '보호 된 앱'에 의해 종료되었는지 확인하는 방법이며 이는 Huawei 장치에서만 작동합니다. 다른 장치 (삼성, 소니, 샤오 미 등)에 대한 솔루션이 있으면 알려주십시오.


0

늦을 수도 있지만 누군가에게 도움이되기를 바랍니다.

나는 오랫동안 같은 문제에 갇혀 있었다. 하지만 이제 저는이 문제를 해결하는 방법을 알고 있습니다. 이것은 같은 문제가있을 수있는 모든 사람을위한 것입니다. 사람들은 AutoStart 를 활성화해야한다고 계속 말하지만 저는 자동 시작을 사용하지 않고 관리했습니다.

우선, WakeFullBroadcastaReceiver는 이제 더 이상 사용되지 않으며 BroadcastReceiver를 사용해야합니다. 두 번째로 BackgroundService 대신 ForegroudService를 사용해야합니다.

다음에서 예를 들어 보겠습니다.

IntentService.class

public class NotificationService extends IntentService {


//In order to send notification when the app is close
//we use a foreground service, background service doesn't do the work.



public NotificationService() {
    super("NotificationService");
}

@Override
public void onCreate() {
    super.onCreate();

}

@Override
public int onStartCommand(@Nullable Intent intent, int flags, int startId) {
    super.onStartCommand(intent, flags, startId);

    //There is no difference in the result between start_sticky or start_not_sticky at the moment
    return START_NOT_STICKY;
}

@Override
protected void onHandleIntent(@Nullable Intent intent) {

    //TODO check if the app is in foreground or not, we can use activity lifecyclecallbacks for this

    startForegroundServiceT();
    sendNotification(intent);
    stopSelf();
}


/***
 * you have to show the notification to the user when running foreground service
 * otherwise it will throw an exception
 */
private void startForegroundServiceT(){

    if (Build.VERSION.SDK_INT >= 26) {
        String CHANNEL_ID = "my_channel_01";
        NotificationChannel channel = new NotificationChannel(CHANNEL_ID,
                "Channel human readable title",
                NotificationManager.IMPORTANCE_DEFAULT);

        ((NotificationManager) 
   getSystemService(Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);

        Notification notification = new Notification.Builder(this, CHANNEL_ID)
                .setContentTitle("")
                .setContentText("").build();

        startForeground(1, notification);
    }
}

private void sendNotification(Intent intent){

    //Send notification
    //Use notification channle for android O+
}
}

BroadcastReceiver.class 에서 포 그라운드 서비스 시작

public class AlarmReceiver extends BroadcastReceiver {


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


    Intent service = new Intent(context, NotificationService.class);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
        context.startForegroundService(service);
    } else {
        context.startService(service);
    }

}
}

그리고 setAlarms는 다음과 같습니다.

 public static void setAlarm(Context context, int requestCode, int hour, int minute){


    AlarmManager alarmManager =( AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
    Intent intent = new Intent(context//same activity should be used when canceling the alarm
            , AlarmReceiver.class);
    intent.setAction("android.intent.action.NOTIFY");

    //setting FLAG_CANCEL_CURRENT makes some problems. and doest allow the cancelAlarm to work properly
    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 1001, intent, 0);

    Calendar time = getTime(hour, minute);

    //set Alarm for different API levels
    if (Build.VERSION.SDK_INT >= 23){
        alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent);
    }
    else{
        alarmManager.set(AlarmManager.RTC_WAKEUP,time.getTimeInMillis(),pendingIntent);
    }

그런 다음 매니페스트에서 수신자와 foregroundservice를 선언해야합니다.

       <receiver android:name=".AlarmReceiver"
        android:enabled="true"
        android:exported="true">
        <intent-filter>
            <action android:name="android.intent.action.NOTIFY">

            </action>
        </intent-filter>
    </receiver>
    <service
        android:name=".NotificationService"
        android:enabled="true"
        android:exported="true"></service>

이것이 도움이되기를 바랍니다.

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.