ProgressBar去显示下载进度。这种实现方式有很多不完美之处,首先在Dialog+ProgressBar去实现,下载的过程中我们无法进行其他的操作,得停留在这个页面,用户体验不太好,其次,在下载的过程中会遇到很多异常需要我们自己去处理,比较麻烦,如果再要自己实现断点下载的功能,那就比较头痛了。下面来介绍2种我自己在项目开发中整理出来的比较好用的方法,第一种是采用Xutil(Github一款比较好用的框架,主要功能有数据库封装,网络请求,图片处理,注解)+自定义Notification,第2种是利用系统提供的DownloadManager去实现。 Notification去显示相关下载信息,贴上图和相应代码:

android 下拉通知栏 安卓下拉通知栏的软件_版本更新

package com.example.download;

import java.io.File;

import android.app.Notification;
import android.app.NotificationManager;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Environment;
import android.widget.RemoteViews;

import com.lidroid.xutils.HttpUtils;
import com.lidroid.xutils.exception.HttpException;
import com.lidroid.xutils.http.ResponseInfo;
import com.lidroid.xutils.http.callback.RequestCallBack;

public class HttpConnectService {
	private static final int NOTIFY_ID = 0;
	private NotificationManager mNotificationManager;
	private Notification mNotification;

	// 下载地址
	private String apkUrl = "http://dldir1.qq.com/dlomg/weishi/weishi_guanwang.apk";

	// 下载包安装路径
	private static final String savePath = Environment.getExternalStorageDirectory().getAbsolutePath()+"/weishi.apk";
	
	public void connectDownLoad(final Context context,final String packageName) {
		mNotificationManager = (NotificationManager) context.getSystemService(android.content.Context.NOTIFICATION_SERVICE);
		HttpUtils http = new HttpUtils();
		http.configTimeout(30000);
		http.configSoTimeout(30000);
		http.download(apkUrl,savePath, false, false,
				new RequestCallBack<File>() {

					@Override
					public void onStart() {	
                       setUpNotification(packageName,context);
					}

					@Override
					public void onLoading(long total,long current,boolean isUploading) {   
					    int progress = (int) (current * 100/total);
						RemoteViews contentview = mNotification.contentView;
						contentview.setTextViewText(R.id.tv_progress, progress + "%");
						contentview.setProgressBar(R.id.progressbar, 100, progress, false);
						mNotificationManager.notify(NOTIFY_ID, mNotification);
					}

					@Override
					public void onSuccess(ResponseInfo<File> responseInfo) {
						mNotificationManager.cancel(NOTIFY_ID);
						installAPK(responseInfo.result, context);
					}

					@Override
					public void onFailure(HttpException error, String msg) {
						RemoteViews contentview = mNotification.contentView;
						contentview.setTextViewText(R.id.tv_progress,"下载失败");
						contentview.setProgressBar(R.id.progressbar, 100,0, false);
						mNotificationManager.notify(NOTIFY_ID, mNotification);
					}
				});
	}

	
	/**
	 * 创建通知
	 */
	@SuppressWarnings("deprecation")
	private void setUpNotification(String packageName,Context context) {
		mNotification = new Notification(R.drawable.weishi, "正在下载",  System.currentTimeMillis());
		mNotification.flags = Notification.FLAG_ONGOING_EVENT;
		RemoteViews contentView = new RemoteViews(packageName, R.layout.download_notification_layout);
		mNotification.contentView = contentView;
		mNotificationManager.notify(NOTIFY_ID, mNotification);
	}
	
	//安装APK
	private void installAPK(File t,Context context) {
		Intent intent = new Intent();
		intent.setAction("android.intent.action.VIEW");
		intent.addCategory("android.intent.category.DEFAULT");
		intent.setDataAndType(Uri.fromFile(t),"application/vnd.android.package-archive");
		context.startActivity(intent);
	}
	
}

      主要功能实现在connectDownLoad方法里面,在这个方法里面我们重写了4个方法,分别是onStart(),onLoading(),onSuccess(),onFailure(),对应下载的4种情况,即下载开始,下载进行时,下载完成,下载失败,下载开始时创建一个自定义的Notification,我们将自定义的布局的内容写在R.layout.download_notification_layout布局文件里面,在loading方法里面系统提供了3个参数,我们使用其中的2个参数,total代表文件总大小,current代表已经下载了多少,通过int progress = (int) (current * 100/total)我们就可以计算出下载进度,然后我们通过mNotificationManager.notify(NOTIFY_ID, mNotification)去刷新Notification内容显示,然后我们在onsuccess和onFailure方法里面处理相应的情况,下载成功时我们弹出安装页面,提示用户进行安装,失败时也给出相关提示。

      下面来讲第二种实现方式,就是利用android系统的DownloadManager 去实现的,个人觉得比较方便实用,它可以检测下载速度,显示下载进度,文件大小,断点下载等强大功能,下载过程中他会自动检测网络状态,网络断开时停止下载,连接上时自动接着下载,还可以设置成只有在wifi下面才进行下载,下面直接贴出效果图和相应代码,代码里面关键代码都写了注释,比较简单。

