3

我遵循了一些在线教程并创建了此代码来下载我在 Dropbox 中托管的文件

我正在使用异步任务来执行此操作

// AsyncTask to download a file
    private class DownloadTask extends AsyncTask<String, Integer, String> {

        private Context context;

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

        @Override
        protected String doInBackground(String... sUrl) {
            // 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);
            PowerManager.WakeLock wl = pm.newWakeLock(
                    PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
            wl.acquire();

            try {
                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();

                    // TODO

                    File file = new File(Environment
                            .getExternalStorageDirectory().getPath()
                            + "/kathmandu.map");

                    if (file.exists()) {
                        Log.i("File Exists", "Code Gets here, file exists");
                        return "exists";
                        // if (connection.getResponseCode() ==
                        // HttpURLConnection.HTTP_NOT_MODIFIED) {
                        //
                        // return null;
                        // }
                    }

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

                    // download the file
                    input = connection.getInputStream();
                    output = new FileOutputStream(Environment
                            .getExternalStorageDirectory().getPath()
                            + "/kathmandu.map");

                    byte data[] = new byte[4096];
                    long total = 0;
                    int count;
                    while ((count = input.read(data)) != -1) {
                        // allow canceling with back button
                        if (isCancelled())
                            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();
                }
            } finally {
                wl.release();
            }
            return null;
        }

单击下载选项菜单时,我会调用下载代码。

final DownloadTask downloadTask = new DownloadTask(MapActivity.this);
            downloadTask
                    .execute("https://dl.dropboxusercontent.com/u/95497883/kathmandu-2013-8-12.map");


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

该代码工作正常,但有时输出流不会写入完整文件并退出。一切看起来都很好。文件已下载,但已损坏。

getContentLength() 也返回 -1,因此我无法检查整个文件是否已使用内容长度下载。该文件是离线矢量地图,我需要它来显示离线地图。损坏的文件在尝试访问它时会导致运行时异常。有什么方法可以确保文件已正确下载。

我也想通过应用程序本身提供数据。我可以把它放在我的应用程序的资产文件夹中吗?在运行时访问资产文件夹中文件的最佳方法是什么。

4

1 回答 1

2

您的资产文件夹不可写,因为它是 apk 的一部分。您当然可以像在代码中那样使用应用程序的沙箱存储(使用 Environment.getDir())或外部存储(使用 Environment.getExternalStorageDirectory())。

我认为使用 DownloadManager 将是一个好主意,可以准确地实现您想要的,请参考:http: //developer.android.com/reference/android/app/DownloadManager.html

一个简短的解决方案

DownloadManager.Request req=new DownloadManager.Request(url);

req.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_WIFI
                               | DownloadManager.Request.NETWORK_MOBILE)
   .setTitle("Downloading")
   .setDescription("Map is Being Downloaded")
   .setDestinationInExternalPublicDir(Environment.getExternalStorageDirectory,
                                      "+/maps_app/something.map");
于 2013-11-06T15:59:53.097 回答