jueves, 20 de febrero de 2014

Android: Setting up an alarm

Alarms can be set through the system sevice AlarmManager (context.getSystemService(Context.ALARM_SERVICE)). The problem with alarms is that once the device is shut down the alarms are erased this is why we need Android to give us time when the device has finished booting. To "ask" Android to call us after the device has finished booting we need to implement a BroadcastReceiver who receives the android.intent.action.BOOT_COMPLETED message.

In the following example I have a database with the alarms.

OnBootReceiver (receives android.intent.action.BOOT_COMPLETED messages and sets alarms)

public class OnBootReceiver extends BroadcastReceiver {

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

DatabaseHelper helper = DatabaseHelper.getInstance();

Cursor cursor = helper.getAllAlarms();

cursor.moveToFirst();

while (!cursor.isAfterLast())  {

setAlarm(context, helper.getAlarmFromCursor(cursor));
 
   cursor.moveToNext();
}

helper.close();

}

public static void setAlarm(Context context, Alarm alarm) {

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.set(AlarmManager.RTC_WAKEUP, alarm.getTimeInMillis(), getPendingIntent(context, alarm.getId()));
}

public static void cancelAlarm(Context context, Alarm alarm) {

AlarmManager alarmManager = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(getPendingIntent(context, alarm));
}

private static PendingIntent getPendingIntent(Context context, Alarm alarm) {

Intent intent = new Intent(context, OnAlarmReceiver.class);
intent.putExtra(OnAlarmReceiver.ALARM_ID, alarm.getId());

return PendingIntent.getBroadcast(context, (int) alarmId, intent, 0);
}
}


Manifest
For boot receiver add
<receiver
            android:name="ar.com.fennoma.reporttv.alarm.OnBootReceiver"
            android:enabled="true" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

OnAlarmReceiver (Receives the pendingIntent from OnBootReceiver)

public class OnAlarmReceiver extends BroadcastReceiver {

public static final String ALARM_ID = "ALARM_ID";

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

if (isProcessAliveAndInForeground(context)) {
this.createAlertView(context, intent);
}
else {

this.createNotification(context, intent);
}
}

private void createAlertView(Context context, Intent intent) {

DatabaseHelper helper = DatabaseHelper.getInstance();

Notification notification = helper.getNotification(intent.getLongExtra(ALARM_ID, -1));

helper.deleteNotification((int) notification.getCalendaredProgramId());

helper.close();

Intent i = new Intent(context, MainActivity.class);
i.putExtra(MainActivity.SHOW_ALARM_NOTIFICATION, true);
i.putExtra(MainActivity.NOTIFICATION, notification);
        i.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        context.startActivity(i);
}

private void createNotification(Context context, Intent intent) {

DatabaseHelper helper = DatabaseHelper.getInstance();

Notification notification = helper.getNotification(intent.getLongExtra(ALARM_ID, -1));

helper.deleteNotification((int) notification.getCalendaredProgramId());

SimpleDate programStartingDate = new SimpleDate(notification.getProgramStartingDateInMillis());

String time = SimpleDate.getPrettyHour(programStartingDate.getHours(), programStartingDate.getMinutes());

String message = String.format("%s empezará a las %s en el canal %s", notification.getProgramName(), time,
notification.getSignName());

NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(context).setSmallIcon(R.drawable.notification_icon)
.setContentTitle("ReporTV").setContentText(message);

Intent resultIntent = new Intent(context, MainActivity.class);
resultIntent.putExtra(MainActivity.SHOW_ALARM_NOTIFICATION, true);
resultIntent.putExtra(MainActivity.NOTIFICATION, notification);

// The stack builder object will contain an artificial back stack for the started Activity.
// This ensures that navigating backward from the Activity leads out of your application to the Home screen.
TaskStackBuilder stackBuilder = TaskStackBuilder.create(context);
// Adds the back stack for the Intent (but not the Intent itself)
// stackBuilder.addParentStack(MainActivity.class);
// Adds the Intent that starts the Activity to the top of the stack
stackBuilder.addNextIntent(resultIntent);

PendingIntent resultPendingIntent = stackBuilder.getPendingIntent(0, PendingIntent.FLAG_UPDATE_CURRENT);
mBuilder.setContentIntent(resultPendingIntent);
NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);
// mId allows you to update the notification later on.
mNotificationManager.notify((int) notification.getId(), mBuilder.build());

helper.close();
}

private boolean isProcessAliveAndInForeground(Context context) {

return BaseActivity.isVisible();
}
}


Manifest
In this case simple add
<receiver android:name="ar.com.fennoma.reporttv.alarm.OnAlarmReceiver" />


No hay comentarios:

Publicar un comentario