android 下拉通知栏 安卓下拉通知栏的软件_DownloadManager_02

package com.example.download;

import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.app.DownloadManager.Request;
import android.database.Cursor;
import android.net.Uri;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;

@SuppressLint("NewApi")
public class MainActivity extends Activity  implements OnClickListener{
	
    static final String DOWNLOAD_FILE_NAME = "weishi.apk";
    private DownloadManager manager ;
    private Button downBtn1 ;
    private Button downBtn2 ;
    private long downloadId;
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        manager =(DownloadManager)getSystemService(DOWNLOAD_SERVICE);
        downBtn1 = (Button)findViewById(R.id.downBtn1);
        downBtn1.setOnClickListener(this); 
        downBtn2 = (Button)findViewById(R.id.downBtn2);
        downBtn2.setOnClickListener(this); 
    }
    
	@Override
	public void onClick(View v) {	
		switch (v.getId()) {
			case R.id.downBtn1:
				Query query = new Query();
		    	query.setFilterById(downloadId);
		    	query.setFilterByStatus(DownloadManager.STATUS_RUNNING);//正在下载   	
		    	Cursor c = manager.query(query);
		    	if(c.moveToNext()){
		    		//正在下载中,不重新下载
		    	}else{
		    		//创建下载请求
		    		DownloadManager.Request down=new DownloadManager.Request (Uri.parse("http://dldir1.qq.com/dlomg/weishi/weishi_guanwang.apk"));
		            //设置允许使用的网络类型,这里是移动网络和wifi都可以
		            down.setAllowedNetworkTypes(DownloadManager.Request.NETWORK_MOBILE|DownloadManager.Request.NETWORK_WIFI);
		            //显示在下载界面,即下载后的文件在系统下载管理里显示
		            down.setVisibleInDownloadsUi(true);
		            //设置下载标题      
		            down.setTitle("微视");
		            //显示Notification
		            down.setNotificationVisibility(Request.VISIBILITY_VISIBLE);
		            //设置下载后文件存放的位置,在SDCard/Android/data/你的应用的包名/files/目录下面
		            down.setDestinationInExternalFilesDir(this, null,DOWNLOAD_FILE_NAME);
		            //将下载请求放入队列,返回值为downloadId
		            downloadId = manager.enqueue(down);
		    	}        
				break;
	
			case R.id.downBtn2:
				 HttpConnectService hcs = new HttpConnectService();
				 hcs.connectDownLoad(this, getPackageName());
				 break;
		}
	}
}

           然后我们在AndroidManifest.xml配置文件里面去注册一个广播,监听下载完成的动作,这里不建议这Activity里面动态注册广播,因为这样activity销毁时广播会被销毁我们就无法接受到下载完成的广播了。

          

package com.example.download;

import java.io.File;

import android.annotation.SuppressLint;
import android.app.DownloadManager;
import android.app.DownloadManager.Query;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.database.Cursor;
import android.net.Uri;

@SuppressLint("NewApi")
public class DownloadCompleteReceiver extends BroadcastReceiver {
	private DownloadManager manager ;
    @Override
    public void onReceive(Context context, Intent intent) {
        manager =(DownloadManager)context.getSystemService(Context.DOWNLOAD_SERVICE);
        if(intent.getAction().equals(DownloadManager.ACTION_DOWNLOAD_COMPLETE)){
        	//通过downloadId去查询下载的文件名
        	long downloadId = intent.getLongExtra(DownloadManager.EXTRA_DOWNLOAD_ID, -1);
        	Query query = new Query();  
            query.setFilterById(downloadId);       
            Cursor myDownload = manager.query(query);  
            if (myDownload.moveToFirst()) {  
              int fileNameIdx = myDownload.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME);  
              String fileName = myDownload.getString(fileNameIdx);  
              installAPK(fileName,context);
            }
        }
    }
    
    //安装APK
  	private void installAPK(String  filePath,Context context) {
  		Intent intent = new Intent();
  		intent.setAction("android.intent.action.VIEW");
  		intent.addCategory("android.intent.category.DEFAULT");
  		intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);//广播里面操作需要加上这句,存在于一个独立的栈里
  	    intent.setDataAndType(Uri.fromFile(new File(filePath)),"application/vnd.android.package-archive");
  		context.startActivity(intent);
  	}
}


源码下载