如何在Android下载pdf文件?

时间:2022-08-02 21:20:54

I want to download a pdf file from an url. For viewing the pdf file I used the code below.

我想从网址下载pdf文件。为了查看pdf文件,我使用了以下代码。

File file = new File("/sdcard/example.pdf");

if (file.exists()) {
    Uri path = Uri.fromFile(file);
    Intent intent = new Intent(Intent.ACTION_VIEW);
    intent.setDataAndType(path, "application/pdf");
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

    try {
        startActivity(intent);
    } 
    catch (ActivityNotFoundException e) {
        Toast.makeText(OpenPdf.this, "No Application Available to View PDF",
            Toast.LENGTH_SHORT).show();
    }
}

It is working but how do I get the pdf file from an url (e.g http://.../example.pdf). I want to download the pdf file from this url. Please help me. Thanks in advance.

它工作正常,但我如何从网址获取pdf文件(例如http://.../example.pdf)。我想从这个网址下载pdf文件。请帮帮我。提前致谢。

5 个解决方案

#1


7  

Downloading a PDF works the same as downloading any other binary file.

下载PDF与下载任何其他二进制文件的工作方式相同。

  1. Open a HttpUrlConnection
  2. 打开HttpUrlConnection
  3. Use the connection's getInputStream() method to read the file.
  4. 使用连接的getInputStream()方法读取文件。
  5. Create a FileOutputStream and write the inputstream.
  6. 创建FileOutputStream并编写输入流。

Check this post for example source code.

查看此帖子以获取示例源代码。

#2


20  

Download a pdf:

下载pdf:

 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("www.education.gov.yk.ca/pdf/pdf-test.pdf")));

Ah as I've just found out this is device dependant.

啊,因为我刚刚发现这取决于设备。

scenarios

场景

  1. It will download the pdf to your browser/downloaded/ folder

    它会将pdf下载到您的浏览器/下载/文件夹中

  2. You have a google docs account - It will ask you to sign in then view the pdf in the browser

    您有一个Google文档帐户 - 它会要求您登录,然后在浏览器中查看pdf

  3. You have a pdf reader installed - App dependant may catch it may not

    你安装了一个PDF阅读器 - 依赖App依赖它可能没有

In all scenario's though the user has access to the PDF with one line of code :-)

在所有情况下,虽然用户可以使用一行代码访问PDF :-)

#3


8  

There are many ways to download files. Following I will post most common ways; it is up to you to decide which method is better for your app.

有很多方法可以下载文件。以下我将发布最常见的方式;您可以自行决定哪种方法更适合您的应用。

1. Use AsyncTask and show the download progress in a dialog

This method will allow you to execute some background processes and update the UI at the same time (in this case, we'll update a progress bar).

此方法将允许您执行一些后台进程并同时更新UI(在这种情况下,我们将更新进度条)。

This is an example code:

这是一个示例代码:

// declare the dialog as a member field of your activity
ProgressDialog mProgressDialog;

// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);

// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");

mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        downloadTask.cancel(true);
    }
});

The AsyncTask will look like this:

AsyncTask看起来像这样:

// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;

    public DownloadTask(Context context) {
        this.context = context;
    }

    @Override
    protected String doInBackground(String... sUrl) {
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + connection.getResponseCode()
                        + " " + connection.getResponseMessage();
            }

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                total += count;
                // publishing the progress....
                if (fileLength > 0) // only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }
        return null;
    }

The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:

上面的方法(doInBackground)总是在后台线程上运行。你不应该在那里做任何UI任务。另一方面,onProgressUpdate和onPreExecute在UI线程上运行,因此您可以更改进度条:

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // take CPU lock to prevent CPU from going off if the user 
        // presses the power button during download
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
             getClass().getName());
        mWakeLock.acquire();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        mWakeLock.release();
        mProgressDialog.dismiss();
        if (result != null)
            Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
    }

For this to run, you need the WAKE_LOCK permission.

要运行此选项,您需要WAKE_LOCK权限。

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

2. Download from Service

