最近在研究项目更新下载的方法,通过启动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