1、沒有實現服務器端,下載地址為網上的一個下載鏈接。
2、網絡開發不要忘記在配置文件中添加訪問網絡的權限
<uses-permission android:name="android.permission.INTERNET"/>
3、網絡請求、處理不能在主線程中進行,一定要在子線程中進行。因為網絡請求一般有1~3秒左右的延時,在主線程中進行造成主線程的停頓,對用戶體驗來說是致命的。(主線程應該只進行UI繪制,像網絡請求、資源下載、各種耗時操作都應該放到子線程中)。
4、斷點下載返回碼為206,而不是200,不同的網站可能有區別,大家注意一下,斷點請求失敗的返回碼為416。
5、
/** * 斷點下載 */ public class MoreTimesActivity extends Activity { private TextView mTvMsg; private String result = ""; private long start = 0; private long stop = 1024 * 1024; private int times = 0; // 根據文件大小自己設的, @Override protected void onCreate(Bundle savedInstanceState) { // TODO Auto-generated method stub super.onCreate(savedInstanceState); requestWindowFeature(Window.FEATURE_NO_TITLE); setContentView(R.layout.activity_times_download); initView(); } private void initView(){ mTvMsg = (TextView) findViewById(R.id.tv_msg); new Thread(moreThread).start(); } private Thread moreThread = new Thread(){ public void run() { HttpURLConnection connection = null; try { URL url = new URL("http://ftp-apk.pconline.com.cn/ef19af4e28462271af1117efaf868bc2/pub/download/201010/renshengrili_v4.0.04.05.apk"); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setDoInput(true); // 設置開始下載的位置和結束下載的位置,單位為字節 connection.setRequestProperty("Range", "bytes=" + start + "-" + stop); String path = Environment.getExternalStorageDirectory().getPath() + "/aaaaa/baidu_map.apk"; // 斷點下載使用的文件對象RandomAccessFile RandomAccessFile access = new RandomAccessFile(path, "rw"); // 移動指針到開始位置 access.seek(start); InputStream is = null; Log.e("ADB----", connection.getResponseCode() + ""); if(connection.getResponseCode() == 206){ is = connection.getInputStream(); int count = 0; byte[] buffer = new byte[1024]; while((count = is.read(buffer)) != -1){ access.write(buffer, 0, count); } } if(access != null){ access.close(); } if(is != null){ is.close(); } start = stop + 1; stop += 1024*1024; // 每次下載1M Message msg = Message.obtain(); msg.what = 0; result += "文件" + times + "下載成功" + ":" + start + "---" + stop + "\n"; moreHandler.sendMessage(msg); } catch (MalformedURLException e) { e.printStackTrace(); } catch (IOException e) { e.printStackTrace(); } finally { if(connection != null){ connection.disconnect(); } } }; }; private Handler moreHandler = new Handler(){ public void handleMessage(android.os.Message msg) { if(msg.what == 0 && result!=null){ if(times >= 10){ Message msg1 = Message.obtain(); msg1.what = 1; moreHandler.sendMessage(msg1); }else{ new Thread(moreThread).start(); times += 1; } mTvMsg.setText(result); }else if(msg.what == 1){ mTvMsg.setText(result); } }; }; }
6、斷點下載重要的是實現一:設置斷點請求setRequestProperty("Range", "bytes=0-1024");
二:通過RandomAccessFile來將下載的字節插入到指定的位置。
7、對於輸出流的三個方法的對比:
os.write(byte[] buffer); 可能錯誤,因為你每次讀取的數據小於等於1024,但你每次寫入的數據仍然是1024, 對圖片有一定影響,對安裝包絕對是致命的影響。
os.write(int oneByte); 效率低
os.write(byte[] buffer, int byteOffset, int byteCount); 效率高,和第二個方法相比有一個數量級的差別(主觀上看,有興趣的可以測幾下)。
8、如何實現多線程斷點下載這里不再介紹,大家可以自己思考一下。
9、參考博文: http://blog.sina.com.cn/s/blog_413580c20100wmr8.html