How to download PDF file with Retrofit and Kotlin coroutines? (2024)

Downloading a PDF file using Retrofit and Kotlin coroutines in an Android application involves setting up Retrofit to handle file downloads and using coroutines to manage asynchronous operations. Here's a step-by-step guide on how to achieve this:

Step 1: Set up Retrofit Interface for File Download

First, define your Retrofit interface to handle the file download:

interface FileDownloadService { @GET @Streaming suspend fun downloadFile(@Url fileUrl: String): ResponseBody}
  • @GET: Specifies the HTTP method as GET.
  • @Streaming: Indicates that the response body should be streamed directly without buffering in memory, which is crucial for handling large files like PDFs efficiently.
  • @Url: Annotation for specifying the complete URL dynamically.

Step 2: Configure Retrofit Client

Set up your Retrofit client in a singleton object or as needed:

object RetrofitClient { private const val BASE_URL = "https://your_base_url_here.com/" private val okHttpClient = OkHttpClient.Builder() .build() private val retrofit = Retrofit.Builder() .baseUrl(BASE_URL) .client(okHttpClient) .addConverterFactory(GsonConverterFactory.create()) .build() fun createFileDownloadService(): FileDownloadService { return retrofit.create(FileDownloadService::class.java) }}

Ensure you have added necessary dependencies in your build.gradle file:

implementation 'com.squareup.retrofit2:retrofit:2.9.0'implementation 'com.squareup.retrofit2:converter-gson:2.9.0' // Replace with your preferred converterimplementation 'com.squareup.okhttp3:okhttp:4.9.2'

Step 3: Implement Coroutine Function for File Download

Now, implement a coroutine function to handle the file download using Retrofit and coroutines:

