Android загрузите PDF-файл по URL-адресу, затем откройте его с помощью программы для чтения PDF-файлов.

Я пытаюсь написать приложение для загрузки PDF-файлов по URL-адресу, хранения их на SD, а затем открытия с помощью Adobe PDF Reader или других приложений (которые когда-либо могут открывать PDF).

До сих пор я успешно загружал и сохранял его на SD-карте (но каждый раз, когда я пытаюсь открыть PDF-файл с помощью PDF-ридера, он вылетает и сообщает о неожиданной ошибке), например, http://maven.apache.org/maven-1.x/maven.pdf

Вот код моего загрузчика:

//........code set ui stuff
//........code set ui stuff
     new DownloadFile().execute(fileUrl, fileName); 


private class DownloadFile extends AsyncTask<String, Void, Void>{

        @Override
        protected Void doInBackground(String... strings) {
            String fileUrl = strings[0];   // -> http://maven.apache.org/maven-1.x/maven.pdf
            String fileName = strings[1];  // -> maven.pdf
            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();
            }
            FileDownloader.downloadFile(fileUrl, pdfFile);
            return null;
        }
    }



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();
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream(directory);
            int totalSize = urlConnection.getContentLength();

            byte[] buffer = new byte[MEGABYTE];
            int bufferLength = 0;
            while((bufferLength = inputStream.read(buffer))>0 ){
                fileOutputStream.write(buffer, 0, bufferLength);
            }
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

В режиме отладки я вижу, что приложение загрузило его и сохранило этот PDF-файл в /storage/sdcard/testpdf/maven.pdf. Однако я предполагаю, что файл может быть каким-то образом поврежден во время загрузки, поэтому он не открывается должным образом ...

Вот код, в котором я собираюсь открыть его с помощью другого приложения для чтения:

File pdfFile = new File(Environment.getExternalStorageDirectory() + "/testthreepdf/" + fileName);  // -> filename = maven.pdf
                    Uri path = Uri.fromFile(pdfFile);
                    Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
                    pdfIntent.setDataAndType(path, "application/pdf");
                    pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

                    try{
                        startActivity(pdfIntent);
                    }catch(ActivityNotFoundException e){
                        Toast.makeText(documentActivity, "No Application available to view PDF", Toast.LENGTH_SHORT).show();
                    }

person sefirosu    schedule 14.07.2014    source источник
comment
byte[] buffer = new byte[MEGABYTE]; что означает эта строка? Выделяет ли он 1 ГБ в буфер?   -  person NullByte08    schedule 12.06.2020


Ответы (3)


Привет, проблема в классе FileDownloader

 urlConnection.setRequestMethod("GET");
    urlConnection.setDoOutput(true);

Вам нужно удалить две вышеупомянутые строки, и все будет работать нормально. Отметьте вопрос как отвеченный, если он работает должным образом.

Обновлено последнее решение для той же проблемы Запись / чтение Android PDF с помощью Android 9 (уровень API 28)

Прикрепляем рабочий код со скриншотами.

введите описание изображения здесь

введите описание изображения здесь

MainActivity.java

package com.example.downloadread;

import java.io.File;
import java.io.IOException;

import android.app.Activity;
import android.content.ActivityNotFoundException;
import android.content.Intent;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.view.Menu;
import android.view.View;
import android.widget.Toast;

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    public void download(View v)
    {
        new DownloadFile().execute("http://maven.apache.org/maven-1.x/maven.pdf", "maven.pdf"); 
    }

    public void view(View v)
    {
        File pdfFile = new File(Environment.getExternalStorageDirectory() + "/testthreepdf/" + "maven.pdf");  // -> filename = maven.pdf
        Uri path = Uri.fromFile(pdfFile);
        Intent pdfIntent = new Intent(Intent.ACTION_VIEW);
        pdfIntent.setDataAndType(path, "application/pdf");
        pdfIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

        try{
            startActivity(pdfIntent);
        }catch(ActivityNotFoundException e){
            Toast.makeText(MainActivity.this, "No Application available to view PDF", Toast.LENGTH_SHORT).show();
        }
    }

    private class DownloadFile extends AsyncTask<String, Void, Void>{

        @Override
        protected Void doInBackground(String... strings) {
            String fileUrl = strings[0];   // -> http://maven.apache.org/maven-1.x/maven.pdf
            String fileName = strings[1];  // -> maven.pdf
            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();
            }
            FileDownloader.downloadFile(fileUrl, pdfFile);
            return null;
        }
    }


}

FileDownloader.java

