程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> 更多編程語言 >> 編程綜合問答 >> java-用android下載一個文件,在ProgressDialog顯示下載進度

java-用android下載一個文件,在ProgressDialog顯示下載進度

編輯:編程綜合問答
用android下載一個文件,在ProgressDialog顯示下載進度

我正在嘗試寫一個簡單的應用,然後應用可以進行更新。為了做成這個,我需要一個簡單的功能,就是可以進行下載一個文件,同時在一個ProgressDialog顯示出當前的下載進度。我知道如何做ProgressDialog,但是我不知道在同一個地方怎麼既下載一個文件又顯示當前的進度。

最佳回答:


有很多下載文件的方法,接下來我將貼出最常用的一些方法;究竟哪一種對你的應用來說最實用取決於你。

  1. 使用AsyncTask,在一個對話框中顯示下載進度

這個方法可以讓你進行後台處理的同時更新UI(在這種情況下,我們將更新一個進度條)
這是實例代碼:

// 聲明對話框是你activity的成員字段
ProgressDialog mProgressDialog;

// 舉例說明在onCreate中的方法
mProgressDialog = new ProgressDialog(YourActivity.this);
mProgressDialog.setMessage("A message");
mProgressDialog.setIndeterminate(false);
mProgressDialog.setMax(100);
mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);

DownloadFile downloadFile = new DownloadFile();
downloadFile.execute("the url to the file you want to download");

AsyncTask像這樣:

// 通常,AsyncTask子類在activity類中進行聲明
// 這樣,你可以很容易在這裡修改UI線程
private class DownloadFile extends AsyncTask<String, Integer, String> {
    @Override
    protected String doInBackground(String... sUrl) {
        try {
            URL url = new URL(sUrl[0]);
            URLConnection connection = url.openConnection();
            connection.connect();
            //這將是有用的,這樣你可以顯示一個典型的0-100%的進度條
            int fileLength = connection.getContentLength();

            // 下載文件
            InputStream input = new BufferedInputStream(url.openStream());
            OutputStream output = new FileOutputStream("/sdcard/file_name.extension");

            byte data[] = new byte[1024];
            long total = 0;
            int count;
            while ((count = input.read(data)) != -1) {
                total += count;
                publishProgress((int) (total * 100 / fileLength));
                output.write(data, 0, count);
            }

            output.flush();
            output.close();
            input.close();
        } catch (Exception e) {
        }
        return null;
    }

上邊的方法(doInBackground)一直在一個後台線程中進行。你不需要做任何UI的任務。另一方面,onProgressUpdate和onPreExecute在UI線程上運行,因此你可以改變進度條

    @Override
    protected void onPreExecute() {
        super.onPreExecute();
        mProgressDialog.show();
    }

    @Override
    protected void onProgressUpdate(Integer... progress) {
        super.onProgressUpdate(progress);
        mProgressDialog.setProgress(progress[0]);
    }
}

一旦文件已經下載完,如果你想要執行一些代碼(例如mProgressDialog.dismiss()),你也可能想要重寫onPostExecute方法。

2.從服務器下載

這個大的問題是:我如何從服務器上更新我的activity?在下個示例中,我們將使用兩個你可能沒有太注意過的類:ResultReceiver和IntentService. ResultReceiver允許我們從服務器上更新我們的線程的類,IntentService 是Service的一個子類,從那,它可以產生一個線程來處理後台任務(你應該知道,你的應用的Service在同樣的進程運行;當你繼承Service時,你必須手動生成新的線程來運行CPU的阻塞操作)
可以像這樣:

public class DownloadService extends IntentService {
   public static final int UPDATE_PROGRESS= 8344;‘
   public DownloadService() {
       super("DownloadService");
   }
   @Override
   protected void onHandleIntent(Intent intent) {
       String urlToDownload= intent.getStringExtra("url");
       ResultReceiver receiver= (ResultReceiver)
 intent.getParcelableExtra("receiver");
       try {
            URL url= new URL(urlToDownload);
           URLConnection connection= url.openConnection();
            connection.connect();
           // 這將是有用的,這樣你可以顯示一個典型的0-100%的進度條
           int fileLength= connection.getContentLength();
           // 下載文件
           InputStream input= new BufferedInputStream(url.openStream());
           OutputStream output= new FileOutputStream("/sdcard/BarcodeScanner-debug.apk");
           byte data[] = new byte[1024];
           long total= 0;
           int count;
           while ((count= input.read(data)) != -1) {
                total+= count;
               Bundle resultData= new Bundle();
                resultData.putInt("progress" ,(int) (total* 100 / fileLength));
                receiver.send(UPDATE_PROGRESS, resultData);
                output.write(data, 0, count);
           }
            output.flush();
            output.close();
            input.close();

}catch (IOException e) {

            e.printStackTrace();
       }
       Bundle resultData= new Bundle();
        resultData.putInt("progress" ,100);
        receiver.send(UPDATE_PROGRESS, resultData);
   }
}

向你的manifest中加service

<service android:name=".DownloadService"/>

Activity將像這樣

// 像第一個例子那樣初始化進度條

//這是你怎麼啟動下載器
mProgressDialog.show();
Intent intent = new Intent(this, DownloadService.class);
intent.putExtra("url", "url of the file to download");
intent.putExtra("receiver", new DownloadReceiver(new Handler()));
startService(intent);

這是ResultReceiver開始起作用

private class DownloadReceiver extends ResultReceiver{
    public DownloadReceiver(Handler handler) {
        super(handler);
    }

    @Override
    protected void onReceiveResult(int resultCode, Bundle resultData) {
        super.onReceiveResult(resultCode, resultData);
        if (resultCode == DownloadService.UPDATE_PROGRESS) {
            int progress = resultData.getInt("progress");
            mProgressDialog.setProgress(progress);
            if (progress == 100) {
                mProgressDialog.dismiss();
            }
        }
    }
}

3.使用DownloadManager 類(GingerBread ,而且僅僅是最新的)
這個方法是可怕的,你不用擔心手動下載文件,處理線程,數據流,等等。GingerBread有一個新的特點,DownloadManager可以讓你很容易的下載文件,然後將辛苦的工作給系統做。

/**
 * @ param上下文用來檢查設備的版本和DownloadManager信息
 * @如果下載管理器可以用,則返回true
 */
public static boolean isDownloadManagerAvailable(Context context) {
   try {
       if (Build.VERSION.SDK_INT< Build.VERSION_CODES.GINGERBREAD) {
           return false;
       }
       Intent intent= new Intent(Intent.ACTION_MAIN);
        intent.addCategory(Intent.CATEGORY_LAUNCHER);
        intent.setClassName("com.android.providers.downloads.ui", "com.android.providers.downloads.ui.DownloadList");
       List<ResolveInfo> list= context.getPackageManager().queryIntentActivities(intent,
               PackageManager.MATCH_DEFAULT_ONLY);
       return list.size() > 0;
   } catch (Exception e) {
       return false;
   }
}

方法的名字直接就解釋了。一旦你確定DownloadManager是可用的,你可以做下邊這些:

String url= "url you want to download";
DownloadManager.Request request= new DownloadManager.Request(Uri.parse(url));
request.setDescription("Some descrition");request.setTitle("Some title");
// 如果為了讓它運行,你必須用android3.2編譯你的應用程序
if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.HONEYCOMB) {
    request.allowScanningByMediaScanner();
    request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED);
}
request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext");
// 獲得下載服務和隊列文件
DownloadManager manager= (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE);
manager.enqueue(request);

下載進度條將在通知欄顯示
結語
第一個和第二個方法僅僅是冰山一角。如果你想要你的app是健壯的,這有很多事情需要你記住。這是一個簡短的列表:

  • 你必須檢查用戶是否有可用的網絡鏈接。

  • 確定你有權限((INTERNET and
    WRITE_EXTERNAL_STORAGE);如果你想要檢查網絡是否可用也可以用ACCESS_NETWORK_STATE

  • 確保你要下載的文件的目錄存在,有讀寫權限

  • 如果下載包太大,之前的下載失敗了,你可能需要實現一種方法來恢復下載

  • 如果你允許用戶中斷下載,他們會很感激你。

除非你已經完全控制了下載過程,否則我強烈建議你使用DownloadManager ,它已經實現了上邊列出的大部分功能。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved