// It could be part of the AIDL Interface but at the moment no Activity uses it directly public void addIncompleteDownloads() { Log.i(AnkiDroidApp.TAG, "DownloadManagerService - Adding incomplete downloads:"); File dir = new File(mDestination + "/tmp/"); File[] fileList = dir.listFiles(new IncompleteDownloadsFilter()); if (fileList != null) { for (File file : fileList) { String filename = file.getName(); Log.i(AnkiDroidApp.TAG, "Filename = " + filename); // Personal decks if (filename.endsWith(".anki.tmp")) { Download download = new Download(filename.substring(0, filename.length() - ".anki.tmp".length())); download.setDownloaded(file.length()); mPersonalDeckDownloads.add(download); } // Shared decks else if (filename.endsWith(".shared.zip.tmp")) { filename = filename.substring(0, filename.length() - ".shared.zip.tmp".length()); int lastDotPosition = filename.lastIndexOf("."); String identifier = filename.substring(lastDotPosition + 1, filename.length()); String title = filename.substring(0, lastDotPosition); SharedDeckDownload download = new SharedDeckDownload(Integer.parseInt(identifier), title); download.setDownloaded(file.length()); mSharedDeckDownloads.add(download); } // Shared but not totally updated decks else if (filename.endsWith(".anki.updating")) { String title = filename.substring(0, filename.length() - ".anki.updating".length()); SharedDeckDownload download = new SharedDeckDownload(title); SharedPreferences pref = PrefSettings.getSharedPrefs(getBaseContext()); String pausedPref = "paused:" + mDestination + "/tmp/" + download.getTitle() + ".anki.updating"; if (pref.getBoolean(pausedPref, false)) { download.setStatus(SharedDeckDownload.STATUS_PAUSED); } else { download.setStatus(SharedDeckDownload.STATUS_UPDATING); } mSharedDeckDownloads.add(download); } } notifyObservers(); } // If no decks were added, stop the service stopIfFinished(); }
@Override protected void onPostExecute(Download download) { Log.i(AnkiDroidApp.TAG, "on post execute"); if (download.getStatus() == Download.STATUS_COMPLETE) { showNotification(download.getTitle()); } else if (download.getStatus() == Download.STATUS_ERROR) { // Error - Clean up Log.i(AnkiDroidApp.TAG, "deleting file"); new File(mDestination + "/tmp/" + download.getTitle() + ".anki.tmp").delete(); Log.e(AnkiDroidApp.TAG, "Error while downloading personal deck."); } mPersonalDeckDownloads.remove(download); notifyPersonalDeckObservers(); stopIfFinished(); }
@Override protected Download doInBackground(Download... downloads) { Download download = downloads[0]; URL url; RandomAccessFile file = null; InflaterInputStream iis = null; try { url = new URL(AnkiDroidProxy.SYNC_URL + "fulldown"); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoInput(true); connection.setDoOutput(true); connection.setUseCaches(false); connection.setRequestMethod("POST"); // FIXME: The connection always returns all bytes, regardless of what is indicated in range // property, so // resuming downloads of personal decks is not possible at the moment // Fix this when the connection is fixed on AnkiOnline // Log.i(AnkiDroidApp.TAG, "Range = " + download.getDownloaded()); // connection.setRequestProperty("Range","bytes=" + download.getDownloaded() + "-"); connection.setRequestProperty("Content-type", "application/x-www-form-urlencoded"); connection.connect(); long startTime = System.currentTimeMillis(); DataOutputStream ds = new DataOutputStream(connection.getOutputStream()); String data = "p=" + URLEncoder.encode(mPassword, "UTF-8") + "&u=" + URLEncoder.encode(mUsername, "UTF-8") + "&d=" + URLEncoder.encode(download.getTitle(), "UTF-8"); ds.writeBytes(data); Log.i(AnkiDroidApp.TAG, "Closing streams..."); ds.flush(); ds.close(); // Make sure response code is in the 200 range. if (connection.getResponseCode() / 100 != 2) { download.setStatus(Download.STATUS_ERROR); publishProgress(); } else { download.setStatus(Download.STATUS_DOWNLOADING); publishProgress(); } Log.i(AnkiDroidApp.TAG, "Response code = " + connection.getResponseCode()); // Check for valid content length. Log.i(AnkiDroidApp.TAG, "Connection length = " + connection.getContentLength()); int contentLength = connection.getContentLength(); if (contentLength < 1) { Log.i(AnkiDroidApp.TAG, "Content Length = -1"); // download.setStatus(Download.ERROR); } // Set the size for this download if it hasn't been already set if (download.getSize() == -1 && contentLength != -1) { download.setSize(contentLength); Log.i(AnkiDroidApp.TAG, "File size = " + contentLength); } // Open file file = new RandomAccessFile(mDestination + "/tmp/" + download.getTitle() + ".anki.tmp", "rw"); // FIXME: Uncomment next line when the connection is fixed on AnkiOnline (= when the // connection only // returns the bytes specified on the range property) // file.seek(download.getDownloaded()); iis = new InflaterInputStream(connection.getInputStream()); while (download.getStatus() == Download.STATUS_DOWNLOADING) { // Size buffer according to how much of the file is left to download Log.v(AnkiDroidApp.TAG, "Downloading... " + download.getDownloaded()); byte[] buffer; // if (size - downloaded > MAX_BUFFER_SIZE) { buffer = new byte[MAX_BUFFER_SIZE]; // } else { // buffer = new byte[size - downloaded]; // } // Read from server into buffer. int read = iis.read(buffer); if (read == -1) { break; } // Write buffer to file. file.write(buffer, 0, read); download.setDownloaded(download.getDownloaded() + read); publishProgress(); } if (download.getStatus() == Download.STATUS_DOWNLOADING) { // Change status to complete if this point was reached because downloading has finished download.setStatus(Download.STATUS_COMPLETE); new File(mDestination + "/tmp/" + download.getTitle() + ".anki.tmp") .renameTo(new File(mDestination + "/" + download.getTitle() + ".anki")); long finishTime = System.currentTimeMillis(); Log.i(AnkiDroidApp.TAG, "Finished in " + ((finishTime - startTime) / 1000) + " seconds!"); Log.i(AnkiDroidApp.TAG, "Downloaded = " + download.getDownloaded()); } else if (download.getStatus() == Download.STATUS_CANCELLED) { // Cancelled download, clean up new File(mDestination + "/tmp/" + download.getTitle() + ".anki.tmp").delete(); Log.i(AnkiDroidApp.TAG, "Download cancelled."); } publishProgress(); connection.disconnect(); } catch (Exception e) { e.printStackTrace(); Log.i(AnkiDroidApp.TAG, "Exception Error = " + e.getMessage()); download.setStatus(Download.STATUS_ERROR); publishProgress(); } finally { Log.i(AnkiDroidApp.TAG, "finally"); // Close file if (file != null) { try { Log.i(AnkiDroidApp.TAG, "closing file"); file.close(); } catch (Exception e) { Log.i(AnkiDroidApp.TAG, "exception closing file"); } } // Close connection to server if (iis != null) { try { Log.i(AnkiDroidApp.TAG, "closing iis"); iis.close(); Log.i(AnkiDroidApp.TAG, "closed iis"); } catch (Exception e) { Log.i(AnkiDroidApp.TAG, "exception closing iis: " + e.getMessage()); } } } return download; }