AntennaPod - 开源Android播客管理器
AntennaPod是一款功能丰富、易于使用的开源Android播客管理器,致力于为用户提供纯净、无广告的播客收听体验。
功能特性
- 智能播客管理:轻松订阅、管理和组织您的播客收藏
- 自动下载:支持在WiFi环境下自动下载新剧集,节省流量
- 播放控制:完整的播放控制功能,包括播放、暂停、跳过等
- 多平台同步:支持与Gpodder.net等平台进行订阅同步
- 本地播客支持:能够管理和播放设备本地的音频文件
- 个性化设置:可自定义播放速度、音量增强、睡眠定时器等
- 无广告体验:完全开源,没有任何广告干扰
- 多搜索源:集成iTunes、Podcast Index等多个播客搜索源
安装指南
系统要求
- Android 5.0 (API 21) 或更高版本
- 至少50MB可用存储空间
安装方式
Google Play商店
在Google Play商店中搜索"AntennaPod"并安装
F-Droid
在F-Droid应用商店中搜索"AntennaPod"并安装
手动安装
- 从GitHub Releases页面下载最新APK文件
- 在Android设备上启用"未知来源"安装权限
- 安装下载的APK文件
依赖项
- AndroidX库
- Material Design组件
- OkHttp网络库
- RxJava响应式编程库
使用说明
基础使用
添加播客订阅
- 点击主界面右下角的"+"按钮
- 在搜索框中输入播客名称或URL
- 从搜索结果中选择要订阅的播客
- 点击"订阅"按钮
播放控制
// 播放剧集
new PlaybackServiceStarter(context, media).callEvenIfRunning(true).start();// 暂停播放
context.sendBroadcast(MediaButtonStarter.createIntent(context, KeyEvent.KEYCODE_MEDIA_PAUSE));
下载管理
// 下载剧集
DownloadServiceInterface.get().downloadNow(context, item, false);// 取消下载
DownloadServiceInterface.get().cancel(context, media);
高级功能
自动下载设置
- 进入设置 → 网络 → 自动下载
- 配置在WiFi环境下自动下载新剧集
- 设置要保留的剧集数量
播放列表管理
- 创建自定义播放列表
- 设置播放顺序(顺序、随机等)
- 管理队列中的剧集
核心代码
应用初始化配置
package de.danoeh.antennapod;public class ClientConfigurator {private static boolean initialized = false;public static synchronized void initialize(Context context) {if (initialized) return;// 配置用户代理PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);UserAgentInterceptor.USER_AGENT = "AntennaPod/" + packageInfo.versionName;// 初始化数据库和偏好设置PodDBAdapter.init(context);UserPreferences.init(context);SynchronizationCredentials.init(context);// 配置网络组件SslProviderInstaller.install(context);NetworkUtils.init(context);DownloadServiceInterface.setImpl(new DownloadServiceInterfaceImpl());initialized = true;}
}
播放动作按钮系统
package de.danoeh.antennapod.actionbutton;public abstract class ItemActionButton {FeedItem item;public abstract int getLabel(); // 按钮文本public abstract int getDrawable(); // 按钮图标public abstract void onClick(Context context); // 点击动作// 根据剧集状态自动选择合适的动作按钮public static ItemActionButton forItem(@NonNull FeedItem item) {final FeedMedia media = item.getMedia();if (media == null) {return new MarkAsPlayedActionButton(item);}if (PlaybackStatus.isCurrentlyPlaying(media)) {return new PauseActionButton(item); // 暂停按钮} else if (media.isDownloaded()) {return new PlayActionButton(item); // 播放按钮} else if (isDownloadingMedia) {return new CancelDownloadActionButton(item); // 取消下载按钮} else {return new DownloadActionButton(item); // 下载按钮}}
}
下载服务实现
package de.danoeh.antennapod.net.download.service.episode;public class EpisodeDownloadWorker extends Worker {@Overridepublic Result doWork() {// 创建下载请求DownloadRequest request = new DownloadRequest(destination, source, title, feedfileId, feedfileType,lastModified, username, password, false, arguments, initiatedByUser);// 执行下载Downloader downloader = new HttpDownloader(request);downloader.call();// 处理下载结果if (downloader.getResult().isSuccessful()) {handleSuccessfulDownload(context, downloader.getResult(), request);return Result.success();} else {return Result.failure();}}private void handleSuccessfulDownload(Context context, DownloadResult result, DownloadRequest request) {FeedMedia media = DBReader.getFeedMedia(request.getFeedfileId());if (media != null) {media.setDownloaded(true);media.setLocalFileUrl(request.getDestination());DBWriter.setFeedMedia(media);}}
}
自动下载算法
package de.danoeh.antennapod.net.download.service.episode.autodownload;public class AutomaticDownloadAlgorithm {public Runnable autoDownloadUndownloadedItems(final Context context) {return () -> {// 检查网络条件boolean networkShouldAutoDl = NetworkUtils.isAutoDownloadAllowed();// 检查电源条件boolean powerShouldAutoDl = deviceCharging(context) || UserPreferences.isEnableAutodownloadOnBattery();if (networkShouldAutoDl && powerShouldAutoDl) {// 获取可下载的剧集List<FeedItem> queue = DBReader.getQueue();List<FeedItem> unreadItems = DBReader.getEpisodes(0, Integer.MAX_VALUE,new FeedItemFilter(FeedItemFilter.UNPLAYED), SortOrder.DATE_NEW_OLD);// 筛选并下载符合条件的剧集for (FeedItem item : queue) {if (shouldDownload(item)) {DownloadServiceInterface.get().download(context, item);}}}};}
}
崩溃报告系统
package de.danoeh.antennapod;public class CrashReportWriter implements Thread.UncaughtExceptionHandler {@Overridepublic void uncaughtException(Thread thread, Throwable ex) {write(ex);defaultHandler.uncaughtException(thread, ex);}public static void write(Throwable exception) {File path = getFile();try (PrintWriter out = new PrintWriter(path, "UTF-8")) {out.println("## Crash info");out.println("Time: " + new SimpleDateFormat("dd-MM-yyyy HH:mm:ss").format(new Date()));out.println("AntennaPod version: " + BuildConfig.VERSION_NAME);out.println();out.println("## StackTrace");out.println("```");exception.printStackTrace(out);out.println("```");}}public static String getSystemInfo() {return "## Environment"+ "\nAndroid version: " + Build.VERSION.RELEASE+ "\nAntennaPod version: " + BuildConfig.VERSION_NAME+ "\nModel: " + Build.MODEL;}
}
更多精彩内容 请关注我的个人公众号 公众号(办公AI智能小助手)
对网络安全、黑客技术感兴趣的朋友可以关注我的安全公众号(网络安全技术点滴分享)
公众号二维码
公众号二维码