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


当前回答

我推荐你使用我的Project Netroid,它是基于Volley的。我添加了一些功能,如多事件回调,文件下载管理。这可能会有帮助。

其他回答

重要的

AsyncTask在Android 11中已弃用。

欲了解更多信息,请查看以下帖子

Android AsyncTask API在Android 11中已弃用。有什么替代方案? https://developer.android.com/reference/android/os/AsyncTask

可能应该移动到谷歌建议的并发框架

我遇到了一个简单文件下载库 获取,重要的是,它有存储访问框架,内容提供程序和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

我正在为我现在使用的其他解决方案添加另一个答案,因为Android查询太大了,无法保持健康。所以我搬到了这个https://github.com/amitshekhariitbhu/Fast-Android-Networking。

    AndroidNetworking.download(url,dirPath,fileName).build()
      .setDownloadProgressListener(new DownloadProgressListener() {
        public void onProgress(long bytesDownloaded, long totalBytes) {
            bar.setMax((int) totalBytes);
            bar.setProgress((int) bytesDownloaded);
        }
    }).startDownload(new DownloadListener() {
        public void onDownloadComplete() {
            ...
        }

        public void onError(ANError error) {
            ...
        }
    });

您可以使用LiveData和协程观察下载管理器的进度,参见下面的要点

https://gist.github.com/FhdAlotaibi/678eb1f4fa94475daf74ac491874fc0e

data class DownloadItem(val bytesDownloadedSoFar: Long = -1, val totalSizeBytes: Long = -1, val status: Int)

class DownloadProgressLiveData(private val application: Application, private val requestId: Long) : LiveData<DownloadItem>(), CoroutineScope {

    private val downloadManager by lazy {
        application.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
    }

    private val job = Job()

    override val coroutineContext: CoroutineContext
        get() = Dispatchers.IO + job

    override fun onActive() {
        super.onActive()
        launch {
            while (isActive) {
                val query = DownloadManager.Query().setFilterById(requestId)
                val cursor = downloadManager.query(query)
                if (cursor.moveToFirst()) {
                    val status = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_STATUS))
                    Timber.d("Status $status")
                    when (status) {
                        DownloadManager.STATUS_SUCCESSFUL,
                        DownloadManager.STATUS_PENDING,
                        DownloadManager.STATUS_FAILED,
                        DownloadManager.STATUS_PAUSED -> postValue(DownloadItem(status = status))
                        else -> {
                            val bytesDownloadedSoFar = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_BYTES_DOWNLOADED_SO_FAR))
                            val totalSizeBytes = cursor.getInt(cursor.getColumnIndex(DownloadManager.COLUMN_TOTAL_SIZE_BYTES))
                            postValue(DownloadItem(bytesDownloadedSoFar.toLong(), totalSizeBytes.toLong(), status))
                        }
                    }
                    if (status == DownloadManager.STATUS_SUCCESSFUL || status == DownloadManager.STATUS_FAILED)
                        cancel()
                } else {
                    postValue(DownloadItem(status = DownloadManager.STATUS_FAILED))
                    cancel()
                }
                cursor.close()
                delay(300)
            }
        }
    }

    override fun onInactive() {
        super.onInactive()
        job.cancel()
    }

}

当我开始学习android开发时,我知道ProgressDialog是正确的方法。ProgressDialog的setProgress方法可以在下载文件时调用它来更新进度级别。

我在许多应用程序中看到的最好的情况是,它们自定义了进度对话框的属性,使进度对话框的外观和感觉比库存版本更好。很好地保持用户的一些动画,如青蛙,大象或可爱的猫/小狗。任何有进度对话框的动画都能吸引用户,他们不喜欢长时间等待。