package com.miniabs; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.Reader; import java.io.Writer; import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.HashSet; import java.util.List; import org.json.JSONObject; import android.content.Context; import android.os.Environment; /** Downloaded episodes live on the SD card: . plus .json with the episode details. */ final class Downloads { private Downloads() { } private static HashSet ids; static File dir(Context c) throws IOException { if (!Environment.MEDIA_MOUNTED.equals(Environment.getExternalStorageState())) { throw new IOException("Non hai tarxeta SD dispoñible. Insírea ou desconéctaa do USB para descargar."); } File d = c.getExternalFilesDir(Environment.DIRECTORY_PODCASTS); if (d == null) throw new IOException("Non se pode usar a tarxeta SD."); if (!d.exists() && !d.mkdirs()) throw new IOException("Non se pode crear un cartafol na tarxeta SD."); File nomedia = new File(d, ".nomedia"); if (!nomedia.exists()) { try { nomedia.createNewFile(); } catch (IOException ignored) { } } return d; } static File audio(Context c, Episode e) { try { File f = new File(dir(c), e.id + e.ext); return f.exists() && f.length() > 0 ? f : null; } catch (IOException ex) { return null; } } static synchronized boolean has(Context c, String epId) { if (ids == null) scan(c); return ids.contains(epId); } /** Reads the download folder and returns saved episodes, newest first. */ static synchronized List list(Context c) { List out = new ArrayList(); HashSet found = new HashSet(); try { File[] files = dir(c).listFiles(); if (files != null) { for (File f : files) { if (!f.getName().endsWith(".json")) continue; try { Episode e = Episode.fromStored(new JSONObject(readFile(f))); if (audio(c, e) != null) { out.add(e); found.add(e.id); } } catch (Exception ignored) { } } } } catch (IOException ignored) { } ids = found; Collections.sort(out, new Comparator() { public int compare(Episode a, Episode b) { return a.published == b.published ? 0 : (a.published > b.published ? -1 : 1); } }); return out; } static synchronized void scan(Context c) { list(c); } static synchronized void saved(Context c, Episode e) throws IOException { Writer w = new OutputStreamWriter(new FileOutputStream(new File(dir(c), e.id + ".json")), "UTF-8"); try { w.write(e.toJson().toString()); } finally { w.close(); } if (ids == null) scan(c); ids.add(e.id); } static synchronized void delete(Context c, Episode e) { try { File d = dir(c); new File(d, e.id + e.ext).delete(); new File(d, e.id + ".json").delete(); new File(d, e.id + ".part").delete(); } catch (IOException ignored) { } if (ids != null) ids.remove(e.id); App.forgetLocal(c, e.id); } static synchronized int deleteAll(Context c) { int n = 0; for (Episode e : list(c)) { delete(c, e); n++; } try { File[] parts = dir(c).listFiles(); if (parts != null) for (File f : parts) if (f.getName().endsWith(".part")) f.delete(); } catch (IOException ignored) { } return n; } private static String readFile(File f) throws IOException { Reader r = new InputStreamReader(new FileInputStream(f), "UTF-8"); try { StringBuilder sb = new StringBuilder(); char[] b = new char[2048]; int n; while ((n = r.read(b)) > 0) sb.append(b, 0, n); return sb.toString(); } finally { r.close(); } } }