在开发过程中,总会需要从网络上下载文件,有时候还需要将下载进度显示在下拉菜单中。
现在写了一个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>
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