rewrote Downloading process

This commit is contained in:
Daniel Oeh 2011-12-29 21:05:22 +01:00
parent d1db888141
commit 491f2a2f58
5 changed files with 139 additions and 101 deletions

View File

@ -27,10 +27,5 @@
<activity android:name="de.podfetcher.activity.AddFeedActivity"/>
<service android:enabled="true" android:name="de.podfetcher.service.DownloadService" />
<service android:enabled="true" android:name="de.podfetcher.service.FeedSyncService" >
<intent-filter>
<action android:name="action.de.podfetcher.storage.feed_download_completed"></action>
</intent-filter>
</service>
</application>
</manifest>

View File

@ -1,8 +1,10 @@
package de.podfetcher.feed;
/** Represents a component of a Feed that has to be downloaded*/
public abstract class FeedFile extends FeedComponent {
protected String file_url;
protected String download_url;
protected long downloadId; // temporary id given by the Android DownloadManager
public String getFile_url() {
return file_url;
@ -16,7 +18,12 @@ public abstract class FeedFile extends FeedComponent {
public void setDownload_url(String download_url) {
this.download_url = download_url;
}
public long getDownloadId() {
return downloadId;
}
public void setDownloadId(long downloadId) {
this.downloadId = downloadId;
}
}

View File

@ -7,6 +7,8 @@
package de.podfetcher.service;
import java.io.File;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import de.podfetcher.feed.*;
import de.podfetcher.storage.DownloadRequester;
import android.app.Service;
@ -21,14 +23,19 @@ import android.util.Log;
public class DownloadService extends Service {
public static String ACTION_ALL_FEED_DOWNLOADS_COMPLETED = "action.de.podfetcher.storage.all_feed_downloads_completed";
public static final String ACTION_FEED_SYNC_COMPLETED = "action.de.podfetcher.service.feed_sync_completed";
private volatile ScheduledThreadPoolExecutor syncExecutor;
private DownloadRequester requester;
private FeedManager manager;
@Override
public void onCreate() {
Log.d(this.toString(), "Service started");
registerReceiver(receiver, createIntentFilter());
registerReceiver(downloadReceiver, createIntentFilter());
syncExecutor = new ScheduledThreadPoolExecutor(Runtime.getRuntime().availableProcessors() + 2);
manager = FeedManager.getInstance();
requester = DownloadRequester.getInstance();
}
@Override
@ -38,49 +45,62 @@ public class DownloadService extends Service {
@Override
public void onDestroy() {
unregisterReceiver(receiver);
Log.d(this.toString(), "Service shutting down");
sendBroadcast(new Intent(ACTION_FEED_SYNC_COMPLETED));
}
private IntentFilter createIntentFilter() {
IntentFilter filter = new IntentFilter();
filter.addAction(DownloadManager.ACTION_DOWNLOAD_COMPLETE);
return filter;
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
/** Shuts down Executor service and prepares for shutdown */
private void initiateShutdown() {
Log.d(this.toString(), "Initiating shutdown");
// Wait until PoolExecutor is done
Thread waiter = new Thread() {
@Override
public void run() {
syncExecutor.shutdown();
try {
syncExecutor.awaitTermination(20, TimeUnit.SECONDS);
stopSelf();
}catch(InterruptedException e) {
e.printStackTrace();
}
}
};
waiter.start();
}
private BroadcastReceiver downloadReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
long id = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
requester = DownloadRequester.getInstance();
manager = FeedManager.getInstance();
Intent item_intent = requester.getItemIntent(id);
String action = item_intent.getAction();
if(action.equals(DownloadRequester.ACTION_FEED_DOWNLOAD_COMPLETED)) {
handleCompletedFeedDownload(context, item_intent);
if(requester.getNumberOfFeedDownloads() == 0) {
sendBroadcast(new Intent(ACTION_ALL_FEED_DOWNLOADS_COMPLETED));
long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, 0);
Feed feed = requester.getFeed(downloadId);
if(feed != null) {
handleCompletedFeedDownload(context, feed);
}else {
FeedImage image = requester.getFeedImage(downloadId);
if(image != null) {
handleCompletedImageDownload(context, image);
}
} else if(action.equals(DownloadRequester.ACTION_MEDIA_DOWNLOAD_COMPLETED)) {
requester.removeMediaByID(item_intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
} else if(action.equals(DownloadRequester.ACTION_IMAGE_DOWNLOAD_COMPLETED)) {
handleCompletedImageDownload(context, item_intent);
}
// Check if there's something else to download, otherwise stop
if(requester.getNumberOfDownloads() == 0) {
stopSelf();
unregisterReceiver(downloadReceiver);
initiateShutdown();
}
}
};
/** Is called whenever a Feed is downloaded */
private void handleCompletedFeedDownload(Context context, Intent intent) {
requester.removeFeedByID(intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
private void handleCompletedFeedDownload(Context context, Feed feed) {
requester.removeFeed(feed);
// Get Feed Information
Feed feed = manager.getFeed(intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
feed.setFile_url((new File(requester.getFeedfilePath(context), requester.getFeedfileName(feed.getId()))).toString());
// Update Information in Database
manager.setFeed(context, feed);
@ -88,15 +108,39 @@ public class DownloadService extends Service {
if(feed.getImage() != null) {
requester.downloadImage(context, feed.getImage());
}
context.startService(intent);
syncExecutor.submit(new FeedSyncThread(feed, this));
}
/** Is called whenever a Feed-Image is downloaded */
private void handleCompletedImageDownload(Context context, Intent intent) {
requester.removeImageByID(intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
FeedImage image = manager.getFeedImage(intent.getLongExtra(DownloadRequester.EXTRA_ITEM_ID, -1));
private void handleCompletedImageDownload(Context context, FeedImage image) {
requester.removeFeedImage(image);
image.setFile_url(requester.getImagefilePath(context) + requester.getImagefileName(image.getId()));
}
/** Takes a single Feed, parses the corresponding file and refreshes information in the manager */
class FeedSyncThread implements Runnable {
private Feed feed;
private DownloadService service;
public FeedSyncThread(Feed feed, DownloadService service) {
this.feed = feed;
this.service = service;
}
public void run() {
FeedManager manager = FeedManager.getInstance();
FeedHandler handler = new FeedHandler();
feed = handler.parseFeed(feed);
Log.d(this.toString(), feed.getTitle() + " parsed");
// Add Feeditems to the database
for(FeedItem item : feed.getItems()) {
manager.addFeedItem(service, item);
}
}
}
}

View File

@ -65,6 +65,7 @@ public class FeedSyncService extends Service {
/** Prepares itself for stopping */
private void initiateShutdown() {
Log.d(this.toString(), "Initiating shutdown");
// Wait until PoolExecutor is done
Thread waiter = new Thread() {
@Override

View File

@ -3,11 +3,10 @@ package de.podfetcher.storage;
import java.util.ArrayList;
import java.io.File;
import de.podfetcher.feed.Feed;
import de.podfetcher.feed.FeedImage;
import de.podfetcher.feed.FeedMedia;
import de.podfetcher.feed.*;
import de.podfetcher.service.DownloadService;
import android.util.Log;
import android.app.DownloadManager;
import android.content.Context;
import android.content.Intent;
@ -30,14 +29,14 @@ public class DownloadRequester {
private static DownloadRequester downloader;
public ArrayList<Intent> feeds;
public ArrayList<Intent> images;
public ArrayList<Intent> media;
public ArrayList<FeedFile> feeds;
public ArrayList<FeedFile> images;
public ArrayList<FeedFile> media;
private DownloadRequester(){
feeds = new ArrayList<Intent>();
images = new ArrayList<Intent>();
media = new ArrayList<Intent>();
feeds = new ArrayList<FeedFile>();
images = new ArrayList<FeedFile>();
media = new ArrayList<FeedFile>();
}
@ -48,89 +47,81 @@ public class DownloadRequester {
return downloader;
}
private void download(Context context, ArrayList<Intent> type, String str_uri, File dest, boolean visibleInUI, String action, long id) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(str_uri));
private void download(Context context, ArrayList<FeedFile> type, FeedFile item, File dest, boolean visibleInUI) {
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(item.getDownload_url()));
//request.allowScanningByMediaScanner();
request.setDestinationUri(Uri.fromFile(dest));
request.setVisibleInDownloadsUi(visibleInUI);
// TODO Set Allowed Network Types
DownloadManager manager = (DownloadManager) context.getSystemService(Context.DOWNLOAD_SERVICE);
Intent i = new Intent(action);
context.startService(new Intent(context, DownloadService.class));
i.putExtra(EXTRA_DOWNLOAD_ID, manager.enqueue(request));
i.putExtra(EXTRA_ITEM_ID, id);
type.add(i);
item.setDownloadId(manager.enqueue(request));
type.add(item);
}
public void downloadFeed(Context context, Feed feed) {
download(context, feeds, feed.getDownload_url(),
download(context, feeds, feed,
new File(getFeedfilePath(context), getFeedfileName(feed.getId())),
true, ACTION_FEED_DOWNLOAD_COMPLETED, feed.getId());
true);
}
public void downloadImage(Context context, FeedImage image) {
download(context, images, image.getDownload_url(),
download(context, images, image,
new File(getImagefilePath(context), getImagefileName(image.getId())),
true, ACTION_IMAGE_DOWNLOAD_COMPLETED, image.getId());
true);
}
public void downloadMedia(Context context, FeedMedia feedmedia) {
download(context, media, feedmedia.getDownload_url(),
download(context, media, feedmedia,
new File(context.getExternalFilesDir(MEDIA_DOWNLOADPATH), "media-" + feedmedia.getId()),
true, ACTION_MEDIA_DOWNLOAD_COMPLETED, feedmedia.getId());
true);
}
public void removeFeedByID(long id) {
int len = feeds.size();
for(int x = 0; x < len; x++) {
if(feeds.get(x).getLongExtra(EXTRA_ITEM_ID, -1) == id) {
feeds.remove(x);
break;
}
}
}
public void removeMediaByID(long id) {
int len = media.size();
for(int x = 0; x < len; x++) {
if(media.get(x).getLongExtra(EXTRA_ITEM_ID, -1) == id) {
media.remove(x);
break;
}
}
}
public void removeImageByID(long id) {
int len = images.size();
for(int x = 0; x < len; x++) {
if(images.get(x).getLongExtra(EXTRA_ITEM_ID, -1) == id) {
images.remove(x);
break;
}
}
}
/* Returns the stored intent by looking for the right download id */
public Intent getItemIntent(long id) {
for(Intent i : feeds) {
if(i.getLongExtra(EXTRA_DOWNLOAD_ID, -1) == id) {
return i;
}
}
for(Intent i : media) {
if(i.getLongExtra(EXTRA_DOWNLOAD_ID, -1) == id) {
return i;
}
}
for(Intent i : images) {
if(i.getLongExtra(EXTRA_DOWNLOAD_ID, -1) == id) {
return i;
/** Get a Feed by its download id */
public Feed getFeed(long id) {
for(FeedFile f: feeds) {
if(f.getDownloadId() == id) {
return (Feed) f;
}
}
return null;
}
/** Get a FeedImage by its download id */
public FeedImage getFeedImage(long id) {
for(FeedFile f: images) {
if(f.getDownloadId() == id) {
return (FeedImage) f;
}
}
return null;
}
/** Get media by its download id */
public FeedMedia getFeedMedia(long id) {
for(FeedFile f: media) {
if(f.getDownloadId() == id) {
return (FeedMedia) f;
}
}
return null;
}
public void removeFeed(Feed f) {
feeds.remove(f);
}
public void removeFeedMedia(FeedMedia m) {
media.remove(m);
}
public void removeFeedImage(FeedImage fi) {
images.remove(fi);
}
/** Get the number of uncompleted Downloads */
public int getNumberOfDownloads() {
return feeds.size() + images.size() + media.size();