使用AsyncTask实现文件下载并且在状态中显示下载进度

时间:2023-12-16 13:39:32

2013年10月24日  上班的第二天

  昨天我是用afinal完成的则个功能,但是公司里并不希望使用第三方的代码,所以要求我在不使用第三方开源项目的情况下实现。

 

  最先我是使用Thread开启一个子线程,在这个线程中完成文件下载,然后使用Handler异步消息来更新Notification中的进度条,废了九牛二虎之力,虽然完成了功能,但是做出的效果就是特别的卡,甚至连通知栏下拉都被冻结了。

  后来我尝试了AsyncTask,很轻松的完成了下载和进度值的计算,但是在通知栏中改变进度条的进度,依然会出现卡屏的问题。

  最后在*中查找解决方案,给出的答案是,在更新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