Open-source project
amugofjava/anytime_podcast_player avatar
amugofjava/anytime_podcast_player

Anytime Podcast Player: a Flutter podcast app with a fixed Flutter ceiling

Simple, easy to use Podcast player app written in Flutter and Dart.

625 stars140 forksDartBSD-3-Clause

At a glance

What is it?
Anytime Podcast Player is a Dart and Flutter podcast client for Android and iOS that searches iTunes and PodcastIndex, plays in the background and stores state in Sembast. It ships as a store app and as source that pins Flutter 3.27.4, which is the main constraint for anyone building on it.
Who is it for?
Anytime Podcast Player suits people who want a working cross platform podcast client to install from a store, and developers who want a readable Flutter example of BLoC, Streams and a layered service design. It is a poor base for a team that needs an active upstream release cadence, because the last push was on 2026-04-22 and the code deliberately stays pinned to Flutter 3.27.4 to dodge an iOS accessibility bug.
Can I use it commercially?
Yes. BSD-3-Clause is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Activity is slowing. The repository last received commits 6 months ago.
What is it written in?
Mainly Dart, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

What Anytime Podcast Player is built for

Anytime is a podcast playing app for Android and iOS, written in Dart and Flutter, and the project describes itself as simple and easy to use. The scope is a consumer listening client rather than a platform: it finds podcasts, plays episodes, and keeps the state of both across the session and across restarts. The repository topics list android, ios, flutter, dart and podcast-player, and the tree shows both native shells, android/ and ios/, alongside lib/ for the shared Dart code.

Two audiences read this repository differently. End users install the app from the Play Store, the Amazon App Store, the Apple App Store, or F-Droid, and the project links each of those badges. Developers read the source because it is a compact, complete example of how a Flutter app is put together when you take the BLoC pattern seriously, with Streams doing the work of carrying data between layers.

The choice to keep the app mobile only is explicit in the architecture notes, which say the UI layer is currently mobile but could be extended to web or desktop in the future. Nothing in the tree suggests that work has started, so treat that as a stated intention rather than a plan with dates.

The layered BLoC design and where state actually lives

The architecture is described as layered, and the layers are named: UI, BLoC, Services, API, Repository. The important detail is how the layers talk. Communication between the UI and the BLoC happens entirely through Sinks and Streams, which means the widget tree never calls a repository or an HTTP client directly. It subscribes to a stream and renders what arrives.

That choice is what the RxDart package is there for, since it adds capabilities to Dart Streams and StreamControllers. The UI is therefore a function of a stream, and the flow of a screen becomes a sequence of stream events rather than a sequence of method calls that mutate fields.

Data handling sits below the BLoC layer in Services, which interact with the API and the Repository to provide routines to the BLoCs. The API layer is where the iTunes API is called through a package, and the Repository layer is what provides persistent storage. Storage itself is Sembast, described as a NoSQL persistent store, which for an app holding subscriptions and playback positions is a reasonable fit, since there is no fixed schema to migrate.

Audio playback is handled by the audio_service package, which provides background support so that playback survives leaving the app. Podcast discovery and feed parsing come from podcast_search. Those five packages are the load bearing dependencies, and the pubspec.lock in the tree pins their versions for you.

Podcast search across iTunes and PodcastIndex

Search runs against two services. iTunes needs no configuration and works out of the box. PodcastIndex needs credentials, and the mechanism for supplying them is worth understanding because it is a build time decision rather than a settings screen.

You register at podcastindex.org, and that account produces a key and a secret. Those two values are passed to the app as runtime arguments when you launch it:

bash
flutter run --dart-define=PINDEX_KEY=mykey --dart-define=PINDEX_SECRET=mysecret

When you work from Android Studio instead of the command line, the same two definitions go into the run configuration's command line arguments field:

bash
-t lib/main.dart --dart-define=PINDEX_KEY=mykey --dart-define=PINDEX_SECRET=mysecret

One practical warning from the project applies to the second form. There must be exactly one space between each argument, and an extra space between any of them prevents them from reaching Flutter correctly. This is the kind of detail that costs an afternoon when it goes wrong and is not obvious from the error message.

The consequence for anyone shipping their own build is that the PodcastIndex credentials are compiled in as Dart defines, so they are part of the artefact rather than something a user types in. There is no documented way to give a user their own PodcastIndex account in the current documentation.

Building from source with the Flutter SDK

The build path assumes you already have the Flutter SDK, and if you do not, the project points you at the Flutter installation instructions on flutter.dev. The current version of the app is v1.4.x, and the project states it is built against Flutter 3.27.4 or later.

Clone the repository, then resolve the packages inside the project directory:

bash
git clone https://github.com/amugofjava/anytime_podcast_player.git
bash
flutter packages get

After that you can either launch it on a connected device or emulator, which is the faster loop when you are changing Dart code:

bash
flutter run

Or produce an installable Android package:

bash
flutter build apk

Two build artefacts are worth noting. The docs/ directory holds the screenshots used in the README, and the store badges are static images in the same folder, so an image change is a docs change. The xl10n.yaml file at the root points at the localisation setup, and TRANSLATION.md explains how translations are handled, since the project also accepts translation work through Weblate.