The big question here is: how do I update my activity from a service?. In the next example we are going to use two classes you may not be aware of: ResultReceiver and IntentService. ResultReceiver is the one that will allow us to update our thread from a service; IntentService is a subclass of Service which spawns a thread to do background work from there (you should know that a Service runs actually in the same thread of your app; when you extends Service, you must manually spawn new threads to run CPU blocking operations).

这里最大的问题是:如何从服务更新我的活动?在下一个示例中,我们将使用您可能不知道的两个类:ResultReceiver和IntentService。 ResultReceiver是允许我们从服务更新线程的那个; IntentService是Service的一个子类,它产生一个线程来从那里进行后台工作(你应该知道一个服务实际上在你的应用程序的同一个线程中运行;当你扩展Service时,你必须手动生成新的线程来运行CPU阻塞操作) 。

Download service can look like this:

下载服务可能如下所示:

public class DownloadService extends IntentService {
    public static final int UPDATE_PROGRESS = 8344;
    public DownloadService() {
        super("DownloadService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String urlToDownload = intent.getStringExtra("url");
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
        try {
            URL url = new URL(urlToDownload);
            URLConnection connection = url.openConnection();
            connection.connect();
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());
            OutputStream output = new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int) (total * 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Bundle resultData = new Bundle();
        resultData.putInt("progress" ,100);
        receiver.send(UPDATE_PROGRESS, resultData);
    }
}

Add the service to your manifest:

将服务添加到清单:

<service android:name=".DownloadService"/>

And the activity will look like this:

活动将如下所示:

// initialize the progress dialog like in the first example

// this is how you fire the downloader
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);

Here is were ResultReceiver comes to play:

以下是ResultReceiver来玩:

private class DownloadReceiver extends ResultReceiver{
    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        if (resultCode == DownloadService.UPDATE_PROGRESS) {
            int progress = resultData.getInt("progress");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.dismiss();
            }
        }
    }
}

2.1 Use Groundy library

Groundy is a library that basically helps you run pieces of code in a background service, and it is based on the ResultReceiver concept shown above. This library is deprecated at the moment. This is how the whole code would look like:

Groundy是一个基本上可以帮助您在后台服务中运行代码片段的库,它基于上面显示的ResultReceiver概念。此库已弃用。这就是整个代码的样子:

The activity where you are showing the dialog...

您正在显示对话框的活动...

public class MainActivity extends Activity {

    private ProgressDialog mProgressDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
                Bundle extras = new Bundler().add(DownloadTask.PARAM_URL, url).build();
                Groundy.create(DownloadExample.this, DownloadTask.class)
                        .receiver(mReceiver)
                        .params(extras)
                        .queue();

                mProgressDialog = new ProgressDialog(MainActivity.this);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(false);
                mProgressDialog.show();
            }
        });
    }

    private ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            switch (resultCode) {
                case Groundy.STATUS_PROGRESS:
                    mProgressDialog.setProgress(resultData.getInt(Groundy.KEY_PROGRESS));
                    break;
                case Groundy.STATUS_FINISHED:
                    Toast.makeText(DownloadExample.this, R.string.file_downloaded, Toast.LENGTH_LONG);
                    mProgressDialog.dismiss();
                    break;
                case Groundy.STATUS_ERROR:
                    Toast.makeText(DownloadExample.this, resultData.getString(Groundy.KEY_ERROR), Toast.LENGTH_LONG).show();
                    mProgressDialog.dismiss();
                    break;
            }
        }
    };
}

A GroundyTask implementation used by Groundy to download the file and show the progress:

Groundy使用GroundyTask实现下载文件并显示进度:

public class DownloadTask extends GroundyTask {    
    public static final String PARAM_URL = "com.groundy.sample.param.url";

    @Override
    protected boolean doInBackground() {
        try {
            String url = getParameters().getString(PARAM_URL);
            File dest = new File(getContext().getFilesDir(), new File(url).getName());
            DownloadUtils.downloadFile(getContext(), url, dest, DownloadUtils.getDownloadListenerForTask(this));
            return true;
        } catch (Exception pokemon) {
            return false;
        }
    }
}

