- Translate the interface to Galician (tools/translate_gl.py), including Galician month abbreviations for dates, which Android 2.3 lacks - Resize for the Galaxy Mini's 240x320 screen: larger text, rows, tabs and buttons; all sizes now live in res/values/dimens.xml - Redraw play/pause/refresh icons for every density; slightly brighter secondary text colours Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
144 lines
4.5 KiB
Java
144 lines
4.5 KiB
Java
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: <id>.<ext> plus <id>.json with the episode details. */
|
|
final class Downloads {
|
|
private Downloads() {
|
|
}
|
|
|
|
private static HashSet<String> 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<Episode> list(Context c) {
|
|
List<Episode> out = new ArrayList<Episode>();
|
|
HashSet<String> found = new HashSet<String>();
|
|
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<Episode>() {
|
|
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();
|
|
}
|
|
}
|
|
}
|