184 lines
7.1 KiB
Markdown
Executable File
184 lines
7.1 KiB
Markdown
Executable File
# [Android Components](../../../README.md) > Feature > Downloads
|
|
|
|
Feature implementation for apps that want to use [Android downloads manager](https://developer.android.com/reference/android/app/DownloadManager).
|
|
|
|
## Usage
|
|
|
|
### Setting up the dependency
|
|
|
|
Use Gradle to download the library from [maven.mozilla.org](https://maven.mozilla.org/) ([Setup repository](../../../README.md#maven-repository)):
|
|
|
|
```Groovy
|
|
implementation "org.mozilla.components:feature-downloads:{latest-version}"
|
|
```
|
|
|
|
The `AbstractFetchDownloadService` also requires extra permissions needed to post notifications and to start downloads
|
|
- `android.permission.POST_NOTIFICATIONS`
|
|
- `android.permission.FOREGROUND_SERVICE`
|
|
- `android.permission.FOREGROUND_SERVICE_MEDIA_PLAYBACK`
|
|
|
|
The implementing service in the client app also needs to declare `dataSync` as `foregroundServiceType` in the manifest for
|
|
Android 14 compatibility. Adding the `FOREGROUND_SERVICE_DATA_SYNC` permission in the app manifest is not needed since it is declared in feature-downloads module.
|
|
|
|
### DownloadsFeature
|
|
Feature implementation for proving download functionality for the selected session.
|
|
|
|
```kotlin
|
|
|
|
|
|
//This will be called before starting each download in case you don't have the right permissions
|
|
// or if the user removed your permissions.
|
|
val onNeedToRequestPermissions = {
|
|
session: Session, download: Download ->
|
|
//request permission e.g (WRITE_EXTERNAL_STORAGE)
|
|
|
|
// After you get granted the permissions, remember to call downloadsFeature.onPermissionsGranted()
|
|
// to start downloading the pending download.
|
|
}
|
|
|
|
//This will be called after every download is completed.
|
|
val onDownloadCompleted = {
|
|
download: Download, downloadId: Long ->
|
|
//Show some UI to let user know the download was completed.
|
|
}
|
|
|
|
val downloadsFeature =
|
|
DownloadsFeature(context,
|
|
onNeedToRequestPermissions /*Optional*/,
|
|
onDownloadCompleted /*Optional*/,
|
|
fragmentManager /*Optional, if it is provided, before every download a dialog will be shown*/,
|
|
dialog /*Optional, if it is not provided a simple dialog will be shown before every download, with a positive button and negative button.*/,
|
|
sessionManager = sessionManager)
|
|
|
|
//Starts observing the selected session for new downloads and forward it to
|
|
// the download manager
|
|
downloadsFeature.start()
|
|
|
|
//Stop observing the selected session
|
|
downloadsFeature.stop()
|
|
|
|
```
|
|
|
|
### DownloadDialogFragment
|
|
This is general representation of a dialog meant to be used in collaboration with `DownloadsFeature`
|
|
to show a dialog before a download is triggered. If `SimpleDownloadDialogFragment` is not flexible enough for your use case you should inherit for this class.
|
|
|
|
```kotlin
|
|
class FocusDialogDownloadFragment : DownloadDialogFragment() {
|
|
|
|
/*Creating a customized the dialog*/
|
|
override fun onCreateDialog(bundle: Bundle?): AlertDialog {
|
|
//DownloadsFeature will add these metadata before calling show() on the dialog.
|
|
val fileName = arguments?.getString(KEY_FILE_NAME)
|
|
//Not used, just for the sake you can use this metadata
|
|
val url = arguments?.getString(KEY_URL)
|
|
val contentLength = arguments?.getString(KEY_CONTENT_LENGTH)
|
|
|
|
val builder = AlertDialog.Builder(requireContext())
|
|
builder.setCancelable(true)
|
|
builder.setTitle(getString(R.string.download_dialog_title))
|
|
|
|
val inflater = activity!!.layoutInflater
|
|
val dialogView = inflater.inflate(R.layout.download_dialog, null)
|
|
builder.setView(dialogView)
|
|
|
|
dialogView.download_dialog_icon.setImageResource(R.drawable.ic_download)
|
|
dialogView.download_dialog_file_name.text = fileName
|
|
dialogView.download_dialog_cancel.text = getString(R.string.download_dialog_action_cancel)
|
|
dialogView.download_dialog_download.text =
|
|
getString(R.string.download_dialog_action_download)
|
|
|
|
dialogView.download_dialog_warning.text = getString(R.string.download_dialog_warning)
|
|
|
|
setCancelButton(dialogView.download_dialog_cancel)
|
|
setDownloadButton(dialogView.download_dialog_download)
|
|
|
|
return builder.create()
|
|
}
|
|
|
|
private fun setDownloadButton(button: Button) {
|
|
button.setOnClickListener {
|
|
//Letting know DownloadFeature that can proceed with the download
|
|
onStartDownload()
|
|
TelemetryWrapper.downloadDialogDownloadEvent(true)
|
|
dismiss()
|
|
}
|
|
}
|
|
|
|
private fun setCancelButton(button: Button) {
|
|
button.setOnClickListener {
|
|
TelemetryWrapper.downloadDialogDownloadEvent(false)
|
|
dismiss()
|
|
}
|
|
}
|
|
}
|
|
|
|
//Adding our dialog to DownloadsFeature
|
|
val downloadsFeature = DownloadsFeature(
|
|
context(),
|
|
sessionManager = sessionManager,
|
|
fragmentManager = fragmentManager,
|
|
dialog = FocusDialogDownloadFragment()
|
|
)
|
|
|
|
downloadsFeature.start()
|
|
```
|
|
|
|
### SimpleDownloadDialogFragment
|
|
|
|
A confirmation dialog to be called before a download is triggered.
|
|
|
|
SimpleDownloadDialogFragment is the default dialog if you don't provide a value to DownloadsFeature.
|
|
It is composed by a title, a negative and a positive bottoms. When the positive button is clicked the download is triggered.
|
|
|
|
```kotlin
|
|
//To use the default behavior, just provide a fragmentManager/childFragmentManager.
|
|
downloadsFeature = DownloadsFeature(
|
|
requireContext(),
|
|
sessionManager = components.sessionManager,
|
|
fragmentManager = fragmentManager /*If you're inside a Fragment use childFragmentManager '*/
|
|
)
|
|
|
|
downloadsFeature.start()
|
|
```
|
|
Customizing SimpleDownloadDialogFragment.
|
|
|
|
```kotlin
|
|
val dialog = SimpleDownloadDialogFragment.newInstance(
|
|
dialogTitleText = R.string.dialog_title,
|
|
positiveButtonText = R.string.download,
|
|
negativeButtonText = R.string.cancel,
|
|
cancelable = true,
|
|
themeResId = R.style.your_theme
|
|
)
|
|
|
|
downloadsFeature = DownloadsFeature(
|
|
requireContext(),
|
|
sessionManager = components.sessionManager,
|
|
fragmentManager = fragmentManager,
|
|
dialog = dialog
|
|
)
|
|
|
|
downloadsFeature.start()
|
|
```
|
|
|
|
## Facts
|
|
|
|
This component emits the following [Facts](../../support/base/README.md#Facts):
|
|
|
|
| Action | Item | Description |
|
|
|-----------|--------------|---------------------------------------------------|
|
|
| RESUME | notification | The user resumes a download. |
|
|
| PAUSE | notification | The user pauses a download. |
|
|
| CANCEL | notification | The user cancels a download. |
|
|
| TRY_AGAIN | notification | The user taps on try again when a download fails. |
|
|
| OPEN | notification | The user opens a downloaded file. |
|
|
| DISPLAY | prompt | A download prompt was shown. |
|
|
| CANCEL | prompt | A download prompt was canceled. |
|
|
|
|
## License
|
|
|
|
This Source Code Form is subject to the terms of the Mozilla Public
|
|
License, v. 2.0. If a copy of the MPL was not distributed with this
|
|
file, You can obtain one at http://mozilla.org/MPL/2.0/
|