And just add this to the manifest:

然后将其添加到清单中:

<service android:name="com.codeslap.groundy.GroundyService"/>

It couldn't be easier I think. Just grab the latest jar from Github and you are ready to go. Keep in mind that Groundy's main purpose is to make calls to external REST apis in a background service and post results to the UI with easily. If you are doing something like that in your app, it could be really useful.

我想这可不容易。只需从Github拿起最新的罐子,你就可以开始了。请记住,Groundy的主要目的是在后台服务中调用外部REST apis,并轻松地将结果发布到UI。如果你在你的应用程序中做了类似的事情,它可能真的很有用。

2.2 Use https://github.com/koush/ion

3. Use DownloadManager class (GingerBread and newer only)

GingerBread brought a new feature, DownloadManager, which allows you to download files easily and delegate the hard work of handling threads, streams, etc. to the system.

GingerBread带来了一个新功能DownloadManager,它允许您轻松下载文件并将处理线程,流等的艰苦工作委派给系统。

First, let's see a utility method:

首先,让我们看一个实用方法:

/**
 * @param context used to check the device version and DownloadManager information
 * @return true if the download manager is available
 */
public static boolean isDownloadManagerAvailable(Context context) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        return true;
    }
    return false;
}

Method's name explains it all. Once you are sure DownloadManager is available, you can do something like this:

方法的名称解释了这一切。一旦确定DownloadManager可用,您可以执行以下操作:

String url = "url you want to download";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");

// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

Download progress will be showing in the notification bar.

下载进度将显示在通知栏中。

Final thoughts

First and second methods are just the tip of the iceberg. There are lots of things you have to keep in mind if you want your app to be robust. Here is a brief list:

第一种和第二种方法只是冰山一角。如果您希望自己的应用程序功能强大,那么您必须记住很多事情。这是一个简短的清单:

  • You must check whether user has an internet connection available
  • 您必须检查用户是否有可用的Internet连接
  • Make sure you have the right permissions (INTERNET and WRITE_EXTERNAL_STORAGE); also ACCESS_NETWORK_STATE if you want to check internet availability.
  • 确保您拥有正确的权限(INTERNET和WRITE_EXTERNAL_STORAGE);如果您想查看互联网可用性,还可以访问ACCESS_NETWORK_STATE。
  • Make sure the directory were you are going to download files exist and has write permissions.
  • 确保目录是否要下载存在的文件并具有写入权限。
  • If download is too big you may want to implement a way to resume the download if previous attempts failed.
  • 如果下载太大,您可能希望实现一种方法,以便在先前的尝试失败时恢复下载。
  • Users will be grateful if you allow them to interrupt the download.
  • 如果您允许用户中断下载,用户将不胜感激。

Unless you need detailed control of the download process, then consider using DownloadManager (3) because it already handles most of the items listed above.

除非您需要详细控制下载过程,否则请考虑使用DownloadManager(3),因为它已经处理了上面列出的大多数项目。

But also consider that your needs may change. For example, DownloadManager does no response caching. It will blindly download the same big file multiple times. There's no easy way to fix it after the fact. Where if you start with a basic HttpURLConnection (1, 2), then all you need is to add an HttpResponseCache. So the initial effort of learning the basic, standard tools can be a good investment.

但也要考虑您的需求可能会发生变化。例如,DownloadManager没有响应缓存。它会盲目地多次下载同一个大文件。事后没有简单的方法来解决它。如果你从一个基本的HttpURLConnection(1,2)开始,那么你只需要添加一个HttpResponseCache。因此,学习基本标准工具的初步努力可能是一项很好的投资。

#4


0  

public static class Downloader {

