最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

android實現(xiàn)多線程斷點續(xù)傳功能

 更新時間:2022年07月27日 10:00:05   作者:c_bulrush  
這篇文章主要為大家詳細介紹了android實現(xiàn)多線程斷點續(xù)傳功能,具有一定的參考價值,感興趣的小伙伴們可以參考一下

本文實例為大家分享了android實現(xiàn)多線程斷點續(xù)傳的具體代碼,供大家參考,具體內(nèi)容如下

布局:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
 xmlns:tools="http://schemas.android.com/tools"
 android:id="@+id/activity_main"
 android:layout_width="match_parent"
 android:layout_height="match_parent"
 android:paddingBottom="@dimen/activity_vertical_margin"
 android:paddingLeft="@dimen/activity_horizontal_margin"
 android:paddingRight="@dimen/activity_horizontal_margin"
 android:paddingTop="@dimen/activity_vertical_margin">


 <TextView
  android:text="下載進度"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignParentTop="true"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:layout_marginTop="15dp"
  android:id="@+id/tv_progress" />

 <Button
  android:text="下載"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_below="@+id/firstBar"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:layout_marginTop="29dp"
  android:id="@+id/bt" />

 <Button
  android:text="暫停"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignTop="@+id/bt"
  android:layout_toRightOf="@+id/bt"
  android:layout_toEndOf="@+id/bt"
  android:layout_marginLeft="15dp"
  android:layout_marginStart="15dp"
  android:id="@+id/bt_pause" />

 <Button
  android:text="繼續(xù)"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:layout_alignBottom="@+id/bt_pause"
  android:layout_toRightOf="@+id/bt_pause"
  android:layout_toEndOf="@+id/bt_pause"
  android:layout_marginLeft="18dp"
  android:layout_marginStart="18dp"
  android:id="@+id/bt_start" />

 <ProgressBar
  android:id="@+id/firstBar"
  android:layout_width="fill_parent"
  android:layout_height="wrap_content"
  style="@android:style/Widget.ProgressBar.Horizontal"
  android:layout_below="@+id/tv_progress"
  android:layout_alignParentLeft="true"
  android:layout_alignParentStart="true"
  android:layout_marginTop="21dp" />
</RelativeLayout>

MainActivity :

import android.os.Bundle;
import android.os.Environment;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.ProgressBar;
import android.widget.TextView;
import android.widget.Toast;

import butterknife.BindView;
import butterknife.ButterKnife;
import butterknife.OnClick;


public class MainActivity extends AppCompatActivity {
 @BindView(R.id.firstBar)
 ProgressBar firstBar;
 @BindView(R.id.tv_progress)
 TextView tvprogress;
 @BindView(R.id.bt)
 Button bt;
 @BindView(R.id.bt_pause)
 Button btPause;
 @BindView(R.id.bt_start)
 Button btStart;
 //下載地址
 private String loadUrl = "http://mirror.aarnet.edu.au/pub/TED-talks/911Mothers_2010W-480p.mp4";
 //文件緩存路徑
 private String filePath = Environment.getExternalStorageDirectory() + "/" + "911Mothers.mp4";
 DownLoadFile downLoadFile;

 @Override
 protected void onCreate(Bundle savedInstanceState) {
  super.onCreate(savedInstanceState);
  setContentView(R.layout.activity_main);
  ButterKnife.bind(this);
  downLoadFile = new DownLoadFile(this, loadUrl, filePath, 3);
  downLoadFile.setOnDownLoadListener(new DownLoadFile.DownLoadListener() {
   @Override
   public void getProgress(int progress) {
    tvprogress.setText("當前進度 :" + progress + " %");
    //設置進度條進度
    firstBar.setProgress(progress);
    if (progress==100){
     Toast.makeText(MainActivity.this, "下載完成", Toast.LENGTH_SHORT).show();
    }
   }

   @Override
   public void onComplete() {
    Toast.makeText(MainActivity.this, "下載完成", Toast.LENGTH_SHORT).show();
   }

   @Override
   public void onFailure() {
    Toast.makeText(MainActivity.this, "下載失敗", Toast.LENGTH_SHORT).show();
   }
  });



 }

 /*
 * 點擊事件
 * */
 @OnClick({R.id.bt, R.id.bt_pause, R.id.bt_start})
 public void onViewClicked(View view) {
  switch (view.getId()) {
   case R.id.bt:
    downLoadFile.downLoad();
    break;
   case R.id.bt_pause:
    downLoadFile.onPause();
    break;
   case R.id.bt_start:
    downLoadFile.onStart();
    break;
  }
 }