package com.example.downloadread;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;

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();
            //urlConnection.setRequestMethod("GET");
            //urlConnection.setDoOutput(true);
            urlConnection.connect();

            InputStream inputStream = urlConnection.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream(directory);
            int totalSize = urlConnection.getContentLength();

            byte[] buffer = new byte[MEGABYTE];
            int bufferLength = 0;
            while((bufferLength = inputStream.read(buffer))>0 ){
                fileOutputStream.write(buffer, 0, bufferLength);
            }
            fileOutputStream.close();
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.downloadread"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="14"
        android:targetSdkVersion="18" />
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.downloadread.MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
    </application>

</manifest>

activity_main.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context=".MainActivity" >

    <Button
        android:id="@+id/button1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:layout_marginTop="15dp"
        android:text="download"
        android:onClick="download" />

    <Button
        android:id="@+id/button2"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentRight="true"
        android:layout_below="@+id/button1"
        android:layout_marginTop="38dp"
        android:text="view"
        android:onClick="view" />

</RelativeLayout>
person Zack Dawood    schedule 15.07.2014
comment
Привет, Зак, удалив эти две строчки, он работает, я могу загрузить и прочитать на своем мобильном устройстве. но почему-то каждый раз, когда я пытался прочитать DLed pdf на эмуляторе, он вылетал, есть идеи почему? я использую этот apk для Adobe Reader - ›appsapk.com/adobe-reader вы читали эмулятор или ваше устройство? Спасибо - person sefirosu; 15.07.2014
comment
а также, я хочу знать, почему после удаления этих двух строк приложение работает? какова история за кулисами? Спасибо - person sefirosu; 15.07.2014
comment
Насколько я понимаю, при загрузке PDF из настольного приложения вам необходимо указать GET / POST, однако в Android решает, как загрузить, на основе кода ответа. Следовательно, эта строка не требуется. Также doOutput не требуется, поскольку мы выполняем потоковую передачу и запись в файл pdf. Дайте мне знать, если вам понадобятся подробности. Спасибо, что пометили его как ответ. Хорошего дня. - person Zack Dawood; 15.07.2014
comment
Вы пробовали загружать Adobe PDF Reader в эмуляторе? каждый раз, когда я загружаю pdf в эмулятор, происходит сбой и неожиданная ошибка - person sefirosu; 15.07.2014
comment
Привет, используйте программу чтения по умолчанию в эмуляторе, для программы Adobe Reader используйте только приложение в магазине приложений Android. Эти apk-файлы appsapk.com/adobe-reader могут содержать ошибки. Я тестировал на реальных устройствах с Adobe Reader, он работает. прикрепленный мною снимок экрана с реального устройства. Удалите приложение Adobe Reader и повторите попытку. Неожиданную ошибку, которую вы видите в Adobe Reader, невозможно отладить, потому что она возникает в apk, где у вас нет исходного кода. - person Zack Dawood; 15.07.2014
comment
Человек, ты спас меня! Спасибо. - person Bassem Qoulta; 13.01.2017
comment
@ MohammedZackria-Zack Ваш код не работает Вы не указали свой код в списке кнопок как работает ваш код - person Ashish Shahi; 24.06.2017
comment
@ MohammedZackria-Zack Я трачу свое время на ваш код Ничего не найдено - person Ashish Shahi; 24.06.2017
comment
@AshishShahi слушатель установлен в activity_main.xml android: onClick = download, который вызывает загрузку метода в классе MainActivity.java. Выполните отладку и просмотрите код для устранения неполадок. Это 100% рабочий код, сегодня я снова протестировал. - person Zack Dawood; 25.06.2017
comment
@AshishShahi, вы использовали весь код или использовали только некоторые? Все файлы должны быть одинаковыми. Убедитесь, что вы используете следующие файлы MainActivity.java FileDownloader.java AndroidManifest.xml activity_main.xml - person Zack Dawood; 25.06.2017
comment
@ MohammedZackria-Zack Ваш пример хорош, но возникают проблемы, когда я открываю другой PDF-файл. Предыдущий файл удаляется автоматически. Пожалуйста, скажите мне, как я могу предотвратить удаление файла, пожалуйста, помогите мне - person Ashish Shahi; 26.06.2017
comment
@AshishShahi, согласно моему коду, он открывает только один файл pdf, который жестко закодирован. Вам нужно открыть новую проблему в Stackoverflow с помощью кода, чтобы мы могли предложить или устранить неполадки. Код в примере открывает только один файл pdf, который является maven.apache.org/ maven-1.x / maven.pdf. Файл хранится в физическом месте, возможно, вы перезаписываете его с тем же именем. - person Zack Dawood; 27.06.2017
comment
@ MohammedZackria-Zack Правильно скажите, но мое требование - файл загружен, если такой же файл существует, а затем заменить другой мудрый создать новый файл - person Ashish Shahi; 27.06.2017
comment
@AshishShahi Пожалуйста, откройте еще одну проблему с вашим кодом и деталями. Согласно моему коду будет загружен только один файл. - person Zack Dawood; 28.06.2017
comment
Хорошо, спасибо за внимание - person Ashish Shahi; 28.06.2017
comment
Я только что попробовал этот код и не могу заставить его работать. Создал новый проект и скопировал все. Я получаю сообщение об ошибке, что PDF-файл не может быть просмотрен. У вас есть идеи, почему это происходит? Я пытался открыть его с помощью трех разных программ просмотра PDF-файлов, но ни одна из них не может открыть загруженный файл. Спасибо за любую помощь! - person nullforlife; 06.07.2017
comment
@nullforlife проверьте файл журнала logcat и посмотрите сообщение об ошибке. Или отладить код и пройтись. Сообщите нам сообщение об ошибке. Какую версию Android вы используете? Вы используете реальное устройство или эмулятор? - person Zack Dawood; 07.07.2017
comment
@ MohammedZackria-Zack, я исправил. У меня было исключение «Ошибка открытия: EACCES (Permission denied)», похоже, вам нужно запросить разрешение на уровне API ›23. Для получения дополнительной информации ознакомьтесь с этим вопросом: stackoverflow.com/questions/8854359/ Я только что добавил его код и запустил это в onCreate (и принятых разрешениях), и ваш код работал нормально. - person nullforlife; 07.07.2017
comment
@nullforlife Спасибо, что поделились исправлением - person Zack Dawood; 07.07.2017
comment
@ZackDawood Я запускаю ваш код, но он не работает, никаких ошибок нет. Если вы хотите увидеть мой код, я задал вопрос в SO. Ссылка здесь. stackoverflow.com/questions/55816746/ - person Abedin.Zhuniqi; 24.04.2019
comment
@Spritzig Я обновил решение вашей проблемы stackoverflow.com/questions/55816746/ - person Zack Dawood; 26.05.2019

