我试图写一个简单的应用程序得到更新。为此,我需要一个简单的函数,可以下载文件并在ProgressDialog中显示当前进度。我知道如何做的ProgressDialog,但我不确定如何显示当前的进度,以及如何下载文件放在第一位。
当前回答
您可以使用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()
}
}
其他回答
我遇到了一个简单文件下载库 获取,重要的是,它有存储访问框架,内容提供程序和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
我推荐你使用我的Project Netroid,它是基于Volley的。我添加了一些功能,如多事件回调,文件下载管理。这可能会有帮助。
是的,上面的代码是可以工作的,但是如果你在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;
}
}
如果你要从网上下载东西,别忘了给你的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>
我个人的建议是使用进度对话框并在执行前进行构建,或者在OnPreExecute()上初始化,如果你使用进度对话框的水平风格的进度条,则经常发布进度。剩下的部分是优化doInBackground的算法。
推荐文章
- 如何改变菜单项的文本颜色在安卓?
- codestyle;把javadoc放在注释之前还是之后?
- 如何在Spring中定义List bean ?
- 将Set<T>转换为List<T>的最简洁的方法
- 在JavaScript中,什么相当于Java的Thread.sleep() ?
- Android选择器和文本颜色
- 使用Java重命名文件
- URL从Java中的类路径加载资源
- .toArray(new MyClass[0]) or .toArray(new MyClass[myList.size()])?
- Hibernate中不同的保存方法之间有什么区别?
- 视图绑定-我如何获得包含布局的绑定?
- 在Android Studio中改变矢量资产的填充颜色
- 在构建中编写注释的语法是什么?gradle文件?
- 如何以编程方式添加按钮色调
- 用Android Studio进行调试永远停留在“等待调试器”状态