您好,登錄后才能下訂單哦!
怎么在Android應用中實現一個網絡多線程斷點續傳下載功能?很多新手對此不是很清楚,為了幫助大家解決這個難題,下面小編將為大家詳細講解,有這方面需求的人可以來學習下,希望你能有所收獲。
原理
多線程下載的原理就是將要下載的文件分成若干份,其中每份都使用一個單獨的線程進行下載,這樣對于文件的下載速度自然就提高了許多。
既然要分成若干部分分工下載,自然要知道各個線程自己要下載的起始位置,與要下載的大小。所以我們要解決線程的分配與各個線程定位到下載的位置。
封裝
對于多線程下載我們可以將其封裝到一個工具類中DownUtil,向其中傳入下載的鏈接、文件存儲路徑、需要下載的線程數
分配線程
這里通過HttpURLConnection進行網絡請求下載,通過getContentLength()方法獲取下載文件的總大小,再對其平均分配各個線程需要下載的大小。這樣就確定了下載的大小,下面就是定位到各個線程的開始位置進行下載,這里可以使用RandomAccessFile來追蹤定位到要下載的位置,它的seek()方法可以進行定位。
線程下載
下面就是各個線程的下載DownThread,上面已經得到了各個線程要下載的初始位置,所以可以通過獲取網絡請求的輸入流InputStream,通過skip()方法跳躍到指定位置進行讀取數據,再寫入到RandomAccessFile文件中
一、 編寫基本的UI,三個TextView,分別顯示文件名、下載進度和下載速度,一個ProgressBar。二個Button,分別用于開始下載、暫停下載和取消下載。
<?xml version="1.0" encoding="utf-8"?> <LinearLayout 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" android:orientation="vertical" android:paddingBottom="@dimen/activity_vertical_margin" android:paddingLeft="@dimen/activity_horizontal_margin" android:paddingRight="@dimen/activity_horizontal_margin" android:paddingTop="@dimen/activity_vertical_margin" tools:context="com.example.linux.continuedownload.MainActivity"> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <TextView android:id="@+id/textView" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_marginLeft="80dp" android:id="@+id/progress" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <TextView android:layout_marginLeft="80dp" android:id="@+id/speed" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <ProgressBar android:visibility="invisible" android:id="@+id/progressBar" android:layout_width="match_parent" android:layout_height="wrap_content" /> <LinearLayout android:layout_width="match_parent" android:layout_height="wrap_content"> <Button android:id="@+id/start" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="開始下載" /> <Button android:layout_marginLeft="20dp" android:id="@+id/stop" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="暫停下載" /> <Button android:layout_marginLeft="20dp" android:id="@+id/cancel" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="取消下載" /> </LinearLayout> </LinearLayout>
在onCreate方法中綁定開始下載按鈕事件:點擊start按鈕,設置進度條可見,并且設置start的Action,啟動服務。
startButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { textView.setText(fileInfo.getFileName()); progressBar.setVisibility(View.VISIBLE); // 通過Intent傳遞參數給service Intent intent = new Intent(MainActivity.this, DownloadService.class); intent.setAction(DownloadService.ACTION_START); intent.putExtra("fileInfo", fileInfo); startService(intent); } });
在onCreate方法中綁定暫停下載按鈕事件:點擊stop按鈕,設置stop的Action,啟動服務。
stopButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 通過Intent傳遞參數給service Intent intent = new Intent(MainActivity.this, DownloadService.class); intent.setAction(DownloadService.ACTION_STOP); intent.putExtra("fileInfo", fileInfo); startService(intent); } });
在onCreate方法中綁定取消下載按鈕事件:點擊cancel按鈕,設置cancel的Action,啟動服務,之后更新UI。
cancelButton.setOnClickListener(new View.OnClickListener() { @Override public void onClick(View v) { // 通過Intent傳遞參數給service Intent intent = new Intent(MainActivity.this, DownloadService.class); intent.setAction(DownloadService.ACTION_CANCEL); intent.putExtra("fileInfo", fileInfo); startService(intent); // 更新textView和progressBar的顯示UI textView.setText(""); progressBar.setVisibility(View.INVISIBLE); progressView.setText(""); speedView.setText(""); } });
注冊廣播,用于Service向Activity傳遞一些下載進度信息:
// 靜態注冊廣播 IntentFilter intentFilter = new IntentFilter(); intentFilter.addAction(DownloadService.ACTION_UPDATE); registerReceiver(broadcastReceiver, intentFilter); /** * 更新UI */ BroadcastReceiver broadcastReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { if (DownloadService.ACTION_UPDATE.equals(intent.getAction())) { int finished = intent.getIntExtra("finished", 0); int speed = intent.getIntExtra("speed", 0); Log.i("Main", finished + ""); progressBar.setProgress(finished); progressView.setText(finished + "%"); speedView.setText(speed + "KB/s"); } } };
三、 在AndroidManifest.xm文件中聲明權限,定義服務
<service android:name="com.huhx.services.DownloadService" android:exported="true" /> <uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
總結
多線程的關鍵就是分配好需要下載的進程,定位進程下載的準確位置,獲取輸入流讀取數據,同時寫入到文件的相應位置。可以借助RandomAccessFile來進行定位。
當然也并非開的線程數越多下載的速度也就越快,因為線程越多對于程序處理這些線程也是一種負擔,過多的話反而會降低下載的速度,所以要合理運用。
看完上述內容是否對您有幫助呢?如果還想對相關知識有進一步的了解或閱讀更多相關文章,請關注億速云行業資訊頻道,感謝您對億速云的支持。
免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。