 public static void DownloadFile(String fileURL, File directory) {
    try {
         FileOutputStream file = new FileOutputStream(directory);
         URL url = new URL(fileURL);
        HttpURLConnection connection = (HttpURLConnection) url .openConnection();
         connection .setRequestMethod("GET");
         connection .setDoOutput(true);
         connection .connect();
         InputStream input = connection .getInputStream();
         byte[] buffer = new byte[1024];
         int len = 0;
          while ((len = input .read(buffer)) > 0) {
           file .write(buffer, 0, len );
         }
        file .close();
  } catch (Exception e) {
          e.printStackTrace();
   }
}

For more info click here http://androiddhina.blogspot.in/2015/09/how-to-download-pdf-from-url-in-android.html

欲了解更多信息,请点击这里http://androiddhina.blogspot.in/2015/09/how-to-download-pdf-from-url-in-android.html

#5


0  

There is no need to put lengthy code to open and download pdf in android you can just use below code to open and download pdf

没有必要在android中打开和下载pdf冗长的代码,你可以使用下面的代码来打开和下载pdf

String URL ="http://worldhappiness.report/wp-content/uploads/sites/2/2016/03/HR-V1_web.pdf"

 startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse(URL)));

#1


7  

Downloading a PDF works the same as downloading any other binary file.

下载PDF与下载任何其他二进制文件的工作方式相同。

  1. Open a HttpUrlConnection
  2. 打开HttpUrlConnection
  3. Use the connection's getInputStream() method to read the file.
  4. 使用连接的getInputStream()方法读取文件。
  5. Create a FileOutputStream and write the inputstream.
  6. 创建FileOutputStream并编写输入流。

Check this post for example source code.

查看此帖子以获取示例源代码。

#2


20  

Download a pdf:

下载pdf:

 startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("www.education.gov.yk.ca/pdf/pdf-test.pdf")));

Ah as I've just found out this is device dependant.

啊,因为我刚刚发现这取决于设备。

scenarios

场景

  1. It will download the pdf to your browser/downloaded/ folder

    它会将pdf下载到您的浏览器/下载/文件夹中

  2. You have a google docs account - It will ask you to sign in then view the pdf in the browser

    您有一个Google文档帐户 - 它会要求您登录,然后在浏览器中查看pdf

  3. You have a pdf reader installed - App dependant may catch it may not

    你安装了一个PDF阅读器 - 依赖App依赖它可能没有

In all scenario's though the user has access to the PDF with one line of code :-)

在所有情况下,虽然用户可以使用一行代码访问PDF :-)

#3


8  

There are many ways to download files. Following I will post most common ways; it is up to you to decide which method is better for your app.

有很多方法可以下载文件。以下我将发布最常见的方式;您可以自行决定哪种方法更适合您的应用。

1. Use AsyncTask and show the download progress in a dialog

This method will allow you to execute some background processes and update the UI at the same time (in this case, we'll update a progress bar).

此方法将允许您执行一些后台进程并同时更新UI(在这种情况下,我们将更新进度条)。

This is an example code:

这是一个示例代码:

// declare the dialog as a member field of your activity
ProgressDialog mProgressDialog;

// instantiate it within the onCreate method
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(true);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
mProgressDialog.setCancelable(true);

// execute this when the downloader must be fired
final DownloadTask downloadTask = new DownloadTask(YourActivity.this);
downloadTask.execute("the url to the file you want to download");

mProgressDialog.setOnCancelListener(new DialogInterface.OnCancelListener() {
    @Override
    public void onCancel(DialogInterface dialog) {
        downloadTask.cancel(true);
    }
});

The AsyncTask will look like this:

AsyncTask看起来像这样:

// usually, subclasses of AsyncTask are declared inside the activity class.
// that way, you can easily modify the UI thread from here
private class DownloadTask extends AsyncTask<String, Integer, String> {

    private Context context;
    private PowerManager.WakeLock mWakeLock;

    public DownloadTask(Context context) {
        this.context = context;
    }

    @Override
    protected String doInBackground(String... sUrl) {
        InputStream input = null;
        OutputStream output = null;
        HttpURLConnection connection = null;
        try {
            URL url = new URL(sUrl[0]);
            connection = (HttpURLConnection) url.openConnection();
            connection.connect();

            // expect HTTP 200 OK, so we don't mistakenly save error report
            // instead of the file
            if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "Server returned HTTP " + connection.getResponseCode()
                        + " " + connection.getResponseMessage();
            }

            // this will be useful to display download percentage
            // might be -1: server did not report the length
            int fileLength = connection.getContentLength();

            // download the file
            input = connection.getInputStream();
            output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[4096];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                // allow canceling with back button
                if (isCancelled()) {
                    input.close();
                    return null;
                }
                total += count;
                // publishing the progress....
                if (fileLength > 0) // only if total length is known
                    publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }
        } catch (Exception e) {
            return e.toString();
        } finally {
            try {
                if (output != null)
                    output.close();
                if (input != null)
                    input.close();
            } catch (IOException ignored) {
            }

            if (connection != null)
                connection.disconnect();
        }
        return null;
    }

