2012-01-06 17 views
5

Para algunas aplicaciones de Android, me gustaría integrar la siguiente función: El usuario puede definir una hora en la que quiere que se le recuerde algo. Cuando llegue el momento, la aplicación debería crear una notificación en la barra de notificaciones, incluso cuando el usuario no use la aplicación en este momento.Crear notificación cronometrada (por ejemplo, para eventos) en Android

Para este propósito, las clases AlarmManager, NotificationManager y Notification.Builder son las que hay que mirar, ¿no?

Entonces, ¿cómo puedo crear una notificación cronometrada por adelantado? Mi código (hasta ahora) es la siguiente:

Añadir esto bajo la AndroidManifest para registrar el receptor de radiodifusión:

<receiver android:name="AlarmNotificationReceiver"></receiver> 

Crear un nuevo archivo de clase que se encarga de la alarma que recibe:

public class AlarmNotificationReceiver extends BroadcastReceiver { 

    public void onReceive(Context context, Intent intent) { 
     Bundle extras = intent.getExtras(); 
     if (extras != null) { 
      String additionalData = extras.getString("displayText"); 
      // show the notification now 
      NotificationManager mNotificationManager = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE); 
      Notification mNotification = new Notification(R.drawable.ic_launcher, context.getString(R.string.app_name), System.currentTimeMillis()); 
      PendingIntent pi = PendingIntent.getActivity(context, 0, new Intent(context, MainActivity.class), 0); // open MainActivity if the user selects this notification 
      mNotification.setLatestEventInfo(context, context.getString(R.string.app_name), additionalData, pi); 
      mNotification.flags |= Notification.FLAG_AUTO_CANCEL | Notification.DEFAULT_SOUND; 
      mNotificationManager.notify(1, mNotification); 
     } 
    } 

} 

utilizar este código (por ejemplo, en MainActivity) para ajustar la alarma a 3 segundos a partir de ahora:

Intent i = new Intent(this, AlarmNotificationReceiver.class); 
    i.putExtra("displayText", "sample text"); 
    PendingIntent pi = PendingIntent.getBroadcast(this.getApplicationContext(), 234324246, i, 0); 
    AlarmManager mAlarm = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE); 
    mAlarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+3*1000, pi); 

¿Qué necesito cambiar para que esto funcione? ¡Gracias!

Los dos problemas son:

  1. texto de la notificación no cambia cuando lo cambio en el código. Solo cambia cuando cambio el requestCode en PendingIntent.getBroadcast (...). ¿De qué se trata este código de solicitud? ¿Puede ser un valor aleatorio o 0?
  2. Después de reiniciar mi teléfono, la notificación "planificada" o la alarma desaparecen. Pero ahora he visto que esto es un comportamiento normal, ¿verdad? ¿Cómo puedo eludir esto?
+1

¿Qué no funciona hasta ahora? –

Respuesta

4

No estoy seguro acerca de la parte 1, pero para la parte 2, el enfoque general es interceptar el intento BOOT_COMPLETED y usarlo para volver a registrar todas las alarmas. Desafortunadamente, esto significa que, para cada alarma que haya registrado con el administrador de alarmas, también debe almacenarla en la base de datos de su aplicación.

Por lo tanto, se necesita un receptor de radio para interceptar la intención BOOT_COMPLETED:

public class BootReceiver extends BroadcastReceiver { 
    @Override 
    public void onReceive(Context context, Intent intent) { 
     // get your stored alarms from your database 
     // reregister them with the alarm manager 
    } 
} 

Para obtener la intención BOOT_COMPLETED, debe poner el siguiente permiso en su manifiesto:

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" /> 

Y el BootReceiver también necesita estar registrado en su manifiesto con el siguiente filtro de intención:

<receiver android:enabled="true" android:name=".receiver.BootReceiver" 
    android:permission="android.permission.RECEIVE_BOOT_COMPLETED"> 
     <intent-filter> 
       <action android:name="android.intent.action.BOOT_COMPLETED" /> 
       <category android:name="android.intent.category.DEFAULT" /> 
     </intent-filter> 
    </receiver> 

Es importante tener en cuenta que si su aplicación está instalada en la tarjeta SD, nunca podrá recibir el intento BOOT_COMPLETED. Además, vale la pena señalar que esta implementación es un poco ingenua ya que ejecuta el código inmediatamente al arrancar, lo que puede ralentizar el teléfono del usuario al inicio. Por lo tanto, le recomiendo retrasar su ejecución durante unos minutos después de interceptar el intento de arranque.

+0

¡Gracias! Realmente no hay otra manera de hacer esto? Esto suena un poco (demasiado) complejo. Necesita un permiso adicional y realizar esas acciones de registro. Bueno, ¿no es la cantidad de alarmas por aplicación limitada, de todos modos? Creo que todas las aplicaciones solo pueden registrar una alarma y luego se sobrescribirán las anteriores. ¿O es esta la regla para las notificaciones? – caw

+0

Desafortunadamente no hay otra manera de hacer esto. No estoy seguro de las limitaciones de las notificaciones, pero sé con certeza que puede registrar múltiples alarmas sin problema. – danh32

+0

Así que tengo que hacer lo que describiste aquí, está bien :) ¿Debo guardar los ID de estas alarmas? ¿O puedo simplemente crear nuevas alarmas sin almacenarlas? – caw

1

Personalmente lo haría sin un receptor de radiodifusión. Me gustaría que el AlarmManager activara la intención de iniciar una actividad separada, en lugar de un receptor. Entonces esta nueva actividad podría hacer la notificación por usted. No estoy seguro si esta es una mejor manera, pero me parece menos complicado.

Editar: Un servicio probablemente sería mejor aún que una actividad

En su MainActivity:

Intent i = new Intent(getBaseContext(), NotificationService.class); 
PendingIntent pi = PendingIntent.getService(getBaseContext(), 0, i, 0); 
AlarmManager mAlarm = (AlarmManager) Context.getSystemService(Context.ALARM_SERVICE); 
mAlarm.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()+10*60*1000, pi); 

del Servicio:

public class NotificationService extends Service { 

public int onStartCommand(Intent intent, int flags, int startId) { 

//Create the notification here 

return START_NOT_STICKY; 
} 

Su Manifiesto:

<service android:name="com.android.yourpath.NotificationService"></service> 
+0

¡Gracias! ¿Puedes explicar por qué usar un servicio es mejor que usar un servicio de transmisión? Encontré el ejemplo con transmisiones en varias páginas que cubren alarmas. – caw

+0

Realmente es una preferencia personal. Para mí, un Servicio parece una forma más simple porque solo está configurando la Alarma para ejecutar el Servicio en un momento determinado, en lugar de configurar la Alarma para ejecutar la Transmisión, y luego recibir la Transmisión para ejecutar la acción. Creo que tendrías que escribir una intención personalizada para que el método de difusión funcione. –

+0

Ah, está bien. Pero la documentación dice que un servicio es para tareas de fondo de larga duración. Así que pensé que debería usar una transmisión. Y en esta pregunta aquí (http://stackoverflow.com/questions/1026973/android-whats-the-difference-between-the- various-methods-to-get-a-context), dicen que no se debe usar getBaseContext();) – caw

Cuestiones relacionadas