您的位置:首页 > 移动开发 > Android开发

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

2016-11-30 22:05 519 查看
在开发过程中,总会需要从网络上下载文件,有时候还需要将下载进度显示在下拉菜单中。

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

效果图:



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

/ layout / activity_main.xml :

[html] view
plain copy

<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:其中的思路解释均在代码中:

[java] view
plain copy

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一下~

[java] view
plain copy

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;

}

}

}

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

[html] view
plain copy

<?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用于下载文件:

[java] view
plain copy

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
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: