Android中AsyncTask进行后台下载文件并在下拉菜单显示下载进度

在开发过程中,总会需要从网络上下载文件,有时候还需要将下载进度显示在下拉菜单中。

现在写了一个Demo,封装了AsyncTask下载文件和进度显示的代码,以后在做项目的时候能够直接进行使用。

效果图:

技术分享


主界面只有一个按钮,比较简单:

/ layout / 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" >

    <Button
        android:id="@+id/button"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentTop="true"
        android:text="点击下载" />

</RelativeLayout>


MainActivity:其中的思路解释均在代码中:

import android.app.Activity;
import android.os.Bundle;
import android.os.Handler;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

public class MainActivity extends Activity {

	private Handler mHandler = new Handler();
	
	private AsyncTaskUtil mDownloadAsyncTask;
	
	private Button mButton;
	
	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		
		mButton = (Button) findViewById(R.id.button);
		mButton.setOnClickListener(new OnClickListener() {
			
			@Override
			public void onClick(View v) {
				//AsyncTask异步下载任务
				mDownloadAsyncTask = new AsyncTaskUtil(MainActivity.this, mHandler);
				mDownloadAsyncTask.execute("http://apps.wandoujia.com/apps/com.sec.print.mobileprint/download", "Mobile Print.apk");//必须传入两个参数——参数1:url;参数2:文件名(可以为null)
			}
		});
	}
}

以上只要通过新建一个AsyncTaskUtil的对象,传入url和文件名便能后台下载文件病显示下载进度,是不是很方面?具体的代码解析如下:


AsyncTaskRunnable:用于handler.post(Runnable)方法来更新UI,下载进度主要通过NotificationManager、Notification和RemoteView来显示、更新下载的进度,不懂的同学需要google一下~

import java.text.DecimalFormat;

import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.util.Log;
import android.widget.RemoteViews;
import android.widget.Toast;

public class AsyncTaskRunnable implements Runnable{

	public static final String TAG = "AsyncTaskRunnable";
	//主线程的activity
	private Context mContext;
	//notification的状态:更新 or 失败 or 成功
	private int mStatus;
	//notification的下载比例
	private float mSize;
	//管理下拉菜单的通知信息
	private NotificationManager mNotificationManager;
	//下拉菜单的通知信息
	private Notification mNotification;
	//下拉菜单的通知信息的view
	private RemoteViews mRemoteViews;
    //下拉菜单的通知信息的种类id
	private static final int NOTIFICATION_ID = 1;
	
	//设置比例和数据
	public void setDatas(int status , float size) {
		this.mStatus = status;
		this.mSize = size;
	}
	//初始化
	public AsyncTaskRunnable(Context context) {
		this.mContext = context;
		mNotificationManager = (NotificationManager) mContext.getSystemService(Context.NOTIFICATION_SERVICE);
		//初始化下拉菜单的通知信息
		mNotification = new Notification();
		mNotification.icon = R.drawable.ic_launcher;//设置下载进度的icon
		mNotification.tickerText = mContext.getResources().getString(R.string.app_name); //设置下载进度的title
		
		mRemoteViews = new RemoteViews(mContext.getPackageName(), R.layout.down_notification);//对于RemoteView的使用,不懂的需要查找google
		mRemoteViews.setImageViewResource(R.id.id_download_icon, R.drawable.ic_launcher);
	}
	
	@Override
	public void run() {//通过判断不同的状态:更新中/下载失败/下载成功 更新下拉菜单的通知信息
		switch (mStatus) {
		case AsyncTaskUtil.NOTIFICATION_PROGRESS_FAILED://下载失败
			mNotificationManager.cancel(NOTIFICATION_ID);
			break;

		case AsyncTaskUtil.NOTIFICATION_PROGRESS_SUCCEED://下载成功
			mRemoteViews.setTextViewText(R.id.id_download_textview, "Download completed ! ");
			mRemoteViews.setProgressBar(R.id.id_download_progressbar, 100, 100, false);
			mNotification.contentView = mRemoteViews;
			mNotificationManager.notify(NOTIFICATION_ID, mNotification);
			mNotificationManager.cancel(NOTIFICATION_ID);
			Toast.makeText(mContext, "Download completed ! ", Toast.LENGTH_SHORT).show();
			break;
			
		case AsyncTaskUtil.NOTIFICATION_PROGRESS_UPDATE://更新中
			DecimalFormat format = new DecimalFormat("0.00");//数字格式转换
			String progress = format.format(mSize);
			Log.d(TAG, "the progress of the download " + progress);
			mRemoteViews.setTextViewText(R.id.id_download_textview, "Download completed : " + progress + " %");
			mRemoteViews.setProgressBar(R.id.id_download_progressbar, 100, (int)mSize, false);
			mNotification.contentView = mRemoteViews;
			mNotificationManager.notify(NOTIFICATION_ID, mNotification);
			break;
		}
	}

}
其中需要建立一个下载进度的布局文件,如下:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical" >

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:gravity="center"
        android:orientation="horizontal"
        android:background="@android:color/white" >

        <ImageView
            android:id="@+id/id_download_icon"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dp"
            android:layout_marginLeft="10dp"
            android:src="@drawable/ic_launcher" />

        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginRight="10dip"
            android:layout_weight="1"
            android:orientation="vertical" >

            <TextView
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="@string/app_name"
                android:textColor="@android:color/black"
                android:textSize="18dip"
                android:textStyle="bold" />

            <ProgressBar
                android:id="@+id/id_download_progressbar"
                style="?android:attr/progressBarStyleHorizontal"
                android:layout_width="fill_parent"
                android:layout_height="wrap_content"
                android:layout_marginTop="5dp"
                android:max="100"
                android:progress="0"
                android:secondaryProgress="0" />

            <TextView
                android:id="@+id/id_download_textview"
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"
                android:text="Download completed : " 
                android:textColor="@android:color/black"
                android:textSize="12dip"
                android:textStyle="bold" />
        </LinearLayout>
    </LinearLayout>

