Import miniabs 1.0 source

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
xockoandClaude Opus 5.5 committed 2026-10-14 19:26:04 +02:00
commit 4fe9eed870
78 files changed
+5800

No files matched your search

+143
View File
@@ -0,0 +1,143 @@
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("No SD card available. Insert or unmount it from USB to download.");
}
File d = c.getExternalFilesDir(Environment.DIRECTORY_PODCASTS);
if (d == null) throw new IOException("Can't use the SD card.");
if (!d.exists() && !d.mkdirs()) throw new IOException("Can't create a folder on the SD card.");
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();
}
}
}