Это лучший способ скачать и просмотреть PDF-файл. Вы можете просто вызвать его из любого места как угодно.

PDFTools.showPDFUrl(context, url);

вот ниже поместите код. Он будет работать нормально

public class PDFTools {
private static final String TAG = "PDFTools";
private static final String GOOGLE_DRIVE_PDF_READER_PREFIX = "http://drive.google.com/viewer?url=";
private static final String PDF_MIME_TYPE = "application/pdf";
private static final String HTML_MIME_TYPE = "text/html";


public static void showPDFUrl(final Context context, final String pdfUrl ) {
    if ( isPDFSupported( context ) ) {
        downloadAndOpenPDF(context, pdfUrl);
    } else {
        askToOpenPDFThroughGoogleDrive( context, pdfUrl );
    }
}


@TargetApi(Build.VERSION_CODES.GINGERBREAD)
public static void downloadAndOpenPDF(final Context context, final String pdfUrl) {
    // Get filename
    //final String filename = pdfUrl.substring( pdfUrl.lastIndexOf( "/" ) + 1 );
    String filename = "";
    try {
        filename = new GetFileInfo().execute(pdfUrl).get();
    } catch (InterruptedException e) {
        e.printStackTrace();
    } catch (ExecutionException e) {
        e.printStackTrace();
    }
    // The place where the downloaded PDF file will be put
    final File tempFile = new File( context.getExternalFilesDir( Environment.DIRECTORY_DOWNLOADS ), filename );
    Log.e(TAG,"File Path:"+tempFile);
    if ( tempFile.exists() ) {
        // If we have downloaded the file before, just go ahead and show it.
        openPDF( context, Uri.fromFile( tempFile ) );
        return;
    }

    // Show progress dialog while downloading
    final ProgressDialog progress = ProgressDialog.show( context, context.getString( R.string.pdf_show_local_progress_title ), context.getString( R.string.pdf_show_local_progress_content ), true );

    // Create the download request
    DownloadManager.Request r = new DownloadManager.Request( Uri.parse( pdfUrl ) );
    r.setDestinationInExternalFilesDir( context, Environment.DIRECTORY_DOWNLOADS, filename );
    final DownloadManager dm = (DownloadManager) context.getSystemService( Context.DOWNLOAD_SERVICE );
    BroadcastReceiver onComplete = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if ( !progress.isShowing() ) {
                return;
            }
            context.unregisterReceiver( this );

            progress.dismiss();
            long downloadId = intent.getLongExtra( DownloadManager.EXTRA_DOWNLOAD_ID, -1 );
            Cursor c = dm.query( new DownloadManager.Query().setFilterById( downloadId ) );

            if ( c.moveToFirst() ) {
                int status = c.getInt( c.getColumnIndex( DownloadManager.COLUMN_STATUS ) );
                if ( status == DownloadManager.STATUS_SUCCESSFUL ) {
                    openPDF( context, Uri.fromFile( tempFile ) );
                }
            }
            c.close();
        }
    };
    context.registerReceiver( onComplete, new IntentFilter( DownloadManager.ACTION_DOWNLOAD_COMPLETE ) );

    // Enqueue the request
    dm.enqueue( r );
}


