J'ai donc pris le parti de convertir tout ça en notifications. C'est super, ça fonctionne bien. Et puis je me dis qu'ajouter la possibilité d'annuler le téléchargement serait une bonne idée. Et c'est là que la rage commence.
Mon programme télécharge les fichiers via des AsyncTask. Dans le constructeur, j'initialise ma notification (NotificationCompat), et le manager (NotificationManager). Un peu de code vaut mieux qu'un pavé, alors voici.
public DownloaderTask(Context ctx, SearchMatch trackInfo) {
_context = ctx;
_trackInfo = trackInfo;
_notification = new NotificationCompat.Builder(_context);
_notificationManager = (NotificationManager)_context.getSystemService(Context.NOTIFICATION_SERVICE);
if (ImageCache.HasImage(_trackInfo.album.id))
_notification.setLargeIcon(ImageCache.GetImageBitmap(_trackInfo.album.id));
_notification.addAction(android.R.drawable.ic_menu_close_clear_cancel, "Cancel", GetCancelIntent());
}
protected PendingIntent GetCancelIntent()
{
Intent buttonIntent = new Intent("org.warpten.yadda.stopdownload");
buttonIntent.putExtra("notificationId", _trackInfo.id);
return PendingIntent.getBroadcast(_context, 1, buttonIntent, PendingIntent.FLAG_ONE_SHOT);
}
public class CancelReceiver extends BroadcastReceiver {
interface ICancelReceiver
{
void CancelDownload(int trackId);
}
public static ICancelReceiver Listener;
@Override
public void onReceive(Context context, Intent intent) {
int notificationId = intent.getIntExtra("notificationId", -1);
if (Listener != null && notificationId != -1)
Listener.CancelDownload(notificationId);
}
}
Le receiver est déclaré dans AndroidManifest.xml avec le bon filtre.
Ici ICancelReceiver est implémenté par l'activité qui lance les tâches asynchrones, c'est elle qui gère leur cycle de vie (elle les interrompt, et l'interruption de la tâche conduit à la suppression de la notification). L'implémentation de l'interface ressemble à ça:
@Override
public void CancelDownload(int trackId) {
if (!_tasks.containsKey(trackId))
return;
_tasks.get(trackId).cancel(true);
_tasks.remove(trackId);
}
Alors ça donne quoi? Ma notification s'affiche, c'est nickel, mais je ne peux pas déclencher ma PendingIntent: mes "clics" passent à travers, et si je change le fonctionnement pour assigner la PendingIntent au contenu (Notification.Builder.setContentIntent) au lieu d'une action, alors tout fonctionne très bien.
Il n'y a qu'un seul moment où je peux interagir avec l'action définie: quand la notification n'est plus mise à jour avec la progression du téléchargement. Ce qui est bien sûr inutile puisqu'à ce stade, le téléchargement est terminé et le fichier est sauvegardé.
Quelqu'un a une solution à ce comportement?