第一步:創建一張表用來保存下載信息
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