第一步:创建一张表用来保存下载信息
public class DbHelper extends SQLiteOpenHelper { public static String TABLE = "file";//表名 public DbHelper(Context context) { super(context, "download.db", null, 1); } @Override public void onCreate(SQLiteDatabase db) { db.execSQL("create table file(fileName varchar,url varchar,length integer,finished integer)"); } @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { } }
第二步:在DbHelper.class中来写公用方法
/** * 插入一条下载信息 */ public void insertData(SQLiteDatabase db, FileInfo info) { ContentValues values = new ContentValues(); values.put("fileName", info.getFileName()); values.put("url", info.getUrl()); values.put("length", info.getLength()); values.put("finished", info.getFinished()); db.insert(TABLE, null, values); db.close(); } /** * 更新一条下载信息 */ public void updateData(SQLiteDatabase db, FileInfo info) { ContentValues values = new ContentValues(); values.put("fileName", info.getFileName()); values.put("length", info.getLength()); values.put("finished", info.getFinished()); db.update(TABLE, values, "url = ?", new String[]{info.getUrl()}); db.close(); } /** * 是否已经插入这条数据 */ public boolean isExist(SQLiteDatabase db, FileInfo info) { Cursor cursor = db.query(TABLE, null, "url = ?", new String[]{info.getUrl()}, null, null, null, null); boolean exist = cursor.moveToNext(); cursor.close(); db.close(); return exist; } /** * 查询已经存在的一条信息 */ public FileInfo queryData(SQLiteDatabase db, String url) { Cursor cursor = db.query(TABLE, null, "url = ?", new String[]{url}, null, null, null, null); FileInfo info = new FileInfo(); if (cursor != null) { while (cursor.moveToNext()) { String fileName = cursor.getString(cursor.getColumnIndex("fileName")); int length = cursor.getInt(cursor.getColumnIndex("length")); int finished = cursor.getInt(cursor.getColumnIndex("finished")); info.setStop(false); info.setFileName(fileName); info.setUrl(url); info.setLength(length); info.setFinished(finished); } cursor.close(); db.close(); } return info; }
第三步:创建FileInfo对象,一个下载任务实体类,set和get
private String fileName;//文件名 private String url;//下载地址 private int length;//文件大小 private int finished;//下载以已完成进度 private boolean isStop = false;//是否暂停下载 private boolean isDownLoading = false;//是否正在下载
第四步:创建DownLoaderManger来管理下载任务,包括添加下载任务、开始下载、暂停下载、重新下载
public class DownLoaderManger { public static String FILE_PATH = Environment.getExternalStorageDirectory() + "/cjy"; private DbHelper helper;//数据库帮助类 private SQLiteDatabase db; private OnProgressListener listener;//进度回调监听 private Map<String, FileInfo> map = new HashMap<>();//保存正在下载的任务信息 private static DownLoaderManger manger; private DownLoaderManger(DbHelper helper, OnProgressListener listener) { this.helper = helper; this.listener = listener; db = helper.getReadableDatabase(); } /** * 单例模式 * * @param helper 数据库帮助类 * @param listener 下载进度回调接口 * @return */ public static synchronized DownLoaderManger getInstance(DbHelper helper, OnProgressListener listener) { if (manger == null) { synchronized (DownLoaderManger.class) { if (manger == null) { manger = new DownLoaderManger(helper, listener); } } } return manger; } /** * 开始下载任务 */ public void start(String url) { db = helper.getReadableDatabase(); FileInfo info = helper.queryData(db, url); map.put(url, info); //开始任务下载 new DownLoadTask(map.get(url), helper, listener).start(); } /** * 停止下载任务 */ public void stop(String url) { map.get(url).setStop(true); } /** * 重新下载任务 */ public void restart(String url) { stop(url); try { File file = new File(FILE_PATH, map.get(url).getFileName()); if (file.exists()) { file.delete(); } Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } db = helper.getWritableDatabase(); helper.resetData(db, url); start(url); } /** * 获取当前任务状态 */ public boolean getCurrentState(String url) { return map.get(url).isDownLoading(); } /** * 添加下载任务 * * @param info 下载文件信息 */ public void addTask(FileInfo info) { //判断数据库是否已经存在这条下载信息 if (!helper.isExist(db, info)) { db = helper.getWritableDatabase(); helper.insertData(db, info); map.put(info.getUrl(), info); } else { //从数据库获取最新的下载信息 db = helper.getReadableDatabase(); FileInfo o = helper.queryData(db, info.getUrl()); if (!map.containsKey(info.getUrl())) { map.put(info.getUrl(), o); } } } }
第五步:OnProgressListenter接口
public interface OnProgressListener { void updateProgress(int max, int progress, String path); }
第六步:重点---下载线程
/** * 下载文件线程 * 从服务器获取需要下载的文件大小 */ public class DownLoadTask extends Thread { private FileInfo info; private SQLiteDatabase db; private DbHelper helper;//数据库帮助类 private int finished = 0;//当前已下载完成的进度 private OnProgressListener listener;//进度回调监听 public DownLoadTask(FileInfo info, DbHelper helper, OnProgressListener listener) { this.info = info; this.helper = helper; this.db = helper.getReadableDatabase(); this.listener = listener; info.setDownLoading(true); } @Override public void run() { getLength(); HttpURLConnection connection = null; RandomAccessFile rwd = null; try { URL url = new URL(info.getUrl()); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(3000); //从上次下载完成的地方下载 int start = info.getFinished(); //设置下载位置(从服务器上取要下载文件的某一段) connection.setRequestProperty("Range", "bytes=" + start + "-" + info.getLength());//设置下载范围 //设置文件写入位置 File file = new File(DownLoaderManger.FILE_PATH, info.getFileName()); rwd = new RandomAccessFile(file, "rwd"); //从文件的某一位置开始写入 rwd.seek(start); finished += info.getFinished(); if (connection.getResponseCode() == 206) {//文件部分下载,返回码为206 InputStream is = connection.getInputStream(); byte[] buffer = new byte[1024 * 4]; int len; while ((len = is.read(buffer)) != -1) { //写入文件 rwd.write(buffer, 0, len); finished += len; info.setFinished(finished); //更新界面显示 Message msg = new Message(); msg.what = 0x123; msg.arg1 = info.getLength(); msg.arg2 = info.getFinished(); handler.sendMessage(msg); //停止下载 if (info.isStop()) { info.setDownLoading(false); //保存此次下载的进度 helper.updateData(db, info); db.close(); return; } } //下载完成 info.setDownLoading(false); helper.updateData(db, info); db.close(); } } catch (Exception e) { e.printStackTrace(); } finally { if (connection != null) { connection.disconnect(); } try { if (rwd != null) { rwd.close(); } } catch (IOException e) { e.printStackTrace(); } } } /** * 首先开启一个线程去获取要下载文件的大小(长度) */ private void getLength() { HttpURLConnection connection = null; try { //连接网络 URL url = new URL(info.getUrl()); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setConnectTimeout(3000); int length = -1; if (connection.getResponseCode() == 200) {//网络连接成功 //获得文件长度 length = connection.getContentLength(); } if (length <= 0) { //连接失败 return; } //创建文件保存路径 File dir = new File(DownLoaderManger.FILE_PATH); if (!dir.exists()) { dir.mkdirs(); } info.setLength(length); } catch (Exception e) { e.printStackTrace(); } finally { //释放资源 try { if (connection != null) { connection.disconnect(); } } catch (Exception e) { e.printStackTrace(); } } } /** * 更新进度 */ private Handler handler = new Handler() { @Override public void handleMessage(Message msg) { switch (msg.what) { case 0x123: if (listener != null) { listener.updateProgress(msg.arg1, msg.arg2,DownLoaderManger.FILE_PATH); } break; } } }; }
第七步:使用,通知栏的提示及apk更新安装
public class MainActivity extends AppCompatActivity implements OnProgressListener { private NotificationManager notificationManager; private NotificationCompat.Builder builder; private NumberProgressBar pb;//进度条 private DownLoaderManger downLoader = null; private FileInfo info; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); pb = (NumberProgressBar) findViewById(R.id.pb); final Button start = (Button) findViewById(R.id.start);//开始下载 final Button restart = (Button) findViewById(R.id.restart);//重新下载 final DbHelper helper = new DbHelper(this); downLoader = DownLoaderManger.getInstance(helper, this); info = new FileInfo("chuanglifeng.apk", "http://116.62.162.56:80/pjriver/chuanglifeng/app-release.apk"); downLoader.addTask(info); start.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { if (downLoader.getCurrentState(info.getUrl())) { initNofication("暂停下载","创利丰"); downLoader.stop(info.getUrl()); start.setText("开始下载"); } else { initNofication("开始下载","创利丰"); downLoader.start(info.getUrl()); start.setText("暂停下载"); } } }); restart.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { initNofication("重新下载","创利丰"); downLoader.restart(info.getUrl()); start.setText("暂停下载"); } }); } @Override public void updateProgress(final int max, final int progress, String path) { pb.setMax(max); pb.setProgress(progress); int percent = (int) (div(progress,max,2)*100); builder.setProgress(max,progress,false); notificationManager.notify(0x3,builder.build()); //下载进度提示 builder.setContentText("下载"+percent+"%"); if(percent==100) { //下载完成后点击安装 Intent it = new Intent(Intent.ACTION_VIEW); it.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK); it.setDataAndType(Uri.fromFile(new File(path,info.getFileName())), "application/vnd.android.package-archive"); builder.setContentText("点击安装") .setContentInfo("下载完成") .setDefaults(Notification.DEFAULT_SOUND) .setOngoing(false); startActivity(it); notificationManager.notify(0x3, builder.build()); } } private void initNofication(String cticker, String title) { notificationManager = (NotificationManager) getSystemService(Activity.NOTIFICATION_SERVICE); builder = new NotificationCompat.Builder(this); builder.setSmallIcon(R.mipmap.logo) .setTicker(cticker) .setContentInfo("下载中...") .setContentTitle(title) .setOngoing(true);//设置为不可清除模式 } public static double div(double v1, double v2, int scale) { if (scale < 0) { throw new IllegalArgumentException( "The scale must be a positive integer or zero"); } BigDecimal b1 = new BigDecimal(Double.toString(v1)); BigDecimal b2 = new BigDecimal(Double.toString(v2)); return b1.divide(b2, scale, BigDecimal.ROUND_HALF_UP).doubleValue(); } }
Dome地址:http://download.csdn.net/download/qq_39735504/10271919