使用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进度环使用 此处处理不同状态下不同进度环颜色及圈内文字等的相关处理,采用实际案例源码说明 -----------------偶是华丽丽分割线---------------- ...
随机推荐
- Android常用客户端测试工具
Emmagee GT iTest PowerTutor 网速限制 Root Explorer ApkEditor 陆续添加...
- mysql 忘记root 密码的解决方法
LINUX 1.切换root 用户 2.停止mysqld 服务 /etc/inid.d mysqld stop 3.跳过验证登录 mysqld_safe --skip-grant-tables &am ...
- 让window.close不提示:您查看的网页正在试图关闭窗口。是否关闭此窗口?
正常来说,当我们调用window.close来关闭从地址栏中打开的窗口时,IE会弹出提示说:您查看的网页正在试图关闭窗口,是否关闭此窗口? 你可以将window.close替换成下边的脚本,然后再测试 ...
- Support Vector Machine (2) : Sequential Minimal Optimization
目录 Support Vector Machine (1) : 简单SVM原理 Support Vector Machine (2) : Sequential Minimal Optimization ...
- 【Shell脚本】怎样表示一个for循环
[Shell脚本]怎样表示一个for循环 在此说一下我常用的两个结构: 1. for i in $(seq 1 100); do echo $i done 2. for (( i = ...
- Linux不使用useradd创建用户
手动创建用户的全过程:需要管理员权限. 1.在/etc/group中添加用户所属组的相关信息.如果用户还有辅助组则在对应组中加入该用户作为成员. 2.在/etc/passwd和/etc/shadow中 ...
- Java实现emf图片自己留转png(jpg)图片字节流
private byte[] emfToPng(InputStream is){ // InputStream inputStream=null; byte[] by=null; EMFInputSt ...
- Jquery--弹窗
<title>弹窗</title> <script src="JS/jquery-1.7.2.js"></script> <s ...
- Elasticsearch升级1.5版本暴露jdk的bug
把测试环境的Elasticsearch升级到1.5.1版本,启动的时候报错: [root@node2 elasticsearch-1.5.1]# bin/service/elasticsearch s ...
- Getting Started
https://developers.google.com/v8/get_started Getting Started This document introduces some key V8 co ...