suspend fun downloadFile(fileUrl: String, fileName: String): Boolean { val service = RetrofitClient.createFileDownloadService() return withContext(Dispatchers.IO) { try { val response = service.downloadFile(fileUrl) if (response.isSuccessful) { val downloadedFile = response.body() saveFileToStorage(downloadedFile, fileName) return@withContext true } else { // Handle unsuccessful response return@withContext false } } catch (e: Exception) { // Handle exception e.printStackTrace() return@withContext false } }}private suspend fun saveFileToStorage(body: ResponseBody?, fileName: String) { body?.let { try { val inputStream = it.byteStream() val file = File(context.getExternalFilesDir(null), fileName) FileOutputStream(file).use { outputStream -> inputStream.copyTo(outputStream) } } catch (e: Exception) { e.printStackTrace() } }}

Step 4: Call the Coroutine Function from your Activity or Fragment

Invoke the downloadFile() function from your UI component (Activity or Fragment) within a coroutine scope:

class MainActivity : AppCompatActivity() { override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // Example usage CoroutineScope(Dispatchers.Main).launch { val fileUrl = "https://example.com/path/to/file.pdf" val fileName = "example_file.pdf" val downloadSuccess = downloadFile(fileUrl, fileName) if (downloadSuccess) { Toast.makeText(this@MainActivity, "File downloaded successfully", Toast.LENGTH_SHORT).show() // Handle file download success } else { Toast.makeText(this@MainActivity, "Failed to download file", Toast.LENGTH_SHORT).show() // Handle file download failure } } }}

Explanation:

  • FileDownloadService: Retrofit interface defining the HTTP GET method for downloading files.
  • RetrofitClient: Singleton object to configure and create Retrofit instances.
  • downloadFile(): Coroutine function that uses Retrofit to initiate the file download and saves it to the external storage using saveFileToStorage().
  • saveFileToStorage(): Helper function to save the downloaded file (ResponseBody) to the external storage.
  • MainActivity: Example of how to call downloadFile() within a coroutine scope (CoroutineScope) and handle success or failure.

Permissions

Don't forget to add the necessary permissions in your AndroidManifest.xml to write to external storage:

<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

Note

  • Error Handling: Implement appropriate error handling and exception handling in downloadFile() and saveFileToStorage() based on your application's requirements.
  • UI Thread: Perform UI-related operations (like showing Toasts) in the UI thread (Dispatchers.Main), and move long-running tasks to Dispatchers.IO.

By following these steps, you can successfully download a PDF file using Retrofit and Kotlin coroutines in your Android application, ensuring efficient handling of large files and smooth user experience. Adjust the code as per your specific requirements and error handling scenarios.

Examples

  1. Android Retrofit Kotlin coroutines download PDF file example?

    • Description: Example of using Retrofit with Kotlin coroutines to download a PDF file from a server.
    • Code:
      interface ApiService { @GET("download/pdf") @Streaming suspend fun downloadPdf(): ResponseBody}class PdfDownloadActivity : AppCompatActivity() { private val apiService: ApiService by lazy { Retrofit.Builder() .baseUrl("https://example.com/api/") .addConverterFactory(ScalarsConverterFactory.create()) .build() .create(ApiService::class.java) } private fun downloadPdfFile() { val downloadRequest = apiService.downloadPdf() GlobalScope.launch(Dispatchers.IO) { try { val response = downloadRequest.execute() if (response.isSuccessful) { val pdfFile = response.body() savePdfToFile(pdfFile) } else { // Handle error } } catch (e: Exception) { // Handle exception } } } private suspend fun savePdfToFile(pdfFile: ResponseBody?) { withContext(Dispatchers.IO) { pdfFile?.let { val inputStream = it.byteStream() val file = File(getExternalFilesDir(null), "example.pdf") file.outputStream().use { output -> inputStream?.copyTo(output) output.flush() } // Optionally show a notification or open the PDF file } } }}

    This Kotlin code demonstrates using Retrofit to download a PDF file asynchronously with coroutines. The downloadPdf() function in ApiService defines the endpoint, and savePdfToFile() saves the downloaded file.

  2. Android Kotlin coroutine Retrofit download PDF to internal storage?

    • Description: Kotlin code example to download a PDF file using Retrofit and save it to internal storage.
    • Code:
      interface ApiService { @GET("download/pdf") @Streaming suspend fun downloadPdf(): ResponseBody}class PdfDownloadActivity : AppCompatActivity() { private val apiService: ApiService by lazy { Retrofit.Builder() .baseUrl("https://example.com/api/") .addConverterFactory(ScalarsConverterFactory.create()) .build() .create(ApiService::class.java) } private fun downloadPdfFile() { GlobalScope.launch(Dispatchers.Main) { try { val response = apiService.downloadPdf() if (response.isSuccessful) { val pdfFile = response.body() savePdfToFile(pdfFile) } else { // Handle error } } catch (e: Exception) { // Handle exception } } } private suspend fun savePdfToFile(pdfFile: ResponseBody?) { withContext(Dispatchers.IO) { pdfFile?.let { val inputStream = it.byteStream() val file = File(filesDir, "example.pdf") file.outputStream().use { output -> inputStream?.copyTo(output) output.flush() } // Optionally show a notification or open the PDF file } } }}

    This code is similar to the previous example but saves the downloaded PDF file to internal storage (filesDir).

  3. Kotlin coroutine Retrofit download PDF and show progress in Android?

    • Description: Example of downloading a PDF file using Retrofit with coroutines and showing download progress in an Android app.
    • Code:
      interface ApiService { @GET("download/pdf") @Streaming suspend fun downloadPdf(): ResponseBody}class PdfDownloadActivity : AppCompatActivity() { private val apiService: ApiService by lazy { Retrofit.Builder() .baseUrl("https://example.com/api/") .addConverterFactory(ScalarsConverterFactory.create()) .build() .create(ApiService::class.java) } private fun downloadPdfFile() { val downloadRequest = apiService.downloadPdf() GlobalScope.launch(Dispatchers.IO) { try { val response = downloadRequest.execute() if (response.isSuccessful) { val pdfFile = response.body() savePdfToFile(pdfFile) } else { // Handle error } } catch (e: Exception) { // Handle exception } } } private suspend fun savePdfToFile(pdfFile: ResponseBody?) { withContext(Dispatchers.IO) { pdfFile?.let { val inputStream = it.byteStream() val file = File(getExternalFilesDir(null), "example.pdf") val totalFileSize = it.contentLength() var downloadedFileSize: Long = 0 val outputStream = file.outputStream() val buffer = ByteArray(4 * 1024) var bytesRead: Int while (inputStream.read(buffer).also { bytesRead = it } != -1) { outputStream.write(buffer, 0, bytesRead) downloadedFileSize += bytesRead // Optionally update progress bar or UI with progress } outputStream.flush() outputStream.close() inputStream.close() // Optionally show a notification or open the PDF file } } }}

    This code adds a progress indicator while downloading the PDF file using Retrofit and coroutines. It reads the input stream in chunks and updates the progress as bytes are read.

  4. Kotlin coroutine Retrofit download PDF with error handling?

    • Description: Example of downloading a PDF file using Retrofit with Kotlin coroutines and handling errors.
    • Code:
      interface ApiService { @GET("download/pdf") @Streaming suspend fun downloadPdf(): ResponseBody}class PdfDownloadActivity : AppCompatActivity() { private val apiService: ApiService by lazy { Retrofit.Builder() .baseUrl("https://example.com/api/") .addConverterFactory(ScalarsConverterFactory.create()) .build() .create(ApiService::class.java) } private fun downloadPdfFile() { GlobalScope.launch(Dispatchers.Main) { try { val response = apiService.downloadPdf() if (response.isSuccessful) { val pdfFile = response.body() savePdfToFile(pdfFile) } else { // Handle HTTP error Log.e("PdfDownloadActivity", "HTTP error: ${response.code()}") } } catch (e: Exception) { // Handle network or coroutine exception Log.e("PdfDownloadActivity", "Error: ${e.message}") } } } private suspend fun savePdfToFile(pdfFile: ResponseBody?) { withContext(Dispatchers.IO) { pdfFile?.let { val inputStream = it.byteStream() val file = File(getExternalFilesDir(null), "example.pdf") file.outputStream().use { output -> inputStream?.copyTo(output) output.flush() } // Optionally show a notification or open the PDF file } } }}

    This code includes error handling for HTTP errors and exceptions during the PDF file download process.

  5. Retrofit download PDF with authentication using Kotlin coroutines?

    • Description: Example of downloading a PDF file with authentication using Retrofit and Kotlin coroutines.
    • Code:
      interface ApiService { @GET("download/pdf") @Streaming suspend fun downloadPdf( @Header("Authorization") authToken: String ): ResponseBody}class PdfDownloadActivity : AppCompatActivity() { private val apiService: ApiService by lazy { Retrofit.Builder() .baseUrl("https://example.com/api/") .addConverterFactory(ScalarsConverterFactory.create()) .build() .create(ApiService::class.java) } private fun downloadPdfFile(authToken: String) { GlobalScope.launch(Dispatchers.Main) { try { val response = apiService.downloadPdf("Bearer $authToken") if (response.isSuccessful) { val pdfFile = response.body() savePdfToFile(pdfFile) } else { // Handle HTTP error Log.e("PdfDownloadActivity", "HTTP error: ${response.code()}") } } catch (e: Exception) { // Handle network or coroutine exception Log.e("PdfDownloadActivity", "Error: ${e.message}") } } } private suspend fun savePdfToFile(pdfFile: ResponseBody?) { withContext(Dispatchers.IO) { pdfFile?.let { val inputStream = it.byteStream() val file = File(getExternalFilesDir(null), "example.pdf") file.outputStream().use { output -> inputStream?.copyTo(output) output.flush() } // Optionally show a notification or open the PDF file } } }}

    This code demonstrates downloading a PDF file with authentication using a Bearer token passed as a header in the Retrofit request.

More Tags

databaseselenium-ideamazon-redshiftc#-3.0azure-redis-cachetls1.2php-carbonvisual-studio-2015file-sharingdata-extraction

More Programming Questions

  • C++ Pointer to Structure
  • PostgreSQL - Removing Temporary Table
  • HTML comments
  • MySQL AUTO_INCREMENT: Primary Key Auto-increment
  • Access memory address in python
  • Make TextBox uneditable in Winforms/WPF
  • How to specify method return type list of (what) in Python?
  • How to Maximize Code Reuse in this Interface vs Inheritance C# Example
  • Ensuring py.test includes the application directory in sys.path
How to download PDF file with Retrofit and Kotlin coroutines? (2024)
Top Articles
Latest Posts
Article information

Author: Jamar Nader

Last Updated:

Views: 6255

Rating: 4.4 / 5 (75 voted)

Reviews: 82% of readers found this page helpful

Author information

Name: Jamar Nader

Birthday: 1995-02-28

Address: Apt. 536 6162 Reichel Greens, Port Zackaryside, CT 22682-9804

Phone: +9958384818317

Job: IT Representative

Hobby: Scrapbooking, Hiking, Hunting, Kite flying, Blacksmithing, Video gaming, Foraging

Introduction: My name is Jamar Nader, I am a fine, shiny, colorful, bright, nice, perfect, curious person who loves writing and wants to share my knowledge and understanding with you.