Why the code stays pinned to Flutter 3.27.4

This is the sharpest constraint in the repository and it shapes every decision a contributor has to make. Two Flutter problems forced it. On iOS, versions after 3.27.4 carry a significant accessibility bug, tracked in the Flutter issue tracker. On Android, a much later Flutter version is needed for 16KB alignment support.

The result is a separate branch, feature/ios-f374-patch, dedicated to iOS, and an explicit intent to keep the overall code compatible with Flutter 3.27.4 for as long as the iOS bug is open. The practical effect for a developer is that the analyser will complain about deprecated values, and the project asks you to ignore those warnings for now rather than fix them.

That is a reasonable temporary position and an awkward long term one. A codebase that deliberately holds deprecated API usage is a codebase that will need a migration pass when the upstream bug is fixed, and nothing in the documentation dates that pass. Anyone taking this code as a foundation should treat the deprecated analyser warnings as a known cost rather than as sloppiness, and should check the state of the Flutter accessibility issue before planning work that depends on a newer SDK.

Opening a feed from a website with Anytime links

Anytime registers as a handler for podcast links, so a website can hand a feed to the app. The mechanism is a URL on the project's own site, anytimeplayer.app, that carries the feed address as a query parameter:

bash
https://anytimeplayer.app/subscribe?url=www.example.com/myfeed.xml

The pattern is worth noting if you run a site with a podcast: you build a subscribe link in the shape shown above, and the user ends up in the app with that feed loaded. The site handles the hand off, the app resolves the feed.

Two limits are visible in the documentation. The example feed path is a plain XML feed URL, so the design assumes an address the app can parse directly rather than a page that merely mentions a podcast. And the link carries no authentication or feed identifier beyond the URL itself, so it cannot be used to open a feed that requires credentials. The README does not document how the app decides whether to hand off to the store or open internally.

Distribution, releases and the state of the tree

Anytime is distributed through several channels at once, which tells you something about the audience. The stable release is on the Play Store, the Amazon App Store, the Apple App Store, and F-Droid. A Beta channel also exists on the Play Store, and the project asks testers to sign up for it and to send feedback of any kind, positive or negative. Build status is tracked with Codemagic, and the badge is wired into the README.

The release history is regular and versioned: v1.3.14 on 2025-10-08, v1.4.0 on 2025-12-30, and v1.4.1 on 2026-01-21. The default branch is master. The last push was on 2026-04-22, which is three months after the most recent release and a sign that the pace has slowed rather than stopped, so plan around a project with a low change rate rather than one that lands features every few weeks.

The licence is a BSD-style licence, with the full terms in the LICENSE file. That is a permissive licence with the usual attribution obligation, so the copyright notice and licence text need to travel with redistributed copies of the code, including inside a modified application. Read the LICENSE file directly before you rely on that summary, since the specifics matter for how you distribute a derivative build.

Editorial conclusion

Anytime Podcast Player suits people who want a working cross platform podcast client to install from a store, and developers who want a readable Flutter example of BLoC, Streams and a layered service design. It is a poor base for a team that needs an active upstream release cadence, because the last push was on 2026-04-22 and the code deliberately stays pinned to Flutter 3.27.4 to dodge an iOS accessibility bug. Before adopting the code, check the Flutter version you need against that pin, confirm that PodcastIndex credentials can be supplied through --dart-define at build time, and read the BSD licence terms in the LICENSE file yourself.

Frequently asked questions

What does Anytime Podcast Player use for state management and storage?

The UI and the BLoC layer communicate entirely through Sinks and Streams, with RxDart extending Dart Streams and StreamControllers. Persistent storage is handled by the Repository layer on top of Sembast, described as a NoSQL persistent store.

How do I enable PodcastIndex search in Anytime Podcast Player?

Create an account at podcastindex.org to get a key and a secret, then pass them at launch with --dart-define=PINDEX_KEY=mykey --dart-define=PINDEX_SECRET=mysecret. The values are supplied as build time definitions, not entered in the app.

Which Flutter version does Anytime Podcast Player need?

The project is built against Flutter 3.27.4 or later, and the code is deliberately kept compatible with 3.27.4 because of an iOS accessibility bug in later versions. iOS work happens on a separate feature/ios-f374-patch branch.

Can I build and run Anytime Podcast Player from source?

Yes, with the Flutter SDK installed. Clone the repository, run flutter packages get inside the project directory, then either flutter run for a device session or flutter build apk to produce an Android package.

What licence is Anytime Podcast Player released under?

It is released under a BSD-style licence, and the repository states that you should see the LICENSE file for the full details. The terms require the copyright notice and licence text to accompany redistributed copies of the code.

Official sources

  1. amugofjava/anytime_podcast_player on GitHub
  2. Issues
  3. License: BSD-3-Clause
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/amugofjava-anytime-podcast-player.svg)](https://hysenlabs.com/projects/amugofjava-anytime-podcast-player)

Was this useful?