[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才能判斷我們的下載是否完成。
相關文章
- 【Android初級】如何實現一個“模擬後臺下載”的載入效果(附原始碼)Android原始碼
- 《Head First Android》讀後感,電子書PDF下載Android
- Node + Express 後臺開發 —— 上傳、下載和釋出Express
- Python後臺開發(第二章: 模型類實現)Python模型
- Cordova+Vue 混合開發實現下載並預覽Vue
- 點選按鈕,實現檔案下載,通過按鈕傳送url,spring後臺實現伺服器端檔案下載。Spring伺服器
- Android篇:2019初中級Android開發社招面試解答(下)Android面試
- React開發管理後臺實踐1React
- 微信後臺開發實戰教程
- Android開發中利用ObjectAnimator實現ArcMenuAndroidObject
- OpenJDK JDK 20 早期訪問版本提供下載JDK
- 測試開發【Mock平臺】04實戰:前後端專案初始化與登入鑑權實現Mock後端
- 開發人員測試 Devin AI 後的發現devAI
- 一小時完成後臺開發:DjangoRestFramework開發實踐DjangoRESTFramework
- iOS BLE 開發小記[4] 如何實現 CoreBluetooth 後臺執行模式iOS模式
- Android開發中陰影效果的實現Android
- 藉助雲開發輕鬆實現後臺資料批量匯出丨實戰
- 直播平臺軟體開發,一個簡單的Android登入實現demoAndroid
- Android按下返回鍵,將應用退到後臺Android
- 《React Native跨平臺移動應用開發》讀後鬼扯React Native
- Django Admin後臺管理:高效開發與實踐Django
- android開發者資源下載地址記錄(轉+補充)Android
- 乾貨丨RK3399開發板android系統下實現影像識別Android
- iOS原生級別後臺下載詳解iOS
- 檔案上傳/下載後臺程式碼
- servlet實現下載功能Servlet
- [文件教程]PHP實現微信開放平臺掃碼登入原始碼下載PHP原始碼
- 部落格園商業化之路-開發任務眾包平臺:召集早期合作開發者
- 數說深圳美好:發現深圳背後的力量(附下載)
- Vue Router根據後臺資料載入不同的元件(思考->實現->不止於實現)Vue元件
- 【測試】Android Studio 相關下載及引數Android
- Android studio下載安裝後常見問題中的gradle下載失敗AndroidGradle
- DDS協議解讀及測試開發實踐協議
- 【Nginx】Windows平臺下配置Nginx服務實現負載均衡NginxWindows負載
- 後臺開發 -- 核心技術與應用實踐
- 【實用】iOS開發者後臺快速上手指南iOS
- 測試開發實戰[提測平臺]17-Flask&Vue檔案上傳實現FlaskVue
- android短視訊開發,後臺各個管理頁面的分頁管理Android
- Android開發實現連續跳轉幾個介面後在最後一個介面完美跳回最初的介面Android