I'm having a little problem, which I guess is easy to solve. But I'm really not getting the solution at the moment.
I have an IntentService, which shows the state of an actual downloaded file, and gets filled in an ListView child. Everything is working fine there.
Adapted from here: Download multiple files with a progress bar in ListView Android
But as soon as I want to delete a started download, because it was getting unnecessary. My problem occures. I'm not able to stop the IntenService.
I have tried different approaches.
How to force an IntentService to stop immediately with a cancel button from an Activity?
How to stop intentservice in android?
At the moment I'm sending a fake signal to the DownloadTask, which implies that the download was successfull.
public static void removeItems(){
startup--;
Log.e("Button", "clicked" + "position " + global_position);
//tasks contains all DownloadTasks
//**sending fake signal here**
DownloadingService.DownloadTask t = tasks.get(global_position);
t.mProgress = 101;
a.remove(global_position); //remove Progress Array_List
tasks.remove(global_position); //remove DownloadTask
//update the UI
listView.setAdapter(mAdapter = new ArrayAdapter<Progress>(act, R.layout.progressbar_list, R.id.textView, a){
});
//trying to stop the IntentService, but goes to the wrong Thread
act.stopService(intent);
intent = new Intent(act, DownloadingService.class);
intent.putExtra("files", mAdapter.getCount());
if(tasks.size() > 0) {
//startService causes crash
//act.startService(intent);
}
}
This works fine, but only if there is one child in the ListView. The DownloadTask finishes and the IntentService stops. But as soon as there are more childs in the ListView, the call does not finish the download and the IntentService keeps on rolling. Which leads to an NullPointer because it wants to fill a ListView child, which I already deleted.
My DownloadService:
public static class DownloadingService extends IntentService {
public static String PROGRESS_UPDATE_ACTION = DownloadingService.class
.getName() + ".progress_update";
private ExecutorService mExec;
private CompletionService<NoResultType> mEcs;
private LocalBroadcastManager mBroadcastManager;
private ArrayList<DownloadTask> mTasks;
public static volatile boolean shouldContinue = true;
private static final long INTERVAL_BROADCAST = 800;
private long mLastUpdate = 0;
public DownloadingService() {
super("DownloadingService");
Log.e("DOWNLOADING", "SERVICE");
mExec = Executors.newFixedThreadPool(20);
mEcs = new ExecutorCompletionService<NoResultType>(mExec);
mBroadcastManager = LocalBroadcastManager.getInstance(this);
mTasks = new ArrayList<Uebersicht.DownloadingService.DownloadTask>();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
return super.onStartCommand(intent, flags, startId);
}
@Override
protected void onHandleIntent(Intent intent) {
doStuff();
if(startup <= 1) {
Log.e("startup", "<1" + startup);
tasks = mTasks;
noOfFilesToDownalod = 0;
Log.e("filestodownload", " " + noOfFilesToDownalod);
DownloadTask yt1 = new DownloadTask(noOfFilesToDownalod);
tasks.add(yt1);
Log.e("TASKS", " " + tasks.size());
for (DownloadTask t : tasks) {
mEcs.submit(t);
}
// wait for finish
int n = tasks.size();
for (int i = 0; i < n; ++i) {
NoResultType r;
try {
r = mEcs.take().get();
if (r != null) {
// use you result here
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
// send a last broadcast
publishCurrentProgressOneShot(true);
mExec.shutdown();
}else {
Log.e("startup", "elsee" + startup);
noOfFilesToDownalod++;
Log.e("noOFiles", " " + noOfFilesToDownalod);
//noOfFilesToDownalod = intent.getIntExtra("files", 0);
tasks.add(new DownloadTask(noOfFilesToDownalod));
Log.e(" tasks", ""+ tasks.size());
DownloadTask t = new DownloadTask(noOfFilesToDownalod);
mEcs.submit(t);
int n = tasks.size();
for (int i = 0; i < n; ++i) {
NoResultType r;
try {
r = mEcs.take().get();
if (r != null) {
// use you result here
}
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
}
// send a last broadcast
publishCurrentProgressOneShot(true);
mExec.shutdown();
}
}
private void doStuff(){
if (!shouldContinue) {
stopSelf();
Log.e("stopped?", "yeah");
return;
}
}
private void publishCurrentProgressOneShot(boolean forced) {
if (forced
|| System.currentTimeMillis() - mLastUpdate > INTERVAL_BROADCAST) {
mLastUpdate = System.currentTimeMillis();
final List<DownloadTask> taskspublish = mTasks;
int[] positions = new int[taskspublish.size()];
int[] progresses = new int[taskspublish.size()];
int[] times = new int[taskspublish.size()];
for (int i = 0; i < taskspublish.size(); i++) {
DownloadTask t = taskspublish.get(i);
positions[i] = t.mPosition;
progresses[i] = round(t.mProgress);
times[i] = t.minutesleft;
}
publishProgress(positions, progresses, times);
}
}
private int round(double d){
double dAbs = Math.abs(d);
int i = (int) dAbs;
double result = dAbs - (double) i;
if(result<0.5){
return d<0 ? -i : i;
}else{
return d<0 ? -(i+1) : i+1;
}
}
private void publishCurrentProgressOneShot() {
publishCurrentProgressOneShot(false);
}
private synchronized void publishProgress(int[] positions,
int[] progresses, int[] times) {
Intent i = new Intent();
i.setAction(PROGRESS_UPDATE_ACTION);
i.putExtra("position", positions);
i.putExtra("progress", progresses);
i.putExtra("time", times);
i.putExtra("oneshot", true);
mBroadcastManager.sendBroadcast(i);
}
class DownloadTask implements Callable<NoResultType> {
private int mPosition;
private double mProgress = (100 * Menge.getGroesse()) / 50;
private double rateinsek = Menge.getRate() / 60 / 60;
private double mlprosek = (rateinsek * Menge.getRate()) / Menge.getGroesse();
private int count = 0;
private double ratepromin = Menge.getRate() / 60;
private double left = Menge.getGroesse() / ratepromin;
private int minutesleft = (int) left;
public DownloadTask(int position) {
mPosition = position;
}
@Override
public NoResultType call() throws Exception {
while (mProgress > 0) {
mProgress -= mlprosek;
Log.e("MPROGRESS", " " + mProgress);
Thread.sleep(1000);
count++;
if(count == 60){
minutesleft = minutesleft-1;
Log.e("COUNT", "-1");
count = 0;
}
// publish progress
publishCurrentProgressOneShot();
// we can also call publishProgress(int position, int
// progress) instead, which will work fine but avoid broadcasts
// by aggregating them
//publishProgress(mPosition,mProgress);
}
return new NoResultType();
}
public double getProgress() {
return mProgress;
}
public int getPosition() {
return mPosition;
}
}
class NoResultType {
NoResultType(){
Log.e("READY", "100 %");
}
}
}