我试图写一个简单的应用程序得到更新。为此,我需要一个简单的函数,可以下载文件并在ProgressDialog中显示当前进度。我知道如何做的ProgressDialog,但我不确定如何显示当前的进度,以及如何下载文件放在第一位。


当前回答

我遇到了一个简单文件下载库 获取,重要的是,它有存储访问框架,内容提供程序和URI支持。如果有人还在寻找,可能会有帮助。

//AndroidX .tonyodev.fetch2:xfetch2:3.1.6

实现"com.tonyodev.fetch2:fetch2:3.0.12" //支持lib

需要的权限,如果你不是使用应用程序特定的目录。

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

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

网络权限

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

private Fetch fetch;
FetchConfiguration fetchConfiguration = new FetchConfiguration.Builder(this)
                .setDownloadConcurrentLimit(3)//Concurrent Download limit
                .build();

        fetch = Fetch.Impl.getInstance(fetchConfiguration);

        String url = "http:www.example.com/test.txt";//URL of file
        String file = "/downloads/test.txt";//Path of file
        
        final Request request = new Request(url, file);
        request.setPriority(Priority.HIGH);
        request.setNetworkType(NetworkType.ALL);//Preferred network type
        request.addHeader("clientKey", "SD78DF93_3947&MVNGHE1WONG");//Auth header if any
        
        fetch.enqueue(request, updatedRequest -> {
            //Request was successfully enqueued for download.
        }, error -> {
            //An error occurred enqueuing the request.
        });

    }

倾听更新和进展

FetchListener fetchListener = new FetchListener() {
    @Override
    public void onQueued(@NotNull Download download, boolean waitingOnNetwork) {
        if (request.getId() == download.getId()) {
            showDownloadInList(download);
        }
    }

    @Override
    public void onCompleted(@NotNull Download download) {

    }

    @Override
    public void onError(@NotNull Download download) {
        Error error = download.getError();
    }

    @Override
    public void onProgress(@NotNull Download download, long etaInMilliSeconds, long downloadedBytesPerSecond) {
        if (request.getId() == download.getId()) {
            updateDownload(download, etaInMilliSeconds);
        }
        int progress = download.getProgress();
    }

    @Override
    public void onPaused(@NotNull Download download) {

    }

    @Override
    public void onResumed(@NotNull Download download) {

    }

    @Override
    public void onCancelled(@NotNull Download download) {

    }

    @Override
    public void onRemoved(@NotNull Download download) {

    }

    @Override
    public void onDeleted(@NotNull Download download) {

    }
};

fetch.addListener(fetchListener);

//Remove listener when done.
fetch.removeListener(fetchListener);

此示例代码取自所有者页面,所有功劳都归于Tonyo Francis

其他回答