public static void askToOpenPDFThroughGoogleDrive( final Context context, final String pdfUrl ) {
    new AlertDialog.Builder( context )
            .setTitle( R.string.pdf_show_online_dialog_title )
            .setMessage( R.string.pdf_show_online_dialog_question )
            .setNegativeButton( R.string.pdf_show_online_dialog_button_no, null )
            .setPositiveButton( R.string.pdf_show_online_dialog_button_yes, new DialogInterface.OnClickListener() {
                @Override
                public void onClick(DialogInterface dialog, int which) {
                    openPDFThroughGoogleDrive(context, pdfUrl);
                }
            })
            .show();
}

public static void openPDFThroughGoogleDrive(final Context context, final String pdfUrl) {
    Intent i = new Intent( Intent.ACTION_VIEW );
    i.setDataAndType(Uri.parse(GOOGLE_DRIVE_PDF_READER_PREFIX + pdfUrl ), HTML_MIME_TYPE );
    context.startActivity( i );
}

public static final void openPDF(Context context, Uri localUri ) {
    Intent i = new Intent( Intent.ACTION_VIEW );
    i.setDataAndType( localUri, PDF_MIME_TYPE );
    context.startActivity( i );
}

public static boolean isPDFSupported( Context context ) {
    Intent i = new Intent( Intent.ACTION_VIEW );
    final File tempFile = new File( context.getExternalFilesDir( Environment.DIRECTORY_DOWNLOADS ), "test.pdf" );
    i.setDataAndType( Uri.fromFile( tempFile ), PDF_MIME_TYPE );
    return context.getPackageManager().queryIntentActivities( i, PackageManager.MATCH_DEFAULT_ONLY ).size() > 0;
}

// get File name from url
static class GetFileInfo extends AsyncTask<String, Integer, String>
{
    protected String doInBackground(String... urls)
    {
        URL url;
        String filename = null;
        try {
            url = new URL(urls[0]);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.connect();
            conn.setInstanceFollowRedirects(false);
            if(conn.getHeaderField("Content-Disposition")!=null){
                String depo = conn.getHeaderField("Content-Disposition");

                String depoSplit[] = depo.split("filename=");
                filename = depoSplit[1].replace("filename=", "").replace("\"", "").trim();
            }else{
                filename = "download.pdf";
            }
        } catch (MalformedURLException e1) {
            e1.printStackTrace();
        } catch (IOException e) {
        }
        return filename;
    }

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
    }
    @Override
    protected void onPostExecute(String result) {
        super.onPostExecute(result);
        // use result as file name
    }
}

}

попробуй. это будет работать, наслаждайтесь

person Jijo    schedule 22.10.2016
comment
это немного долгий процесс - person Anand Savjani; 09.05.2018
comment
Это сработало для меня после замены метода openPDF, такого как openPDF (context, FileProvider.getUriForFile (context, context.getApplicationContext (). GetPackageName () + .my.package.name.provider, tempFile)); Здесь описано: stackoverflow.com/a/38858040/1492681 - person ilker; 04.02.2019
comment
Будьте осторожны, думайте, что веб-служба Google http://drive.google.com/viewer не была официально запущена для публичного использования в качестве API и что они могут отключить ее в любое время без какого-либо публичного уведомления. - person Abel Callejo; 07.02.2019

Загрузите исходный код отсюда (Открыть PDF-файл с URL-адреса в Android программно)

MainActivity.java

package com.deepshikha.openpdf;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.ProgressBar;

public class MainActivity extends AppCompatActivity {
    WebView webview;
    ProgressBar progressbar;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        webview = (WebView)findViewById(R.id.webview);
        progressbar = (ProgressBar) findViewById(R.id.progressbar);
        webview.getSettings().setJavaScriptEnabled(true);
        String filename ="http://www3.nd.edu/~cpoellab/teaching/cse40816/android_tutorial.pdf";
        webview.loadUrl("http://docs.google.com/gview?embedded=true&url=" + filename);

        webview.setWebViewClient(new WebViewClient() {

            public void onPageFinished(WebView view, String url) {
                // do your stuff here
                progressbar.setVisibility(View.GONE);
            }
        });

    }
}

Спасибо!

person Deepshikha Puri    schedule 19.07.2017