[TEAP早期試讀]Android開發實現後臺下載
圖靈社群按:
TEAP是什麼?TEAP是Turingbook Early Access Program的簡稱,即早期試讀,它公佈的是圖靈在途新書未經編輯的內容。一本書的翻譯週期約為3到6個月,如果在翻譯過程中,譯者就能與讀者進行溝通和交流,對整本書的翻譯品質是有幫助的。通過TEAP,讀者可以提前閱讀將來才能出版的內容,譯者也能收穫寶貴的反饋意見,改進翻譯,提高質量。
本書原名為Android Recipes: A Problem-Solution Approach,中文暫定名為《Android攻略》,本文節選自原書第3章第5節。
問題
應用要將一個很大的資源下載到裝置上,例如電影,但在這個過程中無需使用者時刻保持應用處於活躍狀態。
解決方案
(API Level 9)
使用DownloadManager API。SDK在API Level 9中加入了DownloadManager服務,可以將長時間的下載任務交給系統,完全由系統管理。使用這個服務的主要好處就是,在遇到下載失敗、連線改變甚至是裝置重啟等情況時,DownloadManager會自動的繼續下載指定的資源。
原理
程式碼清單3-12中的示例Activity用DownloadManager下載大型圖片檔案。在下載完成時,圖片就會顯示在ImageView中。在使用DownloadManager訪問網際網路內容時,一定要在應用的manifest檔案中宣告android.permission.INTERNET許可權。
程式碼清單3-12 DownloadManager示例Activity
public class DownloadActivity extends Activity {
private static final String DL_ID = "downloadId";
private SharedPreferences prefs;
private DownloadManager dm;
private ImageView imageView;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
imageView = new ImageView(this);
setContentView(imageView);
prefs = PreferenceManager.getDefaultSharedPreferences(this);
dm = (DownloadManager)getSystemService(DOWNLOAD_SERVICE);
}
@Override
public void onResume() {
super.onResume();
if(!prefs.contains(DL_ID)) {
//開始下載
Uri resource = Uri.parse("http://www.bigfoto.com/dog-animal.jpg");
DownloadManager.Request request = new DownloadManager.Request(resource);
request.setAllowedNetworkTypes(Request.NETWORK_MOBILE |
Request.NETWORK_WIFI);
request.setAllowedOverRoaming(false);
//在通知欄中顯示
request.setTitle("Download Sample");
long id = dm.enqueue(request);
//儲存id
prefs.edit().putLong(DL_ID, id).commit();
} else {
//下載已經開始,檢查狀態
queryDownloadStatus();
}
registerReceiver(receiver,
new IntentFilter(DownloadManager.ACTION_DOWNLOAD_COMPLETE));
}
@Override
public void onPause() {
super.onPause();
unregisterReceiver(receiver);
}
private BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
queryDownloadStatus();
}
};
private void queryDownloadStatus() {
DownloadManager.Query query = new DownloadManager.Query();
query.setFilterById(prefs.getLong(DL_ID, 0));
Cursor c = dm.query(query);
if(c.moveToFirst()) {
int status = c.getInt(c.getColumnIndex(DownloadManager.COLUMN_STATUS));
switch(status) {
case DownloadManager.STATUS_PAUSED:
case DownloadManager.STATUS_PENDING:
case DownloadManager.STATUS_RUNNING:
//正在下載,不做任何事情
break;
case DownloadManager.STATUS_SUCCESSFUL:
//完成,顯示圖片
try {
ParcelFileDescriptor file =
dm.openDownloadedFile(prefs.getLong(DL_ID, 0));
FileInputStream fis =
new ParcelFileDescriptor.AutoCloseInputStream(file);
imageView.setImageBitmap(BitmapFactory.decodeStream(fis));
} catch (Exception e) {
e.printStackTrace();
}
break;
case DownloadManager.STATUS_FAILED:
//清除已下載的內容,重新下載
dm.remove(prefs.getLong(DL_ID, 0));
prefs.edit().clear().commit();
break;
}
}
}
}
重要:在本書出版時,SDK中有一個BUG:在使用DownloadManager時會丟擲一個要求宣告android.permission.ACCESS_ALL_DOWNLOADS的異常。但實際上,只有在manifest中沒有申明android.permission.INTERNET許可權時才會出現這個異常。
在這個例子中,所有的實際工作都是在Activity.onResume()方法中完成的。因此,每次使用者返回該Activity時,應用都會判斷下載的狀態。管理器中的下載任務可以通過呼叫DownloadManager.enqeue()時返回的長長的ID值來引用。在這個例子中,我們將這個值儲存到應用的設定中,這樣就隨時都能監控和獲取下載的內容。
在第一次啟動這個示例應用時,會建立一個表示要下載的內容的DownloadManager.Request物件。至少需要指定遠端資源的Uri來建立請求。不過,還有很多有用的屬性可以用來控制它的行為。這些有用的屬性包括: - Request.setAllowedNetworkTypes() 指定下載所使用的網路型別。 - Request.setAllowedOverRoaming() 設定當裝置處於漫遊模式時是否要下載。 - Request.setTitle() 設定下載在系統通知欄中顯示的標題。 - Request.setDescription() 設定下載在系統通知欄中顯示的描述。
在獲得ID後,應用就用這個ID檢查下載的狀態。註冊一個BroadcastReceiver監聽ACTION_DOWNLOAD_COMPLETE廣播,在下載完成時,應用就可以將下載的圖片檔案設定到Activity的ImageView上。如果在下載完成時Activity處於暫停狀態,那麼就會在下次恢復Activity時檢查下載狀態,並設定ImageView的內容。
要注意ACTION_DOWNLOAD_COMPLETE是DownloadManager對其管理的所有下載任務發出的廣播。正因為如此,我們必須要根據下載ID才能判斷我們的下載是否完成。
相關文章
- [TEAP早期試讀]資料庫和敏捷開發資料庫敏捷
- [TEAP早期試讀]《敏捷武士》推薦序敏捷
- [TEAP早期試讀]HTML5與JSONHTMLJSON
- [TEAP早期試讀]敏捷武士之敏捷簡介敏捷
- [TEAP早期試讀]《深入淺出CoffeeScript》譯者序
- [TEAP早期試讀]《MongoDB in Action》——為什麼選擇MongoDB?MongoDB
- [TEAP早期試讀]《程式設計師的數學》- 前言程式設計師
- [TEAP早期試讀]基於WebSocket的聯機作圖例子Web
- [TEAP早期試讀]NoSQL資料庫的基礎知識SQL資料庫
- [TEAP早期試讀]在資料庫中使用PL/SQL實現業務邏輯的優勢資料庫SQL
- [TEAP早期試讀]真正的好處:客戶端批量處理客戶端
- [TEAP早期試讀]《深入淺出CoffeeScript》CoffeeScript中的OOPOOP
- [TEAP早期試讀]Linux: 一個人加上一百萬人的智慧Linux
- [TEAP早期試讀]《深入淺出CoffeeScript》CoffeeScript與Node.jsNode.js
- [TEAP早期試讀]《Linux/Unix設計思想》之: 大教堂?多怪異Linux
- [TEAP早期試讀]《程式設計師的數學》- 邏輯工具卡諾圖程式設計師
- [TEAP早期試讀]《深入淺出CoffeeScript》集合與迭代節選和若干問題
- [TEAP早期試讀]《30天寫出你的作業系統》 - 挑戰多工作業系統
- 【Android初級】如何實現一個“模擬後臺下載”的載入效果(附原始碼)Android原始碼
- Node + Express 後臺開發 —— 上傳、下載和釋出Express
- Android開發工具下載地址Android
- js和其他後臺語言結合實現附件下載功能JS
- 微信後臺開發實戰教程
- 《Head First Android》讀後感,電子書PDF下載Android
- Python後臺開發(第二章: 模型類實現)Python模型
- Cordova+Vue 混合開發實現下載並預覽Vue
- React開發管理後臺實踐1React
- 開發人員測試 Devin AI 後的發現devAI
- Android 中 DownLoadManager 實現檔案下載Android
- Android通過startService實現批量下載示例Android
- iOS 後臺下載及管理庫iOS
- Android SDK開發包國內下載地址Android
- 點選按鈕,實現檔案下載,通過按鈕傳送url,spring後臺實現伺服器端檔案下載。Spring伺服器
- 測試開發【Mock平臺】04實戰:前後端專案初始化與登入鑑權實現Mock後端
- 一小時完成後臺開發:DjangoRestFramework開發實踐DjangoRESTFramework
- iOS BLE 開發小記[4] 如何實現 CoreBluetooth 後臺執行模式iOS模式
- (連載)Android 8.0 : 如何下載和閱讀Android原始碼Android原始碼
- Android實現zip檔案下載和解壓功能Android