最近在研究项目更新下载的方法,通过启动Service进行后台下载,并通过Notification做实时显示,分析如下:
关联文件结构图:
act.xml布局:
<FrameLayout 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"
tools:context=".MainActivity" >
<LinearLayout
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1000" />
<Button
android:id="@+id/but_down"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="下载" />
</LinearLayout>
</FrameLayout>
MainActivity:
package com.example.test20150104;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends Activity implements
android.view.View.OnClickListener {
private Button but_down = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act);
but_down = (Button) findViewById(R.id.but_down);
but_down.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if (R.id.but_down == v.getId()) {
Downloader loader = new Downloader(this);
if (!loader.isLoading())
loader.load();
else
Toast.makeText(this, "正在后台下载中...", Toast.LENGTH_SHORT).show();
}
}
}
Downloader.java
package com.example.test20150104;
import android.content.Context;
import android.content.Intent;
import android.os.Handler;
/**
* 可拓展断点续传
*
* @author yayalvtu 2014-12-30 上午11:02:09
*/
public class Downloader {
private Context context;
/**
* 判断是否还在下载
*/
private static boolean loading;
public static Handler handler=new Handler(){
public void handleMessage(android.os.Message msg) {
loading=false;
};
};
public Downloader(Context context) {
this.context = context;
}
public void load() {
loading=true;
Intent intent = new Intent(context, DownLoadService.class);
context.startService(intent);
}
public boolean isLoading() {
return loading;
}
}
DownLoadService.java
package com.example.test20150104;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.net.URL;
import java.net.URLConnection;
import java.text.SimpleDateFormat;
import java.util.Date;
import android.annotation.SuppressLint;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.net.Uri;
import android.os.AsyncTask;
import android.os.IBinder;
import android.support.v4.app.NotificationCompat;
public class DownLoadService extends Service {
private NotificationManager manager = null;
private NotificationCompat.Builder builder;
/**
* 下载路径
*/
private String path;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@SuppressLint("SimpleDateFormat")
@Override
public void onCreate() {
super.onCreate();
manager = (NotificationManager) this
.getSystemService(NOTIFICATION_SERVICE);
SimpleDateFormat df = new SimpleDateFormat("yyyyMMddHHmmss");
path = "http://www.yylvtu.com/app/YaYaLvTu01.apk?ver="
+ df.format(new Date());//下载地址
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
new DownloadImageTask().execute(path);
return super.onStartCommand(intent, flags, startId);
}
private class DownloadImageTask extends AsyncTask<String, Integer, Bitmap> {
@Override
protected void onPostExecute(Bitmap result) {//下载后
if (result != null) {
builder.setProgress(0, 0, true);
builder.setContentText("下载完成");
Notification no = builder.build();
no.flags = Notification.FLAG_AUTO_CANCEL;
no.defaults = Notification.DEFAULT_SOUND;
manager.notify(1, no);
} else {
builder.setProgress(0, 0, true);
builder.setContentText("下载失败..");
manager.notify(1, builder.build());
}
Downloader.handler.sendEmptyMessage(0);//通知下载已经停止
stopSelf();//关闭Service
}
//文件存放位置
private String filePath = "/storage/emulated/0/yylt/downloads/yylvtu.apk";
@Override
protected Bitmap doInBackground(String... params) {
String path = params[0];
try {
URL u = new URL(path);
URLConnection conn = u.openConnection();
InputStream is = conn.getInputStream();
long total_length = conn.getContentLength();
FileOutputStream fos = new FileOutputStream(filePath);
int len = 0;
byte[] buf = new byte[1024];
int current_len = 0;
int progress = 0;// 当前下载进度
int temp = 0;
while ((len = is.read(buf)) != -1) {
current_len += len;
fos.write(buf, 0, len);
if ((current_len - temp) > 204800) {//间断性的更新进度条,否则会因更新过于频繁而导致进度条不刷新
temp = current_len;
progress = (int) ((current_len / (float) total_length) * 100);
this.publishProgress(progress);
}
}
is.close();
Resources res = getResources();
Bitmap bmp = BitmapFactory.decodeResource(res,
R.drawable.ic_launcher);//这里只是一个标志,实际意义为下载完成 中间无故障
return bmp;
} catch (Exception e) {
e.printStackTrace();
}
return null;
}
@Override
protected void onProgressUpdate(Integer... values) {//更新进度条
builder.setContentText("下载进度:" + values[0] + "%");
builder.setProgress(100, values[0], false);
Notification no = builder.build();
no.flags = Notification.FLAG_NO_CLEAR;
manager.notify(1, no);
no = null;
}
@Override
protected void onPreExecute() {//现在前的准备
builder = new NotificationCompat.Builder(DownLoadService.this);
builder.setSmallIcon(R.drawable.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(),
R.drawable.ic_launcher));
builder.setContentTitle("apk文件");
Intent notificationIntent1 = new Intent(Intent.ACTION_VIEW);
notificationIntent1.setDataAndType(
Uri.fromFile(new File(filePath)),
"application/vnd.android.package-archive");
PendingIntent pi = PendingIntent.getActivity(DownLoadService.this,
0, notificationIntent1, PendingIntent.FLAG_ONE_SHOT);
builder.setContentIntent(pi);
builder.setProgress(100, 0, false);
builder.setTicker("文件开始下载...");
Notification no = builder.build();
no.flags |= Notification.FLAG_AUTO_CANCEL;
manager.notify(1, no);
}
}
}
权限配置:
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<!-- 版本更新 -->
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS" />
<uses-permission android:name="android.permission.INSTALL_PACKAGES" />
资源链接:http://download.csdn.net/detail/atsince/8324281