使用AsyncTask实现文件下载并且在状态中显示下载进度
2013年10月24日 上班的第二天
昨天我是用afinal完成的则个功能,但是公司里并不希望使用第三方的代码,所以要求我在不使用第三方开源项目的情况下实现。
最先我是使用Thread开启一个子线程,在这个线程中完成文件下载,然后使用Handler异步消息来更新Notification中的进度条,废了九牛二虎之力,虽然完成了功能,但是做出的效果就是特别的卡,甚至连通知栏下拉都被冻结了。
后来我尝试了AsyncTask,很轻松的完成了下载和进度值的计算,但是在通知栏中改变进度条的进度,依然会出现卡屏的问题。
最后在StackOverFlow中查找解决方案,给出的答案是,在更新Notification的时候,使用Handler来更新进度条进度,更新的频率特别高,再次期间会不断的生成RemoteViews对象,所以消耗了大量的内存。虽然没有看到实实在在的代码,但是有了解决的思路。
1.降低Handler的更新的频率;
2.尽量能够复用RemoteViews的对象。
对应的具体的实现是用计数器来控制更新的频率,用静态的RemoteViews对象。
后面上代码:
主界面的布局文件:activity_main.xml
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:padding="10dp"
tools:context=".MainActivity" > <TextView
android:id="@+id/hint_tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="10dp"
android:text="@string/tv_main_hint" /> <EditText
android:id="@+id/url_et"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/hint_tv"
android:hint="@string/et_downloadurl"
android:singleLine="true" /> <Button
android:id="@+id/downloadBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/url_et"
android:paddingTop="20dp"
android:text="@string/str_download" /> <Button
android:layout_below="@id/downloadBtn"
android:id="@+id/pauseBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:text="@string/btn_pause" /> <Button
android:layout_below="@id/pauseBtn"
android:id="@+id/continueBtn"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp"
android:text="@string/btn_continue" /> <ProgressBar
android:layout_below="@id/continueBtn"
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:paddingTop="20dp" /> <TextView
android:layout_below="@id/pb"
android:id="@+id/progressTV"
android:text="0%"
android:layout_centerHorizontal="true"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="20dp" /> </RelativeLayout>
自定义Notification的布局文件: notify_vew.xml
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent" > <ImageView
android:id="@+id/notify_icon"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:src="@drawable/ic_launcher" /> <TextView
android:id="@+id/tv"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_toRightOf="@id/notify_icon"
android:singleLine="true"
android:text="下载进度..." /> <ProgressBar
android:id="@+id/pb"
style="?android:attr/progressBarStyleHorizontal"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_below="@id/tv"
android:layout_toRightOf="@id/notify_icon"
android:max="100"
android:paddingRight="10dp"
android:progress="50"
android:secondaryProgress="74"
android:visibility="visible" /> </RelativeLayout>
strings.xml
<?xml version="1.0" encoding="utf-8"?>
<resources> <string name="app_name">DownLoader</string>
<string name="action_settings">Settings</string>
<string name="hello_world">Hello world!</string>
<string name="tv_main_hint">下载地址:</string>
<string name="et_downloadurl">请输入下载地址</string>
<string name="str_download">开始下载</string>
<string name="btn_pause">暂停下载</string>
<string name="btn_continue">继续下载</string> </resources>
在清单文件中申请的权限:AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
MainActivity.java
package com.yt.asynctaskdemo; import java.io.FileOutputStream; import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLConnection; import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Message;
import android.app.Activity;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;
import android.widget.ProgressBar;
import android.widget.RemoteViews;
import android.widget.TextView; public class MainActivity extends Activity { public static final String TAG = "MainActivity"; private int count;
private int current;
private EditText downloadUrlEt;
private Button downloadBtn;
private Button pauseBtn;
private Button continueBtn;
private ProgressBar pb;
private int progress;
private TextView progressTV;
private boolean finished;
private boolean paused;
private NotificationManager manager;
private Notification notification;
private static RemoteViews contentView; private int times; private MyAsyncTask mTask; private Handler handler = new Handler(){
public void handleMessage(android.os.Message msg) {
if(contentView == null){
contentView = new RemoteViews(getPackageName(), R.layout.notify_view);
contentView.setProgressBar(R.id.pb, 100, 0, false);
notification.icon = R.drawable.ic_launcher;
notification.tickerText = "下载进度";
notification.flags = notification.DEFAULT_ALL;
notification.contentView = contentView;
PendingIntent contentIntent = PendingIntent.getActivity(MainActivity.this, 0,
new Intent(MainActivity.this, MainActivity.class), 0); notification.setLatestEventInfo(MainActivity.this, "你好!",
"byebye", contentIntent);
manager.notify(0, notification);
}
if(times++ % 5 == 0 || progress==100){
contentView.setProgressBar(R.id.pb, 100, progress, false);
notification.contentView = contentView;
manager.notify(0, notification);
}
super.handleMessage(msg);
};
};
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
downloadUrlEt = (EditText) findViewById(R.id.url_et);
downloadUrlEt.setText("http://mit.95195.com/singleonline.apk");
downloadBtn = (Button) findViewById(R.id.downloadBtn);
pauseBtn = (Button) findViewById(R.id.pauseBtn);
continueBtn = (Button) findViewById(R.id.continueBtn);
progressTV = (TextView) findViewById(R.id.progressTV);
pb = (ProgressBar) findViewById(R.id.pb);
MyOnClickListener listener = new MyOnClickListener();
downloadBtn.setOnClickListener(listener);
pauseBtn.setOnClickListener(listener);
continueBtn.setOnClickListener(listener);
mTask = new MyAsyncTask();
manager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
notification = new Notification(R.drawable.ic_launcher, "下载进度条...",System.currentTimeMillis());
} /**
* 按钮事件监听
*
* @author yt
*
*/
class MyOnClickListener implements OnClickListener { @Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.downloadBtn:
mTask.execute("http://mit.95195.com/singleonline.apk");
break; case R.id.pauseBtn:
paused = true;
break; case R.id.continueBtn:
paused = false;
break;
}
} } class MyAsyncTask extends AsyncTask<String, Integer, String>{
@Override
protected String doInBackground(String... params) {
try {
URL url = new URL(params[0]);
URLConnection conn = url.openConnection();
count = conn.getContentLength();
InputStream is = conn.getInputStream();
OutputStream os = new FileOutputStream(Environment.getExternalStorageDirectory()+"/singleon.apk");
byte[] buffer = new byte[1024];
int len = -1;
while(!finished){
while(!paused && (len = is.read(buffer))>0){
current += len;
os.write(buffer,0,len);
progress = current * 100 / count;
// Log.i(TAG, "current = " + current + " count = " + count + " progress = " + progress);
publishProgress(progress);
Message msg = new Message();
handler.handleMessage(msg);
}
} } catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {;
e.printStackTrace();
} return progress+"";
} @Override
protected void onPostExecute(String result) {
Log.i(TAG, result+"");
super.onPostExecute(result);
} @Override
protected void onProgressUpdate(Integer... values) { if(values[0]==99){
finished = true;
manager.cancel(0);
}
progressTV.setText(values[0]+"");
pb.setProgress(progress);
super.onProgressUpdate(values);
} @Override
protected void onPreExecute() {
handler.handleMessage(new Message());
super.onPreExecute();
} } }
完整代码下载:http://download.csdn.net/detail/yuan936845015/6450041
使用AsyncTask实现文件下载并且在状态中显示下载进度的更多相关文章
- Android开发之文件下载,状态时显示下载进度,点击自动安装
在进行软件升级时,需要进行文件下载,在这里实现自定义的文件下载,并在状态栏显示下载进度,下载完成后,点击触发安装. 效果如图: 用于下载文件和显示现在进度的线程类如下: [java] view pl ...
- Android中如何下载文件并显示下载进度
原文地址:http://jcodecraeer.com/a/anzhuokaifa/androidkaifa/2014/1125/2057.html 这里主要讨论三种方式:AsyncTask.Serv ...
- 使用afinal下载文件并且在状态栏中显示下载的进度
2013年10月23日,今天是在“我在找你信息服务有限公司”第一天上班,公司给提出了这样一个要求:下载本公司的app,并且在下载的过程中要在状态栏中显示下载的进度,并且,可以暂停和继续下载. 下面是我 ...
- [iOS 多线程 & 网络 - 2.4] - 大文件下载 (边下边写/暂停恢复下载/压缩解压zip/多线程下载)
A.需求 边下边写入硬盘 显示下载进度 暂停/恢复 下载 解压文件 多线程下载 B.基本知识 1.小文件下载 如果文件比较小,下载方式会比较多直接用NSData的+ (id)dataWithCon ...
- 在Installshield的安装进度中显示自己设置的信息
原文:在Installshield的安装进度中显示自己设置的信息 以Installscript msi project为例,在installshield所制作的安装包安装过程中显示安装进度的,就在On ...
- (数据科学学习手札91)在Python中妥善使用进度条
本文示例代码已上传至我的Github仓库https://github.com/CNFeffery/DataScienceStudyNotes 1 简介 在日常运行程序的过程中常常涉及到循环迭代过程,对 ...
- Android中使用AsyncTask实现文件下载以及进度更新提示
Android提供了一个工具类:AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单.相对Handler来说AsyncTask更轻量级一些,适用于简单的异步处理,不需要借助线程和 ...
- ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案
原文:ssis package 在调试状态中设置断点,程序 不进入断点 的解决方案 针对 SSIS intergation 项目 > 属性 > Debug >Run64bITRunt ...
- 接上一篇中记录Echarts进度环使用【不同状态不同进度环颜色及圈内文字】--采用单实例业务进行说明
接上一篇中记录Echarts进度环使用 此处处理不同状态下不同进度环颜色及圈内文字等的相关处理,采用实际案例源码说明 -----------------偶是华丽丽分割线---------------- ...
随机推荐
- Li-Fi,LED光无线局域网
无需WiFi信号,点一盏LED灯就能上网.昨天,复旦大学计算机科学技术学院传出好消 息,一种利用屋内可见光传输网络信号的国际前沿通讯技术在实验室成功实现.研究人员将网络信号接入一盏1W的LED灯珠,灯 ...
- 转 LoadRunner 技巧之THML 与 URL两种录制模式分析
Loadrunner的Virtual User Generator 提供人脚本的录制功能,对于初学者来说,这大大的降低了编写脚本的门槛,loadrunner提供两种录制脚本的方式:Html_based ...
- LCC
LCC: super vector:
- poi批量导入excel文件
package com.practice.util; import java.io.File; import java.io.FileInputStream; import java.io.FileN ...
- c#轻松实现磁性窗口
/// <summary>/// 磁性窗体函数/// </summary>/// <param name="form">窗体控件(一般传this ...
- 《IT蓝豹》PlayNewsStandDemo资讯类新闻客户端框架
PlayNewsStandDemo资讯类新闻客户端框架,支持tab滑动切换,当切换到最左边或者最后边的时候停止滑动 本例子切换tab的效果根据AccelerateDecelerateInterpola ...
- Xrm.Utility.openEntityForm 时404.15 maxQueryString 错误 和 长度超过maxQueryStringLength值 错误
最近的项目里用到Xrm.Utility.openEntityForm 创建新记录时分别碰到以下错误: 以及 这两个错误都是因为想传递给表单的参数太多导致的url 查询参数太长导致的,前者是因为iis的 ...
- LNMP添加、删除虚拟主机及伪静态使用教程
一般情况下每个虚拟主机就是一个网站,网站一般通过域名进行访问.LNMP 1.2的网站添加过程和LNMP 1.1的基本类似,但是增加了FTP和数据库的创建.LNMP1.2的防跨目录也由原来在php.in ...
- mave的变量说明
Maven提供了三个隐式的变量可以用来访问环境变量,POM信息,和Maven Settings env env变量,暴露了你操作系统或者shell的环境变量.便 如在Maven POM中一个对${en ...
- DataRow[]与DataTable的转换代码【精炼】
Day_20170106 代码记录 //DataTable查询出DataRow[] DataRow[] drs = AllSysModuleDs.Tables[].Select(string.Form ...