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