Android 文件下載三種基本方式

来源:http://www.cnblogs.com/xiaoxiaoqingyi/archive/2017/06/13/7003241.html
-Advertisement-
Play Games

一、自己封裝URLConnection 連接請求類 public void downloadFile1() { try{ //下載路徑,如果路徑無效了,可換成你的下載路徑 String url = "http://c.qijingonline.com/test.mkv"; String path = ...


一、自己封裝URLConnection 連接請求類

   public void downloadFile1() {
    try{
        //下載路徑,如果路徑無效了,可換成你的下載路徑
        String url = "http://c.qijingonline.com/test.mkv";
        String path = Environment.getExternalStorageDirectory().getAbsolutePath();

        final long startTime = System.currentTimeMillis();
        Log.i("DOWNLOAD","startTime="+startTime);
        //下載函數
       String filename=url.substring(url.lastIndexOf("/") + 1);
        //獲取文件名
        URL myURL = new URL(url);
        URLConnection conn = myURL.openConnection();
        conn.connect();
        InputStream is = conn.getInputStream();
        int fileSize = conn.getContentLength();//根據響應獲取文件大小
        if (fileSize <= 0) throw new RuntimeException("無法獲知文件大小 ");
        if (is == null) throw new RuntimeException("stream is null");
        File file1 = new File(path);
        if(!file1.exists()){
            file1.mkdirs();
        }
        //把數據存入路徑+文件名
        FileOutputStream fos = new FileOutputStream(path+"/"+filename);
        byte buf[] = new byte[1024];
        int downLoadFileSize = 0;
        do{
            //迴圈讀取
            int numread = is.read(buf);
            if (numread == -1)
            {
                break;
            }
            fos.write(buf, 0, numread);
            downLoadFileSize += numread;
            //更新進度條
        } while (true);

        Log.i("DOWNLOAD","download success");
        Log.i("DOWNLOAD","totalTime="+ (System.currentTimeMillis() - startTime));

        is.close();
    } catch (Exception ex) {
        Log.e("DOWNLOAD", "error: " + ex.getMessage(), ex);
    }
}
這種方式在Android 剛興起的時候,很少下載封裝框架,就自己封裝了。雖然一般的文件都能下載,但這種方式缺點很多,不穩定或者各種各樣的問題會出現。  

二、Android自定的下載管理(會在notification 顯示下載的進度,同時可以暫停、重新連接等)

private void downloadFile2(){
    //下載路徑,如果路徑無效了,可換成你的下載路徑
    String url = "http://c.qijingonline.com/test.mkv";
    //創建下載任務,downloadUrl就是下載鏈接
    DownloadManager.Request request = new DownloadManager.Request(Uri.parse(url));
    //指定下載路徑和下載文件名
    request.setDestinationInExternalPublicDir("", url.substring(url.lastIndexOf("/") + 1));
    //獲取下載管理器
    DownloadManager downloadManager= (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
    //將下載任務加入下載隊列,否則不會進行下載
    downloadManager.enqueue(request);
}

 這種方式其實就是交給了Android系統的另一個app去下載管理。這樣的好處不會消耗該APP的 CPU資源。缺點是:控制起來很不靈活。

 

三、使用第三方 okhttp 網路請求框架

private void downloadFile3(){
    //下載路徑,如果路徑無效了,可換成你的下載路徑
    final String url = "http://c.qijingonline.com/test.mkv";
    final long startTime = System.currentTimeMillis();
    Log.i("DOWNLOAD","startTime="+startTime);

    Request request = new Request.Builder().url(url).build();
    new OkHttpClient().newCall(request).enqueue(new Callback() {
        @Override
        public void onFailure(Call call, IOException e) {
            // 下載失敗
            e.printStackTrace();
            Log.i("DOWNLOAD","download failed");
        }
        @Override
        public void onResponse(Call call, Response response) throws IOException {
            Sink sink = null;
            BufferedSink bufferedSink = null;
            try {
                String mSDCardPath= Environment.getExternalStorageDirectory().getAbsolutePath();
                File dest = new File(mSDCardPath,   url.substring(url.lastIndexOf("/") + 1));
                sink = Okio.sink(dest);
                bufferedSink = Okio.buffer(sink);
                bufferedSink.writeAll(response.body().source());

                bufferedSink.close();
                Log.i("DOWNLOAD","download success");
                Log.i("DOWNLOAD","totalTime="+ (System.currentTimeMillis() - startTime));
            } catch (Exception e) {
                e.printStackTrace();
                Log.i("DOWNLOAD","download failed");
            } finally {
                if(bufferedSink != null){
                    bufferedSink.close();
                }

            }
        }
    });
}
okhttp是一個很有名氣的開源框架,目前已經很多大公司都直接使用它作為網路請求庫(七牛雲SDK, 阿裡雲SDK)。 且裡面集成了很多優勢,包括 okio (一個I/O框架,優化記憶體與CPU)。   在接收數據的時候使用了 okio框架 來做一些I/O處理,okio框架是彌補Java.io 上的不足,節省CPU與記憶體資源,但這個例子,我沒還沒看到其效果,也可以自己來接收字元流,然後獲取下載的進度
 public void downloadFile(){
        final String url = "http://c.qijingonline.com/test.mkv";
        final long startTime = System.currentTimeMillis();
        Log.i("DOWNLOAD","startTime="+startTime);
        OkHttpClient okHttpClient = new OkHttpClient();

        Request request = new Request.Builder().url(url).build();
        okHttpClient.newCall(request).enqueue(new Callback() {
            @Override
            public void onFailure(Call call, IOException e) {
                // 下載失敗
                e.printStackTrace();
                Log.i("DOWNLOAD","download failed");
            }
            @Override
            public void onResponse(Call call, Response response) throws IOException {
                InputStream is = null;
                byte[] buf = new byte[2048];
                int len = 0;
                FileOutputStream fos = null;
                // 儲存下載文件的目錄
                String savePath = Environment.getExternalStorageDirectory().getAbsolutePath();
                try {
                    is = response.body().byteStream();
                    long total = response.body().contentLength();
                    File file = new File(savePath, url.substring(url.lastIndexOf("/") + 1));
                    fos = new FileOutputStream(file);
                    long sum = 0;
                    while ((len = is.read(buf)) != -1) {
                        fos.write(buf, 0, len);
                        sum += len;
                        int progress = (int) (sum * 1.0f / total * 100);
                        // 下載中
//                        listener.onDownloading(progress);
                    }
                    fos.flush();
                    // 下載完成
//                    listener.onDownloadSuccess();
                    Log.i("DOWNLOAD","download success");
                    Log.i("DOWNLOAD","totalTime="+ (System.currentTimeMillis() - startTime));
                } catch (Exception e) {
                    e.printStackTrace();
//                    listener.onDownloadFailed();
                    Log.i("DOWNLOAD","download failed");
                } finally {
                    try {
                        if (is != null)
                            is.close();
                    } catch (IOException e) {
                    }
                    try {
                        if (fos != null)
                            fos.close();
                    } catch (IOException e) {
                    }
                }
            }
        });
    }

 

      綜合來看,第三種方案是最佳的,是目前最流行的下載方案。
您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 博主今天去了一個java的實習面試,發現有好多java最基礎的數據結構對於博主來說反而感到陌生,在面試官問一些常見的例如HashMap這樣的數據結構,博主能回答的頭頭是道,但是在問到Array和ArrayList的區別和聯繫之後,卻讓博主一臉懵。好吧,不多說,現在特此整理。 首先, Array是ja ...
  • 學習的最好途徑就是看書 "學習的最好途徑就是看書",這是我自己學習並且小有了一定的積累之後的第一體會。個人認為看書有兩點好處: 1、能出版出來的書一定是經過反覆的思考、雕琢和審核的,因此從專業性的角度來說,一本好書的價值遠超其他資料 2、對著書上的代碼自己敲的時候方便 "看完書之後再次提升自我的最好 ...
  • 在JavaEE開發中,在把配置文件中的數據或用戶表單提交上來的數據,封裝在相應JavaBean的對象的對應屬性中時:在實際開發中,使用第三方法工具包BeanUtils(commons-beanutils-xxx.jar 依賴於commons-logging-xx.jar)。 如博主在JavaWeb工 ...
  • 一、 基本概述 下麵列出咖啡、茶的沖泡方法。 1.咖啡沖泡方法 (1) 把水煮沸 (2) 用沸水沖泡咖啡 (3) 把咖啡倒進杯子 (4) 家牛奶和糖 2.茶的沖泡方法 (1) 把水煮沸 (2) 用沸水浸泡茶葉 (3) 把茶倒進杯子 (4) 加檸檬 在使用代碼來完成這些方法時,我們一般想到的創建2個類 ...
  • 那對繼承,我是這麼看的。咱們這個繼承一般是針對父方法和子方法來說的,也就是說有兩個方法,一個父方法,一個子方法。子方法可以擁有父方法的所有屬性以及函數,那對於我們來說,js中常用的繼承有3種。 第一種原型鏈繼承:子對象他有一個預設屬性是叫__proto__,他是指向這個方法本身,而方法本身他是不帶父 ...
  • HDHaoShaoPengdeiMac:~ hdhaoshaopeng$ defaults write com.apple.finder AppleShowAllFiles TRUE HDHaoShaoPengdeiMac:~ hdhaoshaopeng$ killall Finder 以上命令是查 ...
  • 一 第一種方法 在select 標簽的父標簽加上 data-tap-disabled=”true” 二 找到 ionic.bundle.js文件 下邊有個方法 function tapIgnoreEvent(e) { if (e.isTapHandled) return true; e.isTapH ...
  • 一,效果圖。 二,工程圖。 三,代碼。 RootViewController.h RootViewController.m ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...