 @Override
 protected void onDestroy() {
  downLoadFile.onDestroy();
  super.onDestroy();
 }
}

DownLoadFile:

import android.content.Context;
import android.content.SharedPreferences;
import android.os.Handler;
import android.os.Message;

import java.io.InputStream;
import java.io.RandomAccessFile;
import java.net.HttpURLConnection;
import java.net.URL;

public class DownLoadFile {
 private static final String SP_NAME = "download_file";
 private static final String CURR_LENGTH = "curr_length";
 private static final int DEFAULT_THREAD_COUNT = 4;//默認下載線程數(shù)

 //以下為線程狀態(tài)
 private static final String DOWNLOAD_INIT = "1"; //初始化
 private static final String DOWNLOAD_ING = "2";  //正在下載
 private static final String DOWNLOAD_PAUSE = "3"; //暫停
 private Context mContext;
 private String loadUrl;//網(wǎng)絡獲取的url
 private String filePath;//下載到本地的path
 private int threadCount = DEFAULT_THREAD_COUNT;//下載線程數(shù)
 private int fileLength;//文件總大小
 //使用volatile防止多線程不安全
 private volatile int currLength;//當前總共下載的大小
 private volatile int runningThreadCount;//正在運行的線程數(shù)
 private Thread[] mThreads;
 private String stateDownload = DOWNLOAD_INIT;//當前線程狀態(tài)

 //下載進度監(jiān)聽
 private DownLoadListener mDownLoadListener;

 public void setOnDownLoadListener(DownLoadListener mDownLoadListener) {
  this.mDownLoadListener = mDownLoadListener;
 }

 //定義一個下載監(jiān)聽的接口
 public interface DownLoadListener {
  //返回當前下載進度的百分比
  void getProgress(int progress);
  //下載完成
  void onComplete();
  //下載失敗
  void onFailure();
 }

 /*
 * 四種有參構造
 * */
 public DownLoadFile(Context mContext, String loadUrl, String filePath) {
  this(mContext, loadUrl, filePath, DEFAULT_THREAD_COUNT, null);
 }

 public DownLoadFile(Context mContext, String loadUrl, String filePath, DownLoadListener mDownLoadListener) {
  this(mContext, loadUrl, filePath, DEFAULT_THREAD_COUNT, mDownLoadListener);
 }

 public DownLoadFile(Context mContext, String loadUrl, String filePath, int threadCount) {
  this(mContext, loadUrl, filePath, threadCount, null);
 }

 public DownLoadFile(Context mContext, String loadUrl, String filePath, int threadCount, DownLoadListener mDownLoadListener) {
  this.mContext = mContext;
  this.loadUrl = loadUrl;
  this.filePath = filePath;
  this.threadCount = threadCount;
  runningThreadCount = 0;
  this.mDownLoadListener = mDownLoadListener;
 }

 /**
  * 開始下載
  */
 protected void downLoad() {
  //在線程中運行,防止anr
  new Thread(new Runnable() {
   @Override
   public void run() {
    try {
     //初始化數(shù)據(jù)
     if (mThreads == null)
      mThreads = new Thread[threadCount];

     //建立連接請求
     URL url = new URL(loadUrl);
     HttpURLConnection conn = (HttpURLConnection) url.openConnection();
     conn.setConnectTimeout(5000);
     conn.setRequestMethod("GET");
     int code = conn.getResponseCode();//獲取返回碼
     if (code == 200) {//請求成功,根據(jù)文件大小開始分多線程下載
      fileLength = conn.getContentLength();
      //根據(jù)文件大小,先創(chuàng)建一個空文件
      //“r“——以只讀方式打開。調(diào)用結果對象的任何 write 方法都將導致拋出 IOException。
      //“rw“——打開以便讀取和寫入。如果該文件尚不存在,則嘗試創(chuàng)建該文件。
      //“rws“—— 打開以便讀取和寫入,對于 “rw”,還要求對文件的內(nèi)容或元數(shù)據(jù)的每個更新都同步寫入到底層存儲設備。
      //“rwd“——打開以便讀取和寫入,對于 “rw”,還要求對文件內(nèi)容的每個更新都同步寫入到底層存儲設備。
      RandomAccessFile raf = new RandomAccessFile(filePath, "rwd");
      raf.setLength(fileLength);
      raf.close();
      //計算各個線程下載的數(shù)據(jù)段
      int blockLength = fileLength / threadCount;

      SharedPreferences sp = mContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
      //獲取上次取消下載的進度,若沒有則返回0
      currLength = sp.getInt(CURR_LENGTH, 0);
      for (int i = 0; i < threadCount; i++) {
       //開始位置,獲取上次取消下載的進度,默認返回i*blockLength,即第i個線程開始下載的位置
       int startPosition = sp.getInt(SP_NAME + (i + 1), i * blockLength);
       //結束位置,-1是為了防止上一個線程和下一個線程重復下載銜接處數(shù)據(jù)
       int endPosition = (i + 1) * blockLength - 1;
       //將最后一個線程結束位置擴大,防止文件下載不完全,大了不影響,小了文件失效
       if ((i + 1) == threadCount)
        endPosition = endPosition * 2;

       mThreads[i] = new DownThread(i + 1, startPosition, endPosition);
       mThreads[i].start();
      }
     } else {
      handler.sendEmptyMessage(FAILURE);
     }
    } catch (Exception e) {
     e.printStackTrace();
     handler.sendEmptyMessage(FAILURE);
    }
   }
  }).start();
 }

 /**
  * 取消下載
  */
 protected void cancel() {
  if (mThreads != null) {
   //若線程處于等待狀態(tài),則while循環(huán)處于阻塞狀態(tài),無法跳出循環(huán),必須先喚醒線程,才能執(zhí)行取消任務
   if (stateDownload.equals(DOWNLOAD_PAUSE))
    onStart();
   for (Thread dt : mThreads) {
    ((DownThread) dt).cancel();
   }
  }
 }

 /**
  * 暫停下載
  */
 protected void onPause() {
  if (mThreads != null)
   stateDownload = DOWNLOAD_PAUSE;
 }

 /**
  * 繼續(xù)下載
  */
 protected void onStart() {
  if (mThreads != null)
   synchronized (DOWNLOAD_PAUSE) {
    stateDownload = DOWNLOAD_ING;
    DOWNLOAD_PAUSE.notifyAll();
   }
 }

 protected void onDestroy() {
  if (mThreads != null)
   mThreads = null;
 }

 private class DownThread extends Thread {

  private boolean isGoOn = true;//是否繼續(xù)下載
  private int threadId;
  private int startPosition;//開始下載點
  private int endPosition;//結束下載點
  private int currPosition;//當前線程的下載進度

  private DownThread(int threadId, int startPosition, int endPosition) {
   this.threadId = threadId;
   this.startPosition = startPosition;
   currPosition = startPosition;
   this.endPosition = endPosition;
   runningThreadCount++;
  }

  @Override
  public void run() {
   SharedPreferences sp = mContext.getSharedPreferences(SP_NAME, Context.MODE_PRIVATE);
   try {
    URL url = new URL(loadUrl);
    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
    conn.setRequestMethod("GET");
    conn.setRequestProperty("Range", "bytes=" + startPosition + "-" + endPosition);
    conn.setConnectTimeout(5000);
    //若請求頭加上Range這個參數(shù),則返回狀態(tài)碼為206,而不是200
    if (conn.getResponseCode() == 206) {
     InputStream is = conn.getInputStream();
     RandomAccessFile raf = new RandomAccessFile(filePath, "rwd");
     raf.seek(startPosition);//跳到指定位置開始寫數(shù)據(jù)
     int len;
     byte[] buffer = new byte[1024];
     while ((len = is.read(buffer)) != -1) {
      //是否繼續(xù)下載
      if (!isGoOn)
       break;
      //回調(diào)當前進度
      if (mDownLoadListener != null) {
       currLength += len;
       int progress = (int) ((float) currLength / (float) fileLength * 100);
       handler.sendEmptyMessage(progress);
      }

      raf.write(buffer, 0, len);
      //寫完后將當前指針后移,為取消下載時保存當前進度做準備
      currPosition += len;
      synchronized (DOWNLOAD_PAUSE) {
       if (stateDownload.equals(DOWNLOAD_PAUSE)) {
        DOWNLOAD_PAUSE.wait();
       }
      }
     }
     is.close();
     raf.close();
     //線程計數(shù)器-1
     runningThreadCount--;
     //若取消下載,則直接返回
     if (!isGoOn) {
      //此處采用SharedPreferences保存每個線程的當前進度,和三個線程的總下載進度
      if (currPosition < endPosition) {
       sp.edit().putInt(SP_NAME + threadId, currPosition).apply();
       sp.edit().putInt(CURR_LENGTH, currLength).apply();
      }
      return;
     }
     if (runningThreadCount == 0) {
      sp.edit().clear().apply();
      handler.sendEmptyMessage(SUCCESS);
      handler.sendEmptyMessage(100);
      mThreads = null;
     }
    } else {
     sp.edit().clear().apply();
     handler.sendEmptyMessage(FAILURE);
    }
   } catch (Exception e) {
    sp.edit().clear().apply();
    e.printStackTrace();
    handler.sendEmptyMessage(FAILURE);
   }
  }

