Technical Implementation and Analysis of Downloading PDF from URL and Opening in Android

Dec 04, 2025 · Programming · 13 views · 7.8

Keywords: Android Development | PDF Download | HttpURLConnection | File Storage | Intent Invocation

Abstract: This paper provides an in-depth exploration of the complete technical process for downloading PDF files from URLs and opening them with external readers in Android applications. By analyzing a common issue where downloaded files become corrupted, it reveals a critical configuration error in HttpURLConnection—incorrectly setting the setDoOutput(true) method. The article offers detailed problem analysis, corrected complete code implementation covering asynchronous downloading, file storage, permission management, and Intent invocation. Additionally, it discusses modern API alternatives and security considerations based on Android development best practices, providing reliable technical references for developers.

Technical Background and Problem Description

In Android application development, implementing the functionality to download PDF files from remote servers and open them with third-party readers on local devices is a common requirement. Developers typically need to handle multiple technical aspects including network requests, file storage, permission management, and inter-app communication. However, even when code appears to execute correctly, downloaded files may become corrupted due to improper configuration, preventing external readers from opening them properly.

Problem Analysis and Core Error

Through detailed analysis of the original code, the core issue was identified in the HttpURLConnection configuration within the FileDownloader class. The original code incorrectly called the urlConnection.setDoOutput(true) method. This method is typically used for POST requests, indicating that the connection will be used for output data. Setting this flag in GET requests causes abnormal connection behavior, potentially affecting the correct reading of input streams and resulting in corrupted downloaded file content.

The correction is simple yet crucial: remove both the setRequestMethod("GET") and setDoOutput(true) lines. In fact, HttpURLConnection defaults to the GET method, and for download operations, output mode doesn't need to be set. The correct configuration should allow the connection to focus on reading input streams.

Complete Technical Implementation

The following presents the corrected complete implementation, covering all key components:

1. Asynchronous Download Task

private class DownloadFile extends AsyncTask<String, Void, Void>{
    @Override
    protected Void doInBackground(String... strings) {
        String fileUrl = strings[0];
        String fileName = strings[1];
        
        // Create storage directory
        String extStorageDirectory = Environment.getExternalStorageDirectory().toString();
        File folder = new File(extStorageDirectory, "testthreepdf");
        folder.mkdir();
        
        File pdfFile = new File(folder, fileName);
        
        try {
            pdfFile.createNewFile();
        } catch (IOException e) {
            e.printStackTrace();
        }
        
        // Call downloader
        FileDownloader.downloadFile(fileUrl, pdfFile);
        return null;
    }
}

2. File Downloader Implementation

public class FileDownloader {
    private static final int MEGABYTE = 1024 * 1024;
    
    public static void downloadFile(String fileUrl, File directory) {
        try {
            URL url = new URL(fileUrl);
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
            
            // Critical correction: remove setDoOutput(true)
            urlConnection.connect();
            
            InputStream inputStream = urlConnection.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream(directory);
            
            byte[] buffer = new byte[MEGABYTE];
            int bufferLength;
            
            while ((bufferLength = inputStream.read(buffer)) > 0) {
                fileOutputStream.write(buffer, 0, bufferLength);
            }
            
            fileOutputStream.close();
            inputStream.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

3. File Opening and Intent Invocation

public void openPdfFile(String fileName) {
    File pdfFile = new File(
        Environment.getExternalStorageDirectory() + 
        "/testthreepdf/" + fileName
    );
    
    // Check if file exists
    if (!pdfFile.exists()) {
        Toast.makeText(this, "File does not exist", Toast.LENGTH_SHORT).show();
        return;
    }
    
    Uri path;
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
        // Android 7.0+ requires FileProvider
        path = FileProvider.getUriForFile(
            this, 
            getPackageName() + ".provider", 
            pdfFile
        );
    } else {
        path = Uri.fromFile(pdfFile);
    }
    
    Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
    pdfIntent.setDataAndType(path, "application/pdf");
    pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    
    // Add temporary read permission
    pdfIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
    
    try {
        startActivity(pdfIntent);
    } catch (ActivityNotFoundException e) {
        Toast.makeText(this, "No PDF reader available", Toast.LENGTH_SHORT).show();
    }
}

Permission Configuration and Security Considerations

Necessary permissions must be configured in AndroidManifest.xml:

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

For Android 6.0+, runtime storage permission requests are also required. Additionally, to address file sharing restrictions in Android 7.0+, using FileProvider for secure file sharing is recommended.

Modern API Alternatives

With the evolution of Android development technologies, consider the following modern alternatives:

  1. Use OkHttp: Provides cleaner APIs and better performance
  2. Use WorkManager: Handles background download tasks with guaranteed completion
  3. Use DownloadManager: System-level download service suitable for large files

Conclusion and Best Practices

This paper provides a detailed analysis of the complete technical process for downloading and opening PDF files in Android, focusing on solving file corruption issues caused by improper HttpURLConnection configuration. Key points include: correct network connection configuration, proper file I/O handling, and adaptation to permission and file sharing mechanisms across different Android versions. In practical development, developers should always implement error handling, add progress feedback, consider network state changes, and follow the principle of least privilege to ensure application security and stability.

Copyright Notice: All rights in this article are reserved by the operators of DevGex. Reasonable sharing and citation are welcome; any reproduction, excerpting, or re-publication without prior permission is prohibited.