</LinearLayout>


异步下载类:AsyncTaskUtil用于下载文件:
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.util.Timer;
import java.util.TimerTask;

import android.content.Context;
import android.os.AsyncTask;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.widget.Toast;

public class AsyncTaskUtil extends AsyncTask<String, Double, Boolean> {

	public static final String TAG = "AsyncTaskUtil";
	
	public static final int NOTIFICATION_PROGRESS_UPDATE = 0x10;//用于更新下载进度的标志
	public static final int NOTIFICATION_PROGRESS_SUCCEED = 0x11;//表示下载成功
	public static final int NOTIFICATION_PROGRESS_FAILED = 0x12;//表示下载失败

	//URL
	private String mUrl;
	//activity
	private Context mContext;
	//任务定时器
	private Timer mTimer;
	//定时任务
	private TimerTask mTask;
	//主线程传递过来的handler
	private Handler  mHandler;
	//所要下载的文件大小
	private long mFileSize;
	//已下载的文件大小
	private long mTotalReadSize;
	//AsyncTaskRunnable实现了Runnable接口,用于更新下载进度的显示
	private AsyncTaskRunnable mRunnable;

	//构造方法
	public AsyncTaskUtil(Context context, Handler handler) {
		mContext = context;
		mHandler = handler;

		mTimer = new Timer();
		mTask = new TimerTask() {//在run方法中执行定时的任务
			@Override
			public void run() {
				//size表示下载进度的百分比
				float size = (float) mTotalReadSize * 100 / (float) mFileSize;
				//通过AsyncTaskRunnable的setDatas方法下载的进度和状态(更新中、失败、成功)
				mRunnable.setDatas(NOTIFICATION_PROGRESS_UPDATE, size);
				//更新进度
				mHandler.post(mRunnable);
			}
		};
		mRunnable = new AsyncTaskRunnable(mContext);
	}

	
	// 执行耗时操作,params[0]为url,params[1]为文件名(空则写入null)
	@Override
	protected Boolean doInBackground(String... params) {
		
		//任务定时器一定要启动
		mTimer.schedule(mTask, 0, 500);
		
		try {
			mUrl = params[0];
			//建立链接
			URLConnection connection = new URL(mUrl).openConnection();
			//获取文件大小
			mFileSize = connection.getContentLength();
			Log.d(TAG, "the count of the url content length is : " + mFileSize);

			//获得输入流
			InputStream is = connection.getInputStream();
			//先建立文件夹
			File fold = new File(getFolderPath());
			if (!fold.exists()) {
				fold.mkdirs();
			}
			
			String fileName = "";
			//判断文件名:用户自定义或由url获得
			if(params[1] != null){
				fileName = params[1];
			} else{
				fileName = getFileName(params[0]);
			}
			//文件输出流
			FileOutputStream fos = new FileOutputStream(new File(getFolderPath()
							+ fileName));

			byte[] buff = new byte[1024];
			int len;
			while ((len = is.read(buff)) != -1) {
				mTotalReadSize += len;
				fos.write(buff, 0, len);
			}
			fos.flush();
			fos.close();

		} catch (Exception e) {
			//异常,下载失败
			mRunnable.setDatas(NOTIFICATION_PROGRESS_FAILED, 0);
			//发送显示下载失败
			mHandler.post(mRunnable);
			if(mTimer != null && mTask != null){
				mTimer.cancel();
				mTask.cancel();
			}
			e.printStackTrace();
			return false;
		}
		//下载成功
		mRunnable.setDatas(NOTIFICATION_PROGRESS_SUCCEED, 0);
		mHandler.post(mRunnable);
		if(mTimer != null && mTask != null){
			mTimer.cancel();
			mTask.cancel();
		}
		return true;
	}

	//由url获得文件名
	private String getFileName(String string) {
		return string.substring(string.lastIndexOf("/") + 1);
	}

	//下载文件夹路径
	private String getFolderPath() {
		return Environment.getExternalStorageDirectory().toString() + "/AsyncTaskDownload/";
	}


	// doInBackground方法之前调用,初始化UI
	@Override
	protected void onPreExecute() {
		super.onPreExecute();
	}

	// 在doInBackground方法之后调用
	@Override
	protected void onPostExecute(Boolean result) {
		super.onPostExecute(result);
		if (result) {
			Toast.makeText(mContext, "Download Completed ! ", Toast.LENGTH_SHORT).show();
		} else {
			Toast.makeText(mContext, "Download Failed ! ", Toast.LENGTH_SHORT).show();
		}
	}

	@Override
	protected void onProgressUpdate(Double... values) {
		super.onProgressUpdate(values);
	}

}

好了,以上就是今天分享的内容~~是时候(~﹃~)~zZ

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。