Added expandable notifications to download service

This commit is contained in:
daniel oeh 2013-02-10 17:20:03 +01:00
parent d85b90f56e
commit cfb7c15646
1 changed files with 140 additions and 25 deletions

View File

@ -14,7 +14,12 @@ import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.RejectedExecutionHandler;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadFactory;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import javax.xml.parsers.ParserConfigurationException;
@ -25,6 +30,7 @@ import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.app.Notification.Builder;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
@ -99,7 +105,8 @@ public class DownloadService extends Service {
private DownloadRequester requester;
private FeedManager manager;
private NotificationCompat.Builder notificationBuilder;
private NotificationCompat.Builder notificationCompatBuilder;
private Notification.BigTextStyle notificationBuilder;
private int NOTIFICATION_ID = 2;
private int REPORT_ID = 3;
@ -114,6 +121,11 @@ public class DownloadService extends Service {
private Handler handler;
private NotificationUpdater notificationUpdater;
private ScheduledFuture notificationUpdaterFuture;
private static final int SCHED_EX_POOL_SIZE = 1;
private ScheduledThreadPoolExecutor schedExecutor;
private final IBinder mBinder = new LocalBinder();
public class LocalBinder extends Binder {
@ -176,6 +188,24 @@ public class DownloadService extends Service {
return t;
}
});
schedExecutor = new ScheduledThreadPoolExecutor(SCHED_EX_POOL_SIZE,
new ThreadFactory() {
@Override
public Thread newThread(Runnable r) {
Thread t = new Thread(r);
t.setPriority(Thread.MIN_PRIORITY);
return t;
}
}, new RejectedExecutionHandler() {
@Override
public void rejectedExecution(Runnable r,
ThreadPoolExecutor executor) {
Log.w(TAG, "SchedEx rejected submission of new task");
}
});
setupNotificationBuilders();
manager = FeedManager.getInstance();
requester = DownloadRequester.getInstance();
}
@ -194,27 +224,81 @@ public class DownloadService extends Service {
unregisterReceiver(downloadQueued);
}
private void setupNotification() {
@SuppressLint("NewApi")
private void setupNotificationBuilders() {
PendingIntent pIntent = PendingIntent.getActivity(this, 0, new Intent(
this, DownloadActivity.class),
PendingIntent.FLAG_UPDATE_CURRENT);
Bitmap icon = BitmapFactory.decodeResource(getResources(),
R.drawable.stat_notify_sync);
notificationBuilder = new NotificationCompat.Builder(this)
.setContentTitle(
getString(R.string.download_notification_title))
.setContentText(
requester.getNumberOfDownloads()
+ getString(R.string.downloads_left))
.setOngoing(true).setContentIntent(pIntent).setLargeIcon(icon)
.setSmallIcon(R.drawable.stat_notify_sync);
startForeground(NOTIFICATION_ID, notificationBuilder.getNotification());
if (android.os.Build.VERSION.SDK_INT >= 16) {
notificationBuilder = new Notification.BigTextStyle(
new Notification.Builder(this).setOngoing(true)
.setContentIntent(pIntent).setLargeIcon(icon)
.setSmallIcon(R.drawable.stat_notify_sync));
} else {
notificationCompatBuilder = new NotificationCompat.Builder(this)
.setOngoing(true).setContentIntent(pIntent)
.setLargeIcon(icon)
.setSmallIcon(R.drawable.stat_notify_sync);
}
if (AppConfig.DEBUG)
Log.d(TAG, "Notification set up");
}
/**
* Updates the contents of the service's notifications. Should be called
* before setupNotificationBuilders.
*/
@SuppressLint("NewApi")
private Notification updateNotifications() {
String contentTitle = getString(R.string.download_notification_title);
String downloadsLeft = requester.getNumberOfDownloads()
+ getString(R.string.downloads_left);
if (android.os.Build.VERSION.SDK_INT >= 16) {
if (notificationBuilder != null) {
StringBuilder bigText = null;
for (Downloader downloader : downloads) {
if (bigText == null) {
bigText = new StringBuilder();
} else {
bigText.append("\n");
}
if (downloader.getStatus() != null) {
FeedFile f = downloader.getStatus().getFeedFile();
if (f.getClass() == Feed.class) {
bigText.append("\u2022 " + ((Feed) f).getTitle());
} else if (f.getClass() == FeedMedia.class) {
FeedMedia media = (FeedMedia) f;
bigText.append("\u2022 "
+ media.getItem().getTitle()
+ " ("
+ downloader.getStatus()
.getProgressPercent() + "%)");
}
}
}
notificationBuilder.setSummaryText(downloadsLeft);
notificationBuilder.setBigContentTitle(contentTitle);
if (bigText != null) {
notificationBuilder.bigText(bigText.toString());
}
return notificationBuilder.build();
}
} else {
if (notificationCompatBuilder != null) {
notificationCompatBuilder.setContentTitle(contentTitle);
notificationCompatBuilder.setContentText(downloadsLeft);
return notificationCompatBuilder.getNotification();
}
}
return null;
}
private Downloader getDownloader(String downloadUrl) {
for (Downloader downloader : downloads) {
if (downloader.getStatus().getFeedFile().getDownload_url()
@ -275,7 +359,6 @@ public class DownloadService extends Service {
if (AppConfig.DEBUG)
Log.d(TAG, "Cancelling shutdown; new download was queued");
shutdownInitiated = false;
setupNotification();
}
DownloadRequester requester = DownloadRequester.getInstance();
@ -340,7 +423,7 @@ public class DownloadService extends Service {
queryDownloads();
}
}
@Override
protected void onPreExecute() {
super.onPreExecute();
@ -392,9 +475,12 @@ public class DownloadService extends Service {
* DownloadService list.
*/
private void removeDownload(final Downloader d) {
if (AppConfig.DEBUG) Log.d(TAG, "Removing downloader: " + d.getStatus().getFeedFile().getDownload_url());
if (AppConfig.DEBUG)
Log.d(TAG, "Removing downloader: "
+ d.getStatus().getFeedFile().getDownload_url());
boolean rc = downloads.remove(d);
if (AppConfig.DEBUG) Log.d(TAG, "Result of downloads.remove: " + rc);
if (AppConfig.DEBUG)
Log.d(TAG, "Result of downloads.remove: " + rc);
DownloadRequester.getInstance().removeDownload(
d.getStatus().getFeedFile());
sendBroadcast(new Intent(ACTION_DOWNLOADS_CONTENT_CHANGED));
@ -502,18 +588,11 @@ public class DownloadService extends Service {
Log.d(TAG, "Starting shutdown");
shutdownInitiated = true;
updateReport();
cancelNotificationUpdater();
stopForeground(true);
} else {
if (notificationBuilder != null) {
// update notification
notificationBuilder.setContentText(numOfDownloads
+ " Downloads left");
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(NOTIFICATION_ID,
notificationBuilder.getNotification());
} else {
setupNotification();
}
setupNotificationUpdater();
startForeground(NOTIFICATION_ID, updateNotifications());
}
}
@ -848,6 +927,42 @@ public class DownloadService extends Service {
}
/** Schedules the notification updater task if it hasn't been scheduled yet. */
private void setupNotificationUpdater() {
if (AppConfig.DEBUG)
Log.d(TAG, "Setting up notification updater");
if (notificationUpdater == null) {
notificationUpdater = new NotificationUpdater();
notificationUpdaterFuture = schedExecutor.scheduleAtFixedRate(
notificationUpdater, 5L, 5L, TimeUnit.SECONDS);
}
}
private void cancelNotificationUpdater() {
boolean result = false;
if (notificationUpdaterFuture != null) {
result = notificationUpdaterFuture.cancel(true);
}
notificationUpdater = null;
notificationUpdaterFuture = null;
Log.d(TAG, "NotificationUpdater cancelled. Result: " + result);
}
private class NotificationUpdater implements Runnable {
public void run() {
handler.post(new Runnable() {
@Override
public void run() {
Notification n = updateNotifications();
if (n != null) {
NotificationManager nm = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
nm.notify(NOTIFICATION_ID, n);
}
}
});
}
}
public List<Downloader> getDownloads() {
return downloads;
}