  public void cancel() {
   isGoOn = false;
  }
 }

 //請求成功
 private final int SUCCESS = 0x00000101;
 //請求失敗
 private final int FAILURE = 0x00000102;

 private Handler handler = new Handler() {
  @Override
  public void handleMessage(Message msg) {

   if (mDownLoadListener != null) {
    if (msg.what == SUCCESS) {
     mDownLoadListener.onComplete();
    } else if (msg.what == FAILURE) {

     mDownLoadListener.onFailure();
    } else {
     mDownLoadListener.getProgress(msg.what);
    }
   }
  }
 };
}

以上就是本文的全部內(nèi)容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。

相關文章

  • android自動化測試知識點總結

    android自動化測試知識點總結

    在本文里小編給大家分享了關于android自動化測試入門的相關知識點,需要的朋友們跟著參考下吧。
    2019-06-06
  • Android 實現(xiàn)夜間模式的快速簡單方法實例詳解

    Android 實現(xiàn)夜間模式的快速簡單方法實例詳解

    這篇文章主要介紹了Android 實現(xiàn)夜間模式的快速簡單方法,非常不錯,具有參考借鑒價值,需要的朋友可以參考下
    2016-09-09
  • Android編程獲取圖片和視頻縮略圖的方法

    Android編程獲取圖片和視頻縮略圖的方法

    這篇文章主要介紹了Android編程獲取圖片和視頻縮略圖的方法,結合實例形式分析了Android圖形圖像處理所涉及的常用函數(shù)與使用技巧,需要的朋友可以參考下
    2016-04-04
  • Glide實現(xiàn)加載圖片顯示進度條效果

    Glide實現(xiàn)加載圖片顯示進度條效果

    Glide作為安卓開發(fā)常用的圖片加載庫,有許多實用而且強大的功能,那么,下面這篇文章主要給大家介紹了利用Glide實現(xiàn)加載圖片顯示進度條效果的相關資料,文中給出了詳細的示例代碼供大家參考學習,需要的朋友們下來一起看看吧。
    2017-05-05
  • Android自定義HorizontalScrollView實現(xiàn)qq側滑菜單

    Android自定義HorizontalScrollView實現(xiàn)qq側滑菜單

    本文主要介紹了android自定義HorizontalScrollView實現(xiàn)qq側滑菜單的相關知識。具有很好的參考價值。下面跟著小編一起來看下吧
    2017-04-04
  • Android RecyclerView添加頭部和底部實例詳解

    Android RecyclerView添加頭部和底部實例詳解

    這篇文章主要介紹了Android RecyclerView添加頭部和底部實例詳解的相關資料,需要的朋友可以參考下
    2017-06-06
  • 一篇文章弄懂kotlin的擴展方法

    一篇文章弄懂kotlin的擴展方法

    這篇文章主要給大家介紹了如何通過一篇文章弄懂kotlin的擴展方法,文中通過示例代碼介紹的非常詳細,對大家學習或者使用kotlin具有一定的參考學習價值,需要的朋友們下面來一起學習學習吧
    2019-09-09
  • Android開發(fā)之Wifi基礎教程

    Android開發(fā)之Wifi基礎教程

    這篇文章主要介紹了Android開發(fā)Wifi基礎教程,實例分析了Wifi的各種常見基本技巧,具有一定參考借鑒價值,需要的朋友可以參考下
    2015-02-02
  • Android常用三方庫混淆規(guī)則整理(小結)

    Android常用三方庫混淆規(guī)則整理(小結)

    這篇文章主要介紹了Android常用三方庫混淆規(guī)則整理(小結),小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2018-07-07
  • Android使用Gallery實現(xiàn)照片拖動的特效

    Android使用Gallery實現(xiàn)照片拖動的特效

    這篇文章主要介紹了Android如何使用Gallery實現(xiàn)照片拖動的特效,幫助大家更好的理解和利用Android進行開發(fā),感興趣的朋友可以了解下
    2021-01-01

最新評論

冷水江市| 稷山县| 太仆寺旗| 永修县| 南京市| 农安县| 阳新县| 木兰县| 静乐县| 大厂| 大厂| 嘉荫县| 西贡区| 临安市| 大邑县| 天柱县| 江永县| 阳高县| 崇仁县| 四会市| 眉山市| 宜都市| 策勒县| 临漳县| 青海省| 六枝特区| 沁水县| 河西区| 新田县| 灵丘县| 井研县| 酒泉市| 西安市| 靖远县| 葵青区| 远安县| 韩城市| 桦甸市| 邻水| 深水埗区| 万源市|