The method above (doInBackground) runs always on a background thread. You shouldn't do any UI tasks there. On the other hand, the onProgressUpdate and onPreExecute run on the UI thread, so there you can change the progress bar:

上面的方法(doInBackground)总是在后台线程上运行。你不应该在那里做任何UI任务。另一方面,onProgressUpdate和onPreExecute在UI线程上运行,因此您可以更改进度条:

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        // take CPU lock to prevent CPU from going off if the user 
        // presses the power button during download
        PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
        mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK,
             getClass().getName());
        mWakeLock.acquire();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        // if we get here, length is known, now set indeterminate to false
        mProgressDialog.setIndeterminate(false);
        mProgressDialog.setMax(100);
        mProgressDialog.setProgress(progress[0]);
    }

    @Override
    protected void onPostExecute(String result) {
        mWakeLock.release();
        mProgressDialog.dismiss();
        if (result != null)
            Toast.makeText(context,"Download error: "+result, Toast.LENGTH_LONG).show();
        else
            Toast.makeText(context,"File downloaded", Toast.LENGTH_SHORT).show();
    }

For this to run, you need the WAKE_LOCK permission.

要运行此选项,您需要WAKE_LOCK权限。

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

2. Download from Service

The big question here is: how do I update my activity from a service?. In the next example we are going to use two classes you may not be aware of: ResultReceiver and IntentService. ResultReceiver is the one that will allow us to update our thread from a service; IntentService is a subclass of Service which spawns a thread to do background work from there (you should know that a Service runs actually in the same thread of your app; when you extends Service, you must manually spawn new threads to run CPU blocking operations).

这里最大的问题是:如何从服务更新我的活动?在下一个示例中,我们将使用您可能不知道的两个类:ResultReceiver和IntentService。 ResultReceiver是允许我们从服务更新线程的那个; IntentService是Service的一个子类,它产生一个线程来从那里进行后台工作(你应该知道一个服务实际上在你的应用程序的同一个线程中运行;当你扩展Service时,你必须手动生成新的线程来运行CPU阻塞操作) 。

Download service can look like this:

下载服务可能如下所示:

public class DownloadService extends IntentService {
    public static final int UPDATE_PROGRESS = 8344;
    public DownloadService() {
        super("DownloadService");
    }
    @Override
    protected void onHandleIntent(Intent intent) {
        String urlToDownload = intent.getStringExtra("url");
        ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver");
        try {
            URL url = new URL(urlToDownload);
            URLConnection connection = url.openConnection();
            connection.connect();
            // this will be useful so that you can show a typical 0-100% progress bar
            int fileLength = connection.getContentLength();

            // download the file
            InputStream input = new BufferedInputStream(connection.getInputStream());
            OutputStream output = new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                // publishing the progress....
                Bundle resultData = new Bundle();
                resultData.putInt("progress" ,(int) (total * 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

        Bundle resultData = new Bundle();
        resultData.putInt("progress" ,100);
        receiver.send(UPDATE_PROGRESS, resultData);
    }
}

Add the service to your manifest:

将服务添加到清单:

<service android:name=".DownloadService"/>

And the activity will look like this:

活动将如下所示:

// initialize the progress dialog like in the first example

// this is how you fire the downloader
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);

Here is were ResultReceiver comes to play:

以下是ResultReceiver来玩:

private class DownloadReceiver extends ResultReceiver{
    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        if (resultCode == DownloadService.UPDATE_PROGRESS) {
            int progress = resultData.getInt("progress");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.dismiss();
            }
        }
    }
}

2.1 Use Groundy library

Groundy is a library that basically helps you run pieces of code in a background service, and it is based on the ResultReceiver concept shown above. This library is deprecated at the moment. This is how the whole code would look like:

Groundy是一个基本上可以帮助您在后台服务中运行代码片段的库,它基于上面显示的ResultReceiver概念。此库已弃用。这就是整个代码的样子:

The activity where you are showing the dialog...

您正在显示对话框的活动...

public class MainActivity extends Activity {

    private ProgressDialog mProgressDialog;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        findViewById(R.id.btn_download).setOnClickListener(new View.OnClickListener() {
            public void onClick(View view) {
                String url = ((EditText) findViewById(R.id.edit_url)).getText().toString().trim();
                Bundle extras = new Bundler().add(DownloadTask.PARAM_URL, url).build();
                Groundy.create(DownloadExample.this, DownloadTask.class)
                        .receiver(mReceiver)
                        .params(extras)
                        .queue();

                mProgressDialog = new ProgressDialog(MainActivity.this);
                mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
                mProgressDialog.setCancelable(false);
                mProgressDialog.show();
            }
        });
    }

    private ResultReceiver mReceiver = new ResultReceiver(new Handler()) {
        @Override
        protected void onReceiveResult(int resultCode, Bundle resultData) {
            super.onReceiveResult(resultCode, resultData);
            switch (resultCode) {
                case Groundy.STATUS_PROGRESS:
                    mProgressDialog.setProgress(resultData.getInt(Groundy.KEY_PROGRESS));
                    break;
                case Groundy.STATUS_FINISHED:
                    Toast.makeText(DownloadExample.this, R.string.file_downloaded, Toast.LENGTH_LONG);
                    mProgressDialog.dismiss();
                    break;
                case Groundy.STATUS_ERROR:
                    Toast.makeText(DownloadExample.this, resultData.getString(Groundy.KEY_ERROR), Toast.LENGTH_LONG).show();
                    mProgressDialog.dismiss();
                    break;
            }
        }
    };
}

A GroundyTask implementation used by Groundy to download the file and show the progress:

Groundy使用GroundyTask实现下载文件并显示进度:

public class DownloadTask extends GroundyTask {    
    public static final String PARAM_URL = "com.groundy.sample.param.url";

    @Override
    protected boolean doInBackground() {
        try {
            String url = getParameters().getString(PARAM_URL);
            File dest = new File(getContext().getFilesDir(), new File(url).getName());
            DownloadUtils.downloadFile(getContext(), url, dest, DownloadUtils.getDownloadListenerForTask(this));
            return true;
        } catch (Exception pokemon) {
            return false;
        }
    }
}

And just add this to the manifest:

然后将其添加到清单中:

<service android:name="com.codeslap.groundy.GroundyService"/>

It couldn't be easier I think. Just grab the latest jar from Github and you are ready to go. Keep in mind that Groundy's main purpose is to make calls to external REST apis in a background service and post results to the UI with easily. If you are doing something like that in your app, it could be really useful.

我想这可不容易。只需从Github拿起最新的罐子,你就可以开始了。请记住,Groundy的主要目的是在后台服务中调用外部REST apis,并轻松地将结果发布到UI。如果你在你的应用程序中做了类似的事情,它可能真的很有用。

2.2 Use https://github.com/koush/ion

3. Use DownloadManager class (GingerBread and newer only)

GingerBread brought a new feature, DownloadManager, which allows you to download files easily and delegate the hard work of handling threads, streams, etc. to the system.

GingerBread带来了一个新功能DownloadManager,它允许您轻松下载文件并将处理线程,流等的艰苦工作委派给系统。

First, let's see a utility method:

首先,让我们看一个实用方法:

/**
 * @param context used to check the device version and DownloadManager information
 * @return true if the download manager is available
 */
public static boolean isDownloadManagerAvailable(Context context) {

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.GINGERBREAD) {
        return true;
    }
    return false;
}

Method's name explains it all. Once you are sure DownloadManager is available, you can do something like this:

方法的名称解释了这一切。一旦确定DownloadManager可用,您可以执行以下操作:

String url = "url you want to download";
DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");
request.setTitle("Some title");
// in order for this if to run, you must use the android 3.2 to compile your app
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");

// get download service and enqueue file
DownloadManager manager = (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

Download progress will be showing in the notification bar.

下载进度将显示在通知栏中。

Final thoughts

First and second methods are just the tip of the iceberg. There are lots of things you have to keep in mind if you want your app to be robust. Here is a brief list:

第一种和第二种方法只是冰山一角。如果您希望自己的应用程序功能强大,那么您必须记住很多事情。这是一个简短的清单:

  • You must check whether user has an internet connection available
  • 您必须检查用户是否有可用的Internet连接
  • Make sure you have the right permissions (INTERNET and WRITE_EXTERNAL_STORAGE); also ACCESS_NETWORK_STATE if you want to check internet availability.
  • 确保您拥有正确的权限(INTERNET和WRITE_EXTERNAL_STORAGE);如果您想查看互联网可用性,还可以访问ACCESS_NETWORK_STATE。
  • Make sure the directory were you are going to download files exist and has write permissions.
  • 确保目录是否要下载存在的文件并具有写入权限。
  • If download is too big you may want to implement a way to resume the download if previous attempts failed.
  • 如果下载太大,您可能希望实现一种方法,以便在先前的尝试失败时恢复下载。
  • Users will be grateful if you allow them to interrupt the download.
  • 如果您允许用户中断下载,用户将不胜感激。

Unless you need detailed control of the download process, then consider using DownloadManager (3) because it already handles most of the items listed above.

除非您需要详细控制下载过程,否则请考虑使用DownloadManager(3),因为它已经处理了上面列出的大多数项目。

But also consider that your needs may change. For example, DownloadManager does no response caching. It will blindly download the same big file multiple times. There's no easy way to fix it after the fact. Where if you start with a basic HttpURLConnection (1, 2), then all you need is to add an HttpResponseCache. So the initial effort of learning the basic, standard tools can be a good investment.

但也要考虑您的需求可能会发生变化。例如,DownloadManager没有响应缓存。它会盲目地多次下载同一个大文件。事后没有简单的方法来解决它。如果你从一个基本的HttpURLConnection(1,2)开始,那么你只需要添加一个HttpResponseCache。因此,学习基本标准工具的初步努力可能是一项很好的投资。

#4


0  

public static class Downloader {

 public static void DownloadFile(String fileURL, File directory) {
    try {
         FileOutputStream file = new FileOutputStream(directory);
         URL url = new URL(fileURL);
        HttpURLConnection connection = (HttpURLConnection) url .openConnection();
         connection .setRequestMethod("GET");
         connection .setDoOutput(true);
         connection .connect();
         InputStream input = connection .getInputStream();
         byte[] buffer = new byte[1024];
         int len = 0;
          while ((len = input .read(buffer)) > 0) {
           file .write(buffer, 0, len );
         }
        file .close();
  } catch (Exception e) {
          e.printStackTrace();
   }
}

For more info click here http://androiddhina.blogspot.in/2015/09/how-to-download-pdf-from-url-in-android.html

欲了解更多信息,请点击这里http://androiddhina.blogspot.in/2015/09/how-to-download-pdf-from-url-in-android.html

#5


0  

There is no need to put lengthy code to open and download pdf in android you can just use below code to open and download pdf

没有必要在android中打开和下载pdf冗长的代码,你可以使用下面的代码来打开和下载pdf

String URL ="http://worldhappiness.report/wp-content/uploads/sites/2/2016/03/HR-V1_web.pdf"

 startActivity(new Intent(Intent.ACTION_VIEW,Uri.parse(URL)));