docs: Add flutter download support documentation#97
docs: Add flutter download support documentation#97Balamurugan-Testpress merged 1 commit intomainfrom
Conversation
Balamurugan-Testpress
commented
Mar 30, 2026
- Developers lacked clear guidance on enabling downloads and offline playback in Flutter
- This was due to missing documentation around player configuration, license expiry, and download handling
- Added comprehensive docs covering download enablement, offline license duration, programmatic download management, progress tracking, and offline playback
There was a problem hiding this comment.
Code Review
This pull request adds comprehensive documentation for the Flutter SDK's download functionality, including setup, management, and code examples. Reviewers suggested clarifying the startDownload method signature, updating the metadata parameter type to reflect null safety, and improving the Flutter usage example by implementing proper stream subscription management and mounted checks to avoid potential memory leaks.
| ```dart | ||
| final downloadManager = TPStreamsDownloadManager(); | ||
|
|
||
| await downloadManager.startDownload( | ||
| assetId, // String: Required | ||
| accessToken, // String: Required | ||
| metadata, // Map<String, String> | null: Optional custom metadata | ||
| ); | ||
| ``` |
There was a problem hiding this comment.
The code example for startDownload is a bit ambiguous. It's not clear if the parameters are positional or named, and the example mixes a method call with parameter type comments, which can be confusing.
For better clarity, I suggest adopting the documentation style used in player-methods.md: first show the method signature, and then provide a clean example of how to call it.
For example:
startDownload
Future<void> startDownload(String assetId, String accessToken, {Map<String, String>? metadata})
Initiates a video download for offline playback.
Example:
await downloadManager.startDownload(
'YOUR_ASSET_ID',
'YOUR_ACCESS_TOKEN',
metadata: {'source': 'example'}
);(Note: The signature above is just an example; please use the actual method signature.)
| | :--- | :--- | :--- | | ||
| | `assetId` | `String` | Unique identifier for the video asset. | | ||
| | `accessToken` | `String` | Valid access token for the video. | | ||
| | `metadata` | `Map<String, String>` | (Optional) Any custom key-value pairs you want to attach to the download. | |
There was a problem hiding this comment.
In the startDownload parameters table, the type for metadata is listed as Map<String, String>. To be consistent with Dart's null safety and the code example comment on line 36 which indicates it's nullable, it would be clearer to represent the type as Map<String, String>?.
| | `metadata` | `Map<String, String>` | (Optional) Any custom key-value pairs you want to attach to the download. | | |
| | `metadata` | `Map<String, String>?` | (Optional) Any custom key-value pairs you want to attach to the download. | |
| _downloadManager.downloadsStream.listen((downloads) { | ||
| setState(() { | ||
| _downloads = downloads; | ||
| }); | ||
| }); |
There was a problem hiding this comment.
In the initState method, you're subscribing to downloadsStream. This creates a StreamSubscription that should be explicitly cancelled in the dispose method to prevent potential memory leaks if the widget is disposed. While _downloadManager.dispose() might handle this, it's a Flutter best practice to manage subscriptions explicitly.
Also, it's safer to check if the widget is mounted before calling setState in an async callback.
Here's a more robust implementation:
class _MyDownloadPageState extends State<MyDownloadPage> {
final _downloadManager = TPStreamsDownloadManager();
List<DownloadAsset> _downloads = [];
StreamSubscription<List<DownloadAsset>>? _downloadsSubscription;
@override
void initState() {
super.initState();
_downloadsSubscription = _downloadManager.downloadsStream.listen((downloads) {
if (mounted) {
setState(() {
_downloads = downloads;
});
}
});
}
// ... build method ...
@override
void dispose() {
_downloadsSubscription?.cancel();
_downloadManager.dispose();
super.dispose();
}
}