diff --git a/res/values/strings.xml b/res/values/strings.xml index 26f5c031f..3a064405c 100644 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -153,14 +153,15 @@ Recently Updated - Downloading %1$s / %2$s (%3$d%%) - Processing application %1$d of %2$d - Connecting to repository:\n%1$s - Checking apps compatibility with your device… + Downloading\n%2$s / %3$s (%4$d%%) from\n%1$s + Processing application\n%2$d of %3$d from\n%1$s + Connecting to\n%1$s + Checking all apps compatibility with your device… diff --git a/src/org/fdroid/fdroid/ProgressListener.java b/src/org/fdroid/fdroid/ProgressListener.java index 2ec97ed92..d38e342cd 100644 --- a/src/org/fdroid/fdroid/ProgressListener.java +++ b/src/org/fdroid/fdroid/ProgressListener.java @@ -1,7 +1,54 @@ package org.fdroid.fdroid; +import android.os.Bundle; + public interface ProgressListener { - public void onProgress(int type, int progress, int total); + public void onProgress(Event event); + + // I went a bit overboard with the overloaded constructors, but they all + // seemed potentially useful and unambiguous, so I just put them in there + // while I'm here. + public static class Event { + + public static final int NO_VALUE = Integer.MIN_VALUE; + + public final int type; + public final Bundle data; + + // These two are not final, so that you can create a template Event, + // pass it into a function which performs something over time, and + // that function can initialize "total" and progressively + // update "progress" + public int progress; + public int total; + + public Event(int type) { + this(type, NO_VALUE, NO_VALUE, null); + } + + public Event(int type, Bundle data) { + this(type, NO_VALUE, NO_VALUE, data); + } + + public Event(int type, int progress) { + this(type, progress, NO_VALUE, null); + } + + public Event(int type, int progress, Bundle data) { + this(type, NO_VALUE, NO_VALUE, data); + } + + public Event(int type, int progress, int total) { + this(type, progress, total, null); + } + + public Event(int type, int progress, int total, Bundle data) { + this.type = type; + this.progress = progress; + this.total = total; + this.data = data == null ? new Bundle() : data; + } + } } diff --git a/src/org/fdroid/fdroid/RepoXMLHandler.java b/src/org/fdroid/fdroid/RepoXMLHandler.java index f8844dc9b..2c9ce8917 100644 --- a/src/org/fdroid/fdroid/RepoXMLHandler.java +++ b/src/org/fdroid/fdroid/RepoXMLHandler.java @@ -42,6 +42,7 @@ import javax.net.ssl.SSLHandshakeException; import javax.xml.parsers.SAXParser; import javax.xml.parsers.SAXParserFactory; +import android.os.Bundle; import org.xml.sax.Attributes; import org.xml.sax.InputSource; import org.xml.sax.SAXException; @@ -55,8 +56,8 @@ import android.util.Log; public class RepoXMLHandler extends DefaultHandler { - // The ID of the repo we're processing. - private int repo; + // The repo we're processing. + private DB.Repo repo; private Vector apps; @@ -73,11 +74,13 @@ public class RepoXMLHandler extends DefaultHandler { public static final int PROGRESS_TYPE_DOWNLOAD = 1; public static final int PROGRESS_TYPE_PROCESS_XML = 2; + public static final String PROGRESS_DATA_REPO = "repo"; + // The date format used in the repo XML file. private SimpleDateFormat mXMLDateFormat = new SimpleDateFormat("yyyy-MM-dd"); private int totalAppCount; - public RepoXMLHandler(int repo, Vector apps, ProgressListener listener) { + public RepoXMLHandler(DB.Repo repo, Vector apps, ProgressListener listener) { this.repo = repo; this.apps = apps; pubkey = null; @@ -228,28 +231,37 @@ public class RepoXMLHandler extends DefaultHandler { curapp.requirements = DB.CommaSeparatedList.make(str); } } - } + private static Bundle createProgressData(String repoAddress) { + Bundle data = new Bundle(); + data.putString(PROGRESS_DATA_REPO, repoAddress); + return data; + } + @Override public void startElement(String uri, String localName, String qName, Attributes attributes) throws SAXException { super.startElement(uri, localName, qName, attributes); - if (localName == "repo") { + if (localName.equals("repo")) { String pk = attributes.getValue("", "pubkey"); if (pk != null) pubkey = pk; - } else if (localName == "application" && curapp == null) { + } else if (localName.equals("application") && curapp == null) { curapp = new DB.App(); curapp.detail_Populated = true; + Bundle progressData = createProgressData(repo.address); progressCounter ++; - progressListener.onProgress(RepoXMLHandler.PROGRESS_TYPE_PROCESS_XML, progressCounter, totalAppCount); - } else if (localName == "package" && curapp != null && curapk == null) { + progressListener.onProgress( + new ProgressListener.Event( + RepoXMLHandler.PROGRESS_TYPE_PROCESS_XML, progressCounter, + totalAppCount, progressData)); + } else if (localName.equals("package") && curapp != null && curapk == null) { curapk = new DB.Apk(); curapk.id = curapp.id; - curapk.repo = repo; + curapk.repo = repo.id; hashType = null; - } else if (localName == "hash" && curapk != null) { + } else if (localName.equals("hash") && curapk != null) { hashType = attributes.getValue("", "type"); } curchars.setLength(0); @@ -263,7 +275,8 @@ public class RepoXMLHandler extends DefaultHandler { // empty if none was available. private static int getRemoteFile(Context ctx, String url, String dest, String etag, StringBuilder retag, - ProgressListener progressListener ) throws MalformedURLException, + ProgressListener progressListener, + ProgressListener.Event progressEvent) throws MalformedURLException, IOException { long startTime = System.currentTimeMillis(); @@ -280,14 +293,14 @@ public class RepoXMLHandler extends DefaultHandler { // - 5k takes ~3 seconds // on my connection. I think the 1/1.5 seconds is worth it, because as the repo grows, the tradeoff will // become more worth it. - int size = connection.getContentLength(); - Log.d("FDroid", "Downloading " + size + " bytes from " + url); + progressEvent.total = connection.getContentLength(); + Log.d("FDroid", "Downloading " + progressEvent.total + " bytes from " + url); InputStream input = null; OutputStream output = null; try { input = connection.getInputStream(); output = ctx.openFileOutput(dest, Context.MODE_PRIVATE); - Utils.copy(input, output, size, progressListener, PROGRESS_TYPE_DOWNLOAD); + Utils.copy(input, output, progressListener, progressEvent); } finally { Utils.closeQuietly(output); Utils.closeQuietly(input); @@ -329,8 +342,11 @@ public class RepoXMLHandler extends DefaultHandler { address += "?" + pi.versionName; } catch (Exception e) { } + Bundle progressData = createProgressData(repo.address); + ProgressListener.Event event = new ProgressListener.Event( + RepoXMLHandler.PROGRESS_TYPE_DOWNLOAD, progressData); code = getRemoteFile(ctx, address, "tempindex.jar", - repo.lastetag, newetag, progressListener); + repo.lastetag, newetag, progressListener, event ); if (code == 200) { String jarpath = ctx.getFilesDir() + "/tempindex.jar"; JarFile jar = null; @@ -385,8 +401,12 @@ public class RepoXMLHandler extends DefaultHandler { // It's an old-fashioned unsigned repo... Log.d("FDroid", "Getting unsigned index from " + repo.address); + Bundle eventData = createProgressData(repo.address); + ProgressListener.Event event = new ProgressListener.Event( + RepoXMLHandler.PROGRESS_TYPE_DOWNLOAD, eventData); code = getRemoteFile(ctx, repo.address + "/index.xml", - "tempindex.xml", repo.lastetag, newetag, progressListener); + "tempindex.xml", repo.lastetag, newetag, + progressListener, event); } if (code == 200) { @@ -394,7 +414,7 @@ public class RepoXMLHandler extends DefaultHandler { SAXParserFactory spf = SAXParserFactory.newInstance(); SAXParser sp = spf.newSAXParser(); XMLReader xr = sp.getXMLReader(); - RepoXMLHandler handler = new RepoXMLHandler(repo.id, apps, progressListener); + RepoXMLHandler handler = new RepoXMLHandler(repo, apps, progressListener); xr.setContentHandler(handler); File tempIndex = new File(ctx.getFilesDir() + "/tempindex.xml"); diff --git a/src/org/fdroid/fdroid/UpdateService.java b/src/org/fdroid/fdroid/UpdateService.java index 667e5ab4e..084af18c0 100644 --- a/src/org/fdroid/fdroid/UpdateService.java +++ b/src/org/fdroid/fdroid/UpdateService.java @@ -330,16 +330,18 @@ public class UpdateService extends IntentService implements ProgressListener { * It could be progress downloading from the repo, or perhaps processing the info from the repo. */ @Override - public void onProgress(int type, int progress, int total) { + public void onProgress(ProgressListener.Event event) { String message = ""; - if (type == RepoXMLHandler.PROGRESS_TYPE_DOWNLOAD) { - String downloadedSize = Utils.getFriendlySize( progress ); - String totalSize = Utils.getFriendlySize( total ); - int percent = (int)((double)progress/total * 100); - message = getString(R.string.status_download, downloadedSize, totalSize, percent); - } else if (type == RepoXMLHandler.PROGRESS_TYPE_PROCESS_XML) { - message = getString(R.string.status_processing_xml, progress, total); + if (event.type == RepoXMLHandler.PROGRESS_TYPE_DOWNLOAD) { + String repoAddress = event.data.getString(RepoXMLHandler.PROGRESS_DATA_REPO); + String downloadedSize = Utils.getFriendlySize( event.progress ); + String totalSize = Utils.getFriendlySize( event.total ); + int percent = (int)((double)event.progress/event.total * 100); + message = getString(R.string.status_download, repoAddress, downloadedSize, totalSize, percent); + } else if (event.type == RepoXMLHandler.PROGRESS_TYPE_PROCESS_XML) { + String repoAddress = event.data.getString(RepoXMLHandler.PROGRESS_DATA_REPO); + message = getString(R.string.status_processing_xml, repoAddress, event.progress, event.total); } sendStatus(STATUS_INFO, message); diff --git a/src/org/fdroid/fdroid/Utils.java b/src/org/fdroid/fdroid/Utils.java index d0d5bfe2f..4d73e5d2c 100644 --- a/src/org/fdroid/fdroid/Utils.java +++ b/src/org/fdroid/fdroid/Utils.java @@ -18,18 +18,9 @@ package org.fdroid.fdroid; -import java.io.Closeable; -import java.io.InputStream; -import java.io.IOException; -import java.io.OutputStream; -import java.io.BufferedReader; -import java.io.File; -import java.io.FileReader; -import java.io.IOException; +import java.io.*; public final class Utils { - private Utils() { - } public static final int BUFFER_SIZE = 4096; @@ -37,28 +28,31 @@ public final class Utils { "%.0f B", "%.0f KiB", "%.1f MiB", "%.2f GiB" }; - public static void copy(InputStream input, OutputStream output) - throws IOException { - copy(input, output, -1, null, -1); - } + public static void copy(InputStream input, OutputStream output) + throws IOException { + copy(input, output, null, null); + } - public static void copy(InputStream input, OutputStream output, int totalSize, ProgressListener progressListener, int progressType) - throws IOException { - byte[] buffer = new byte[BUFFER_SIZE]; - int bytesRead = 0; - while (true) { - int count = input.read(buffer); - if (count == -1) { - break; - } - if (progressListener != null) { - bytesRead += count; - progressListener.onProgress(progressType, bytesRead, totalSize); - } - output.write(buffer, 0, count); - } - output.flush(); - } + public static void copy(InputStream input, OutputStream output, + ProgressListener progressListener, + ProgressListener.Event templateProgressEvent) + throws IOException { + byte[] buffer = new byte[BUFFER_SIZE]; + int bytesRead = 0; + while (true) { + int count = input.read(buffer); + if (count == -1) { + break; + } + if (progressListener != null) { + bytesRead += count; + templateProgressEvent.progress = bytesRead; + progressListener.onProgress(templateProgressEvent); + } + output.write(buffer, 0, count); + } + output.flush(); + } public static void closeQuietly(Closeable closeable) { if (closeable == null) {