Pergunta

Alarm not received during sleep.

I have an alarm set to midnight to update my view once the alarm goes off. The alarm works when the device is awake - have have tested this by changing the time to midnight etc. However when testing on my phone it does not work during sleep. I had my phone on sleep a few hours before midnight and then checked the app at around 8am. However the view did not update so i assumed the alarm was not received.

I have tried the following on the emulator - put the device to sleep just before midnight and then wake up the device after midnight. However i can see the data being updated and the alarm is recieved in my log.

Any ideas as to what i have done wrong in the below code?

Activity:

@Override
    protected void onResume(){
        super.onResume();
        updateReceiver = new AlarmReceiver(new AlarmReceiverCallback(){
            @Override 
            public void onAlarmReceived(Intent intent) {
                //update view code
            }
        });
        IntentFilter updateIntentFilter = new IntentFilter("alarm");
        registerReceiver(updateReceiver,updateIntentFilter);
    }

    @Override
    protected void onPause(){
        super.onPause();
        if(this.updateReceiver!=null){
            unregisterReceiver(updateReceiver);
        }
    }

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        //set up view 

        setRecurringDailyAlarm();
    }

    private void setRecurringDailyAlarm(){

        Calendar updateTime = Calendar.getInstance();
        updateTime.setTimeInMillis(System.currentTimeMillis());

        //daily alarm at midnight
        updateTime.set(Calendar.HOUR_OF_DAY,00);
        updateTime.set(Calendar.MINUTE,00);
        updateTime.set(Calendar.SECOND,00);
        Log.d(TAG, "Alarm time is: " + updateTime.getTime());
        Intent myIntent = new Intent();
        myIntent.setAction("alarm");
        PendingIntent recurringAlarm = PendingIntent.getBroadcast(MainActivity.this, ALARM_ID, myIntent, 
                PendingIntent.FLAG_CANCEL_CURRENT);
        AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

        alarms.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 
                AlarmManager.INTERVAL_DAY, recurringAlarm);

    }

Manifest:

        <category android:name="android.intent.category.LAUNCHER" />
    </intent-filter>
</activity>

<receiver android:name=".receiver.BootUpReceiver" android:enabled="true" android:exported="false" 
    android:permission="android.premission.RECEIVE_BOOT_COMPLETED">
    <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED" />
    <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
</receiver>
 <receiver android:name="com.test.receiver.RestartReceiver" android:enabled="true" android:process=":remote"></receiver>

==EDIT

If i change my code to Intent myIntent = new Intent(this, AlarmReceiver.class);

This will throw an error in my app as i have implemented the alarm receiver as follows. I am using a "callback" to update my UI

Alarm Receiver class:

    interface AlarmReceiverCallback{
    public void onAlarmReceived(Intent intent);
}

public class AlarmReceiver extends BroadcastReceiver{

    private AlarmReceiverCallback callback;

    public AlarmReceiver(AlarmReceiverCallback callback){
        this.callback = callback;
    }
    @Override
    public void onReceive(Context context, Intent intent) {
        callback.onAlarmReceived(intent);
    }
}

Error log:

01-25 16:05:38.655: D/dalvikvm(810): newInstance failed: no <init>()
01-25 16:05:38.686: D/AndroidRuntime(810): Shutting down VM
01-25 16:05:38.686: W/dalvikvm(810): threadid=1: thread exiting with uncaught exception (group=0x40a70930)
01-25 16:05:38.785: E/AndroidRuntime(810): FATAL EXCEPTION: main
01-25 16:05:38.785: E/AndroidRuntime(810): java.lang.RuntimeException: Unable to instantiate receiver com.test.receiver.AlarmReceiver: java.lang.InstantiationException: can't instantiate class com.test.receiver.AlarmReceiver; no empty constructor
01-25 16:05:38.785: E/AndroidRuntime(810):  at android.app.ActivityThread.handleReceiver(ActivityThread.java:2357)
01-25 16:05:38.785: E/AndroidRuntime(810):  at android.app.ActivityThread.access$1500(ActivityThread.java:141)
01-25 16:05:38.785: E/AndroidRuntime(810):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1310)
01-25 16:05:38.785: E/AndroidRuntime(810):  at android.os.Handler.dispatchMessage(Handler.java:99)
01-25 16:05:38.785: E/AndroidRuntime(810):  at android.os.Looper.loop(Looper.java:137)
01-25 16:05:38.785: E/AndroidRuntime(810):  at android.app.ActivityThread.main(ActivityThread.java:5039)
01-25 16:05:38.785: E/AndroidRuntime(810):  at java.lang.reflect.Method.invokeNative(Native Method)
01-25 16:05:38.785: E/AndroidRuntime(810):  at java.lang.reflect.Method.invoke(Method.java:511)
01-25 16:05:38.785: E/AndroidRuntime(810):  at
Foi útil?

Solução

You should register the receiver you use to catch the alarms in your manifest along with your other receivers. Then create your intent to launch the AlarmReceiver.

When you do it in code, as you are, it's unregistered in onPause, so if your activity isn't in the foreground when the alarm fires, it's not going to catch it.

Manifest:

<receiver android:name="com.test.receiver.AlarmReceiver"
/>

Code:

private void setRecurringDailyAlarm(){

    Calendar updateTime = Calendar.getInstance();
    updateTime.setTimeInMillis(System.currentTimeMillis());

    //daily alarm at midnight
    updateTime.set(Calendar.HOUR_OF_DAY,00);
    updateTime.set(Calendar.MINUTE,00);
    updateTime.set(Calendar.SECOND,00);
    Log.d(TAG, "Alarm time is: " + updateTime.getTime());

    Intent myIntent = new Intent( this, AlarmReceiver.class );
    PendingIntent recurringAlarm = PendingIntent.getBroadcast( MainActivity.this, ALARM_ID, myIntent, PendingIntent.FLAG_CANCEL_CURRENT);
    AlarmManager alarms = (AlarmManager)getSystemService(Context.ALARM_SERVICE);

    alarms.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), 
            AlarmManager.INTERVAL_DAY, recurringAlarm);
}
Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top