Source: link
Github: link
You need to create a service to execute your requests in the background and you should not place your notification code inside the Oncreate () method. Maybe this is happening.
I advise you to register two BroadcastReceivers, and a service and also get permission to use wakelock, getting Boot_Completed signal.
AndroidManifest.xml:
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<application>
<receiver android:name=".service.OnBootReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
<receiver android:name=".service.OnAlarmReceiver" >
</receiver>
<service android:name=".service.TaskButlerService" >
</service>
</application>
This is a complete ONBOOT BroadcastReceiver used to reschedule alarms with AlarmManager. There are only 2 lines of code in the OnReceive () method, which is because your own OnReceive () is necessarily short. The first line gets a partial wakelock to keep the CPU running while our IntentService is running.
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
/**
* BroadCastReceiver para android.intent.action.BOOT_COMPLETED
* passa toda a responsabilidade para TaskButlerService.
* @author Dhimitraq Jorgji
*
*/
public class OnBootReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
WakefulIntentService.acquireStaticLock(context); //acquire a partial WakeLock
context.startService(new Intent(context, TaskButlerService.class)); //start TaskButlerService
}
}
IntentService is my favorite way of doing things in the background. Normally I do not put IntentService directly, and I suggest you do the same; set a synchronized method to get a wakelock before proceeding with what you need to accomplish.
import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.os.PowerManager;
/**
* Acquires a partial WakeLock, allows TaskButtlerService to keep the CPU alive
* until the work is done.
* @author Dhimitraq Jorgji
*
*/
public class WakefulIntentService extends IntentService {
public static final String
LOCK_NAME_STATIC="edu.worcester.cs499summer2012.TaskButlerService.Static";;
public static final String
LOCK_NAME_LOCAL="edu.worcester.cs499summer2012.TaskButlerService.Local";
private static PowerManager.WakeLock lockStatic=null;
private PowerManager.WakeLock lockLocal=null;
public WakefulIntentService(String name) {
super(name);
}
/ **
* Para Adquirir um wakelock estático, é preciso também chamar esta dentro da classe
* Que chama StartService ()
*
* /
public static void acquireStaticLock(Context context) {
getLock(context).acquire();
}
synchronized private static PowerManager.WakeLock getLock(Context context) {
if (lockStatic==null) {
PowerManager
mgr=(PowerManager)context.getSystemService(Context.POWER_SERVICE);
lockStatic=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
LOCK_NAME_STATIC);
lockStatic.setReferenceCounted(true);
}
return(lockStatic);
}
@Override
public void onCreate() {
super.onCreate();
PowerManager mgr=(PowerManager)getSystemService(Context.POWER_SERVICE);
lockLocal=mgr.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
LOCK_NAME_LOCAL);
lockLocal.setReferenceCounted(true);
}
@Override
public void onStart(Intent intent, final int startId) {
lockLocal.acquire();
super.onStart(intent, startId);
getLock(this).release();
}
@Override
protected void onHandleIntent(Intent intent) {
lockLocal.release();
}
}
Now we can simply inherit the WakeFulIntentService, and do all of our work with a simple onHandleIntent (Intent) method. The method can be called from anywhere in your program and it will take care of everything in a background like any Service, also in a safe way, since it holds a wakelock until the method finishes at the point where it returns the closing.
import java.util.List;
import android.content.Intent;
import edu.worcester.cs499summer2012.database.TasksDataSource;
import edu.worcester.cs499summer2012.task.Task;
/ **
* Uma IntentService cuida da criação de alarmes para Task Butler
* Para lembrar o usuário de eventos
* author Dhimitraq Jorgji
*
* /
public class TaskButlerService extends WakefulIntentService{
public TaskButlerService() {
super("TaskButlerService");
}
@Override
protected void onHandleIntent(Intent intent) {
TasksDataSource db = TasksDataSource.getInstance(this); //get access to the instance of TasksDataSource
TaskAlarm alarm = new TaskAlarm();
List<Task> tasks = db.getAllTasks(); //Get a list of all the tasks there
for (Task task : tasks) {
// Cancelar alarme existente
alarm.cancelAlarm(this, task.getID());
//alarmes de aviso
if(task.isPastDue()){
alarm.setReminder(this, task.getID());
}
//alarmes de repetição
if(task.isRepeating() && task.isCompleted()){
task = alarm.setRepeatingAlarm(this, task.getID());
}
//alarmes regulares
if(!task.isCompleted() && (task.getDateDue() >= System.currentTimeMillis())){
alarm.setAlarm(this, task);
}
}
super.onHandleIntent(intent);
}
}
At this point, you only need a BroadcastReceiver to receive your alarms.
package edu.worcester.cs499summer2012.service;
import edu.worcester.cs499summer2012.database.TasksDataSource;
import edu.worcester.cs499summer2012.task.Task;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.os.Bundle;
/**
* BroadCastReceiver for Alarms, displays notifications as it receives alarm
* and then starts TaskButlerService to update alarm schedule with AlarmManager
* @author Dhimitraq Jorgji
*
*/
public class OnAlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
WakefulIntentService.acquireStaticLock(context); //adquirindo WakeLock
//enviando notificação com taskID
NotificationHelper notification = new NotificationHelper();
Bundle bundle = intent.getExtras();
int id = bundle.getInt(Task.EXTRA_TASK_ID);
TasksDataSource db = TasksDataSource.getInstance(context);
Task task = db.getTask(id);
if(task.hasFinalDateDue() || task.getPriority() == Task.URGENT){
notification.sendPersistentNotification(context, task); // Básica notificação
} else {
notification.sendBasicNotification(context, task); //Básica notificação
}
context.startService(new Intent(context, TaskButlerService.class)); //iniciando TaskButlerService
}
}