I've got a problem with AlarmManager.
In short, I plan an alarmManager :
Intent intent = new Intent(context, MyActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delayInMs, pendingIntent);
And the activity MyActivity appears at the specified time. Just when the device is plugged. It also works when it is in my pocket, or when the delay is a few minutes. But when I set the alarmManager before night, it won't work in the morning. However, it will work as soon as I take the phone or unlock the screen.
So, I suppose it is due to a sleep mode of the device, but how solve this ?
1) I added a log in every methods of myActivity, and I'm sure no one is called before I manually wake the device. 2) I tried PowerManagement's wake lock (with the WAKE_LOCK permission in manifest), but nothing changed :
alarmManager.setExact(.........);
wakeLock = ((PowerManager)contexte.getSystemService(Context.POWER_SERVICE)).newWakeLock(PowerManager.PROXIMITY_SCREEN_OFF_WAKE_LOCK, "MyActivity");
wakeLock.acquire();
Please, help ! I'm sure I'm so close...
EDIT Dec 04'16 : Thanks to Nick Friskel and Vikram Rao, I changed my initial code to call a broadcastReceiver and acquire my wakeLock in the onReceive. Unfortunately, it doesn't seem to work. It perfectly works when the phone is plugged or when the alarm is planned 35 minutes later, but for a complete night, the onReceive isn't even called. I tried that night, with an alarm planned at 9:00 AM, but the onReceive was only executed at 9:46 AM, that means the moment where I unlocked the device. Here's my new code :
Intent intent = new Intent("com.blah.something.ALARM_RECEIVED");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + delayInMs, pendingIntent);
That said, my log writing "start of onReceive" wasn't really at the beginning of the listener for some reason. I just managed to put it at the real beginning, so I'll see if the listener is called or not.
EDIT Dec 05'16 : So, I changed the log writing, at the top of the onReceive, and the same problem happened : the start of the onReceive is called as soon as I manually wake the device. I can implement the wakefulBroadcastReceiver, but I fear it won't solve anything. If I understood correctly, the wakefulBroadcastReceiver is useful to prevent the device to sleep between onReceive and the launch of the activity or service. But what if the onReceive isn't even called ? I'm a bit desperate... Maybe should I directly ask Sony. Furthermore, my phone has stamina mode, but it isn't activated.
EDIT Dec 11'16 : So, with more tests, I'm now sure that I understand nothing.... I set a broadcastReceiver which activates every 5 minutes (the onReceive resets the alarmManager 5 minutes later), and I can see it's perfectly working... sometimes. It can last several hours, and sleep for two hours, then ok for 30 minutes, then back to sleep. (all that when my phone is on, unplugged and idle). I'm going to remove ALL the code but what interests us. It will be easier to understand and I will be able to write here all the active code.
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.par.hasard.mysimpleapplication">
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<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="com.par.hasard.mysimpleapplication.MySimpleReceiver">
<intent-filter android:priority="1">
<action android:name="com.par.hasard.mysimpleapplication.REGULAR_ALARM" />
</intent-filter>
</receiver>
</application>
</manifest>
MainActivity.java
package com.par.hasard.mysimpleapplication;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button button = (Button)findViewById(R.id.myExportButton);
button.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View view) {
MyLogManager.copyLogToClipboard(view.getContext());
MyLogManager.emptyLogFile(view.getContext());
}
});
try {
MyLogManager.createLogFile(this);
MyLogManager.write(this, "Application launched\n");
MyAlarmPlanner.planAlarm(this);
} catch (Exception e) {
e.printStackTrace();
}
}
}
MySimpleReceiver.java
package com.par.hasard.mysimpleapplication;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
public class MySimpleReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
try {
MyLogManager.write(context, "Beginning of onReceive\n");
MyAlarmPlanner.planAlarm(context);
MyLogManager.write(context, "End of onReceive\n");
} catch (Exception e) {
e.printStackTrace();
}
}
}
MyAlarmPlanner.java
package com.par.hasard.mysimpleapplication;
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.os.SystemClock;
import java.io.IOException;
public class MyAlarmPlanner {
public static void planAlarm(Context context) throws IOException {
MyLogManager.write(context, "Beginning of alarm planning\n");
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent("com.par.hasard.mysimpleapplication.REGULAR_ALARM");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
alarmManager.cancel(pendingIntent);
alarmManager.setExact(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + 300000, pendingIntent);
MyLogManager.write(context, "End of alarm planning\n");
}
}
I don't think MyLogManager.java is useful, it's just boring files management methods.
Content of log file after a long idle time :
12/12 15h33m23s380 => Beginning of onReceive
12/12 15h33m23s381 => Beginning of alarm planning
12/12 15h33m23s383 => End of alarm planning
12/12 15h33m23s384 => End of onReceive
12/12 15h38m24s337 => Beginning of onReceive
12/12 15h38m24s339 => Beginning of alarm planning
12/12 15h38m24s375 => End of alarm planning
12/12 15h38m24s376 => End of onReceive
12/12 15h43m24s375 => Beginning of onReceive
12/12 15h43m24s376 => Beginning of alarm planning
12/12 15h43m24s380 => End of alarm planning
12/12 15h43m24s381 => End of onReceive
12/12 15h48m25s301 => Beginning of onReceive
12/12 15h48m25s304 => Beginning of alarm planning
12/12 15h48m25s307 => End of alarm planning
12/12 15h48m25s308 => End of onReceive
12/12 15h53m25s316 => Beginning of onReceive
12/12 15h53m25s318 => Beginning of alarm planning
12/12 15h53m25s328 => End of alarm planning
12/12 15h53m25s329 => End of onReceive
12/12 15h58m25s328 => Beginning of onReceive
12/12 15h58m25s329 => Beginning of alarm planning
12/12 15h58m25s331 => End of alarm planning
12/12 15h58m25s333 => End of onReceive
12/12 16h3m26s336 => Beginning of onReceive
12/12 16h3m26s351 => Beginning of alarm planning
12/12 16h3m26s379 => End of alarm planning
12/12 16h3m26s380 => End of onReceive
12/12 16h8m26s397 => Beginning of onReceive
12/12 16h8m26s401 => Beginning of alarm planning
12/12 16h8m26s404 => End of alarm planning
12/12 16h8m26s405 => End of onReceive
12/12 16h13m26s406 => Beginning of onReceive
12/12 16h13m26s407 => Beginning of alarm planning
12/12 16h13m26s410 => End of alarm planning
12/12 16h13m26s411 => End of onReceive
12/12 16h18m27s328 => Beginning of onReceive
12/12 16h18m27s329 => Beginning of alarm planning
12/12 16h18m27s346 => End of alarm planning
12/12 16h18m27s348 => End of onReceive
12/12 16h23m28s298 => Beginning of onReceive
12/12 16h23m28s299 => Beginning of alarm planning
12/12 16h23m28s303 => End of alarm planning
12/12 16h23m28s304 => End of onReceive
12/12 16h28m29s308 => Beginning of onReceive
12/12 16h28m29s310 => Beginning of alarm planning
12/12 16h28m29s323 => End of alarm planning
12/12 16h28m29s324 => End of onReceive
12/12 16h33m29s339 => Beginning of onReceive
12/12 16h33m29s340 => Beginning of alarm planning
12/12 16h33m29s355 => End of alarm planning
12/12 16h33m29s361 => End of onReceive
12/12 16h38m29s356 => Beginning of onReceive
12/12 16h38m29s357 => Beginning of alarm planning
12/12 16h38m29s360 => End of alarm planning
12/12 16h38m29s361 => End of onReceive
12/12 16h43m29s364 => Beginning of onReceive
12/12 16h43m29s365 => Beginning of alarm planning
12/12 16h43m29s367 => End of alarm planning
12/12 16h43m29s369 => End of onReceive
12/12 16h48m29s376 => Beginning of onReceive
12/12 16h48m29s380 => Beginning of alarm planning
12/12 16h48m29s390 => End of alarm planning
12/12 16h48m29s394 => End of onReceive
12/12 16h53m29s392 => Beginning of onReceive
12/12 16h53m29s394 => Beginning of alarm planning
12/12 16h53m29s402 => End of alarm planning
12/12 16h53m29s403 => End of onReceive
12/12 17h43m33s986 => Beginning of onReceive //problem, the 16'58 onReceive wasn't called
12/12 17h43m33s988 => Beginning of alarm planning
12/12 17h43m33s996 => End of alarm planning
12/12 17h43m34s4 => End of onReceive
12/12 17h48m34s535 => Beginning of onReceive
12/12 17h48m34s536 => Beginning of alarm planning
12/12 17h48m34s539 => End of alarm planning
12/12 17h48m34s540 => End of onReceive
12/12 18h29m49s635 => Beginning of onReceive //the moment I turned on my device
12/12 18h29m49s648 => Beginning of alarm planning
12/12 18h29m49s667 => End of alarm planning
12/12 18h29m49s668 => End of onReceive
Can someone tell me where is my mistake ?
AlarmManager is a bridge between application and Android system alarm service. It can send a broadcast to your app (which can be completely terminated by user) at a scheduled time and your app can then perform any task accordingly.
There are two general clock types for alarms: "elapsed real time" and "real time clock" (RTC). Elapsed real time uses the "time since system boot" as a reference, and real time clock uses UTC (wall clock) time.
Navigate to the app > res > layout > activity_main. xml and add the below code to that file. In this file, we have added two items 'TimePicker' and 'ToggleButton'. TimePicker is used to capture the alarm time and ToggleButton is added to set the alarm on or off.
Thanks to CommonsWare, the problem is solved ! This fail is due to doze mode (https://developer.android.com/training/monitoring-device-state/doze-standby.html) In short, since Android 6.0, AlarmManager is impacted and cannot fire if the device is in this doze mode. But you can replace setExact by setExactAndAllowWhileIdle. There are limitations but we have to deal with. There's the link to the post where CommonsWare answered : sendWakefulWork not always called with cwac-wakeful-1.1.0
AlarmManager api in android has its limitations. For -
They way I have worked around these is -
Like this -
Intent intent = new Intent("com.blah.something.ALARM_RECIEVED");
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, requestCode, intent, PendingIntent.FLAG_ONE_SHOT);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(Html5Activity.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC, triggerTimeInMillis, pendingIntent);
manifest file -
<receiver android:name=".receiver.BackgroundScheduledAlarmReceiver">
<intent-filter android:priority="1">
<action android:name="com.blah.something.ALARM_RECIEVED" />
</intent-filter>
</receiver>
manifest file -
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
...
<receiver
android:name=".receiver.RecreateAlarmsAtBootReceiver"
android:enabled="true"
android:exported="true"
android:label="RecreateAlarmsAtBootReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
In RecreateAlarmsAtBootReceiver
, read the sqlite storing alarms and adds them to alarm manager again.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With