Android 文件下載三種基本方式


一、自己封裝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) {
                    }
                }
            }
        });
    }

 

 
 
 
綜合來看,第三種方案是最佳的,是目前最流行的下載方案。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM