先贴图 开始下载
暂停下载
杀进程或关闭activity后,再次启动可正常下载,不会做动态图,这里就不贴图了
下载完成后,红框标记即为下载后文件
MainActivit里onCreate()里代码如下,主要做一些变量和UI的初始化工具:
public void onCreate(Bundle icicle) {
super.onCreate(icicle);
setContentView(R.layout.activity_main);
pbBar = (ProgressBar) findViewById(R.id.progressBar);
tv = (TextView) findViewById(R.id.textView);
bt_start= (Button) findViewById(R.id.button);
// 启动时对文件做处理
File file = new File(filePath);
//查询数据库,更新UI
dao = new DownInfoDao(this);
DownInfo info = dao.query(path);
Log.i("guoguo", info+"=info");
if (info == null) {
isFinished=false;
if (file.exists()) {
file.delete();
Log.i("guoguo", "删除文件");
}
} else {
fileSize=info.getTotal();
downlen = info.getDownLen();
if (fileSize>0) {
progress = (int)(((float)downlen /(float) fileSize)* 100) ;
if (downlen==fileSize) {
isFinished=true;
}
}
if (!file.exists()) {
dao.delete(path);
}
pbBar.setProgress(progress);
tv.setText(progress + "%");
}
//启动服务
Intent it = new Intent(this, DownloadService.class);
bindService(it, conn, Context.BIND_AUTO_CREATE);
startService(it);
}
更新回调及handler:
private ICallbackResult callback = new ICallbackResult() {
@Override
public void OnBackResult(int total, int downlen) {
// TODO Auto-generated method stub
//接收回调数据
Log.i("guoguo", "downlen="+downlen+",total="+total);
int pro = (int)(((float)downlen /(float) total)* 100) ;
Message msg = new Message();
msg.what = 1;
msg.obj = pro;
handler.sendMessage(msg);
}
};
//更新UI
Handler handler=new Handler(){
public void handleMessage(Message msg) {
switch (msg.what) {
case 1:
int progress=(Integer) msg.obj;
pbBar.setProgress(progress);
if (progress==100) {
isFinished=true;
}
tv.setText(progress+"%");
break;
default:
break;
}
};
};
核心代码来了,主要工作在service里完成,以下是文件的下载部分,:
try {
URL url = new URL(path);
HttpURLConnection conn = (HttpURLConnection) url
.openConnection();
DownInfo info = dao.query(path);
//若查询不到数据,刚建立 一个DownInfo对象
if (info==null) {
info=new DownInfo(path, 0, fileSize);
dao.insert(info);
}else {
//数据库里存在,更新下载位置
downlen=info.getDownLen();
fileSize=info.getTotal();
//设置从downlen位置开始读取
conn.setRequestProperty("Range", "bytes=" + downlen + "-" + fileSize);
}
conn.connect();
int length = conn.getContentLength();
if (fileSize==0) {
fileSize=length;
}
InputStream is = conn.getInputStream();
File file = new File(savePath);
if (!file.exists()) {
file.mkdirs();
}
RandomAccessFile apkFile = new RandomAccessFile(saveFileName,"rwd");
apkFile.seek(downlen); //文件定位到文件末尾
//设置缓存
byte buf[] = new byte[1024*1024];
//开始下载文件
do {
//对dao做处理,来实现暂停功能
while (isPause) {
synchronized (dao) {
try {
dao.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//读取流
int numread = is.read(buf);
//写入文件
if (numread > 0) {
downlen += numread;
apkFile.write(buf, 0, numread);
}else {
//下载完成
Message msg = mHandler.obtainMessage();
msg.what = 1;
mHandler.sendEmptyMessage(0);
canceled = true;
break;
}
} while (!canceled);//
apkFile.close();
is.close();
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
现在为文件的更新部分
//发起网络请求
url = new URL(path);
URLConnection conn = url.openConnection();
fileSize = conn.getContentLength();
if (downLoadThread == null || !downLoadThread.isAlive()) {
downLoadThread = new Thread(mdownApkRunnable);
downLoadThread.start();
}
DownInfo info = dao.query(path);
if (info != null) {
downlen = info.getDownLen();
// if (fileSize==-1) {
fileSize=info.getTotal();
// }
}
while (!flag) {
while (isPause) {
synchronized (dao) {
try {
dao.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
//下载完成或暂停时,停止 更新
if (downlen==fileSize||isPause) {
flag=true;
}
//存入数据库
dao.update(new DownInfo(path, downlen,fileSize));
//更新UI
callback.OnBackResult(fileSize,downlen);
//设置为0.2秒更新一次
Thread.sleep(200);
}
下载和更新工作如果在同一个线程里处理里下载速度会非常慢,所以我把两个工作分开来处理,这样能保证下载速度 。