不要忘记用新文件("/mnt/sdcard/…")替换"/sdcard…",否则你会得到一个FileNotFoundException

    private class DownloadTask extends AsyncTask<String, Integer, String> {

        private PowerManager.WakeLock mWakeLock;
        String onlinePathBundle, onlinePathMusic, offlinePathBundle, offlinePathMusic;

        CircleProgressBar progressBar;
        RelativeLayout rl_progress;
        ImageView btn_download;
        TextView tv_progress;

        public DownloadTask(String onlinePathBundle, String onlinePathMusic, String offlinePathBundle, String offlinePathMusic, CircleProgressBar progressBar, RelativeLayout rl_progress, ImageView btn_download,
                            TextView tv_progress) {
            this.offlinePathBundle = offlinePathBundle;
            this.offlinePathMusic = offlinePathMusic;
            this.progressBar = progressBar;
            this.rl_progress = rl_progress;
            this.btn_download = btn_download;
            this.tv_progress = tv_progress;
            this.onlinePathBundle = onlinePathBundle;
            this.onlinePathMusic = onlinePathMusic;
        }

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            progressBar.setMax(100);
            rl_progress.setVisibility(View.VISIBLE);
            btn_download.setVisibility(View.GONE);

            PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, getClass().getName());
            mWakeLock.acquire();
        }

        @Override
        protected String doInBackground(String... sUrl) {
            String firstResult = downTask(onlinePathBundle, 1, offlinePathBundle);
            String seondResult = downTask(onlinePathMusic, 2, offlinePathMusic);
            if (firstResult != null) {
                Toast.makeText(SplashActivity.this, "Download error: " + firstResult, Toast.LENGTH_LONG).show();
                return firstResult;
            } else {
                return seondResult;
            }

        }

        @Override
        protected void onProgressUpdate(Integer... progress) {
            super.onProgressUpdate(progress);
            progressBar.setProgress(progress[0]);
            tv_progress.setText(progress[0] + "%");

        }

        @Override
        protected void onPostExecute(String result) {
            super.onPostExecute(result);
            rl_progress.setVisibility(View.GONE);
            btn_download.setVisibility(View.VISIBLE);
            if (result != null) {
                Toast.makeText(SplashActivity.this, "Download error: " + result, Toast.LENGTH_LONG).show();
            } else {
                rl_progress.setVisibility(View.GONE);
                btn_download.setVisibility(View.GONE);
            }

        }

        public String downTask(String onlineNewPath, int numberOfTask, String offlineNewPath) {
            InputStream input = null;
            OutputStream output = null;
            HttpURLConnection connection = null;
            try {
                URL url = new URL(onlineNewPath);
                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(offlineNewPath);

                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
                        if (numberOfTask == 1) {
                            publishProgress((int) (total * 50 / fileLength));
                        } else if (numberOfTask == 2) {
                            publishProgress(((int) (total * 50 / fileLength)) + 50);
                        }

                    }
                    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;
        }
    }

如果你要从网上下载东西,别忘了给你的manifest文件添加权限!

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.helloandroid"
    android:versionCode="1"
    android:versionName="1.0">

        <uses-sdk android:minSdkVersion="10" />

        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
        <uses-permission android:name="android.permission.INTERNET"></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:icon="@drawable/icon" 
            android:label="@string/app_name" 
            android:debuggable="true">

        </application>

</manifest>

使用Android查询库,确实很酷。你可以改变它使用ProgressDialog,就像你在其他例子中看到的那样,这个将从你的布局中显示进度视图,并在完成后隐藏它。

File target = new File(new File(Environment.getExternalStorageDirectory(), "ApplicationName"), "tmp.pdf");
new AQuery(this).progress(R.id.progress_view).download(_competition.qualificationScoreCardsPdf(), target, new AjaxCallback<File>() {
    public void callback(String url, File file, AjaxStatus status) {
        if (file != null) {
            // do something with file  
        } 
    }
});

是的,上面的代码是可以工作的,但是如果你在Asynctask的onProgressUpdate中更新你的进度条,你按下后退按钮或完成你的活动,Asynctask将失去它与你的UI的跟踪,当你回到你的活动,即使下载正在后台运行,你也不会看到进度条上的更新。因此,OnResume()尝试运行一个线程,如runOnUIThread与一个定时器任务更新进度条的值从AsyncTask运行后台更新。

private void updateProgressBar(){
    Runnable runnable = new updateProgress();
    background = new Thread(runnable);
    background.start();
}

public class updateProgress implements Runnable {
    public void run() {
        while(Thread.currentThread()==background)
            //while (!Thread.currentThread().isInterrupted()) {
            try {
                Thread.sleep(1000); 
                Message msg = new Message();
                progress = getProgressPercentage();        
                handler.sendMessage(msg);
            } catch (InterruptedException e) {
                Thread.currentThread().interrupt();
            } catch (Exception e) {
        }
    }
}

private Handler handler = new Handler(){
    @Override
    public void handleMessage(Message msg) {
        progress.setProgress(msg.what);
    }
};

当你的活动不可见时,不要忘记销毁线程。

private void destroyRunningThreads() {
    if (background != null) {
        background.interrupt();
        background=null;
    }
}