I've created a custom class to Download a single Audio File from our Server. The single Download is working without any Problems but now I need to include the functionality to Download multiple Audio files either at one time or in a row..
The problem is that the App crashes with my implementation of downloading: "App isn't responding. Do you want to close it? [wait] [quit]"
I'm not to sure what is causing the Problem but I've already read that the NotificationManager could be the problem so I've implemented it up on a tutorial which said it would fix it but it didn't. So i believe it has to be a problem with the Threading..
AudioDownload class:
public class AudioDownload implements Runnable {
private static Boolean bIAmBusy = false;
private Activity activity;
OnAudioDownloadFinishedListener mycallback;
private String Folder;
private String FileName;
private String FileUrl;
public AudioDownload(String COURSE_FLAG, String AUDIO, String language, Activity a){
Folder = COURSE_FLAG;
FileName = AUDIO;
FileUrl = "http://SOMEURL/"+ language + "/" + COURSE_FLAG + "/" + FileName;
activity = a;
}
@Override
public void run() {
bIAmBusy = true;
File localFile = new File(activity.getFilesDir() + "/" + Folder + "/" + FileName);
if(localFile.exists()){
//don't download
}
else{
/*
In older android versions, your Notification has to have a content Intent,
so that when the user clicks your Notification, something happens. This means you must:
Make an Intent object, pointing somewhere, such as your MainActivity.
Make sure to add the Intent.FLAG_ACTIVITY_NEW_TASK flag.
*/
Intent intent = new Intent(activity, CoursesActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(activity,0,intent,PendingIntent.FLAG_UPDATE_CURRENT);
NotificationManager notificationManager = (NotificationManager) activity.getSystemService(activity.getApplicationContext().NOTIFICATION_SERVICE);
NotificationCompat.Builder builder = new NotificationCompat.Builder(activity);
builder.setContentTitle("Audio Download");
builder.setContentText("Download in Progress");
builder.setSmallIcon(R.drawable.btn_download);
builder.setTicker("Audio Download");
builder.setContentIntent(pendingIntent);
int id = 1;
BufferedInputStream in = null;
FileOutputStream out = null;
boolean saved = false;
try {
URL url = new URL(FileUrl);
URLConnection conn = url.openConnection();
int size = conn.getContentLength();
in = new BufferedInputStream(new URL(FileUrl).openStream());
final File dir = new File(activity.getFilesDir() + "/" + Folder);
dir.mkdirs();
final File file = new File(dir,FileName);
out = new FileOutputStream(file);
final byte data[] = new byte[1024];
int count;
int sumCount = 0;
while ((count = in.read(data, 0, 1024)) != -1) {
sumCount += count;
builder.setProgress(size,sumCount,false);
notificationManager.notify(id, builder.build());
out.write(data, 0, count);
}
saved = true;
builder.setContentText("Download Complete");
builder.setProgress(0,0,false);
notificationManager.notify(id, builder.build());
}catch (IOException e){
}
finally {
if(in != null){
try {
in.close();
} catch (IOException e) {
e.printStackTrace();
}
}
if (out != null){
try {
out.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
final boolean finalSaved = saved;
activity.runOnUiThread(new Runnable() {
@Override
public void run() {
mycallback.OnAudioDownloadThreadFinished(finalSaved);
}
});
}
bIAmBusy = false;
}
And in my Activity up on Button Click I'm trying queue the Threads.
public void onClick(View view) {
Thread t = new Thread(){
@Override
public void run() {
Log.d("Audio", "Downloading all the audio for the chapter");
Toast.makeText(context, "Downloading all the audio for the chapter", Toast.LENGTH_SHORT).show();
List<AudioDownload> downloadList = new ArrayList<AudioDownload>();
for (int child = 0; child < chapters.get(groupPosition).getSubChapters().size(); child++) {
String Language = "en";
String FileName = subChapters.get(chapters.get(group)).get(child).getAudio();
audioDownload = new AudioDownload(Course, FileName, Language, activity);
audioDownload.setOnAudioDownloadFinishedListener(new AudioDownload.OnAudioDownloadFinishedListener() {
@Override
public void OnAudioDownloadThreadFinished(Boolean success) {
if (success) {
Toast.makeText(context, "Download was successful", Toast.LENGTH_SHORT).show();
}
}
});
downloadList.add(audioDownload);
}
for (int i = 0; i < downloadList.size(); i++) {
while (downloadList.get(i).isBusy()) {
//wait
}
if (downloadList.get(i).isBusy() == false) {
new Thread(downloadList.get(i), "AudioDownload_" + i).start();
}
}
}
};
t.start();
The while loop for waiting for the Thread to finish should work since bIamBusy is declared static -> expected behaviour from my point of view is that every AudioDownload gets initiated/started after the other one is completed.
Unfortunately the App crashes up on the multi Download. As stated if I use this class for a single Audio Download the App/UIThread doesn't crash. Has someone any idea why this is happening?
UPDATE App Crashes only when I pull down the NotificationManager.
ThreadLog... -> seems like it doesn't wait with starting them
17 30669 Native 21 6 AudioDownload_6
18 30666 Native 19 7 AudioDownload_4
19 30657 Native 20 7 AudioDownload_3
20 30673 Native 18 6 AudioDownload_10
21 30677 Native 20 8 AudioDownload_12
Stacktrace:
09-16 01:43:57.235 405-440/? E/ActivityManager﹕ ANR in smapp.com.smapp (smapp.com.smapp/.Controller.Screen_4.ChapterOverviewActivity)
Reason: keyDispatchingTimedOut
Load: 1.12 / 0.76 / 0.51
CPU usage from 10166ms to 4102ms ago:
36% 30551/smapp.com.smapp: 35% user + 1.3% kernel / faults: 2463 minor
17% 481/com.android.systemui: 16% user + 0.8% kernel / faults: 5726 minor
9.5% 405/system_server: 8.2% user + 1.3% kernel / faults: 483 minor
1.8% 121/surfaceflinger: 0.6% user + 1.1% kernel
0.2% 124/mediaserver: 0% user + 0.2% kernel / faults: 3 minor
0.9% 114/local_opengl: 0% user + 0.9% kernel
0.3% 60/adbd: 0% user + 0.3% kernel / faults: 34 minor
0.3% 112/vinput: 0% user + 0.3% kernel
0% 28602/flush-8:16: 0% user + 0% kernel
0% 29589/logcat: 0% user + 0% kernel
70% TOTAL: 60% user + 8.8% kernel + 1.1% softirq
CPU usage from 257ms to 760ms later:
59% 30551/smapp.com.smapp: 59% user + 0% kernel
55% 30551/smapp.com.smapp: 55% user + 0% kernel
3.8% 31130/AudioDownload_5: 1.9% user + 1.9% kernel
1.9% 31121/AudioDownload_2: 1.9% user + 0% kernel
1.9% 31122/AudioDownload_3: 1.9% user + 0% kernel
24% 481/com.android.systemui: 20% user + 4% kernel / faults: 657 minor
16% 481/ndroid.systemui: 16% user + 0% kernel
4% 575/Binder_3: 2% user + 2% kernel
2% 519/GC: 2% user + 0% kernel
2% 526/Binder_2: 2% user + 0% kernel
10% 405/system_server: 8% user + 2% kernel
2% 405/system_server: 2% user + 0% kernel
2% 415/Binder_1: 0% user + 2% kernel
2% 416/Binder_2: 0% user + 2% kernel
2% 440/InputDispatcher: 0% user + 2% kernel
2% 662/Binder_5: 2% user + 0% kernel
1.7% 60/adbd: 0% user + 1.7% kernel
1.7% 121/surfaceflinger: 0% user + 1.7% kernel
1.7% 303/VSyncThread: 0% user + 1.7% kernel
100% TOTAL: 90% user + 10% kernel