1. 程式人生 > >Android---服務的最佳實踐(完整版的下載例項)

Android---服務的最佳實踐(完整版的下載例項)

一、定義回撥介面

public interface DownloadListener {
/*
     * 介面類,使用回撥
     */
void onProgress(int progress);
    void onSuccess();
    void onFailed();
    void onPaused();
    void onCanceled();
}

二、定義下載類

package com.mycompany.servicebestpractice;
import android.os.AsyncTask;
import android.os.Environment
; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import okhttp3.OkHttpClient; import okhttp3.Request; import okhttp3.Response; /** * Created by sstek_mars on 2017/9/8. */ /** * AsyncTask的三個泛型引數 * 第一個引數指定為String,表示在執行AsyncTask的時候需要傳入一個字串引數給後臺任務
* 第二個泛型引數指定為Integer,表示使用整數型資料來作為進度顯示單位 * 第三個泛型引數指定為Integer,表示使用整型資料來反饋執行結果 */ public abstract class DownloadTask extends AsyncTask<String, Integer, Integer> { public static final int TYPE_SUCCESS = 0; public static final int TYPE_FAILED = 1; public static final int TYPE_PAUSED = 2; public static final int
TYPE_CANCELED = 3; private DownloadListener listener; private boolean isCanceled = false; private boolean isPaused = false; private int lastProgress; public DownloadTask(DownloadListener listener) { this.listener = listener; } /** * 重寫doInBackground() onProgressUpdate() onPostExecute() * doInBackground():用於在後臺執行具體的下載邏輯 * onProgressUpdate():用於在介面上更新當前的下載進度 * onPostExecute():用於通知最終的下載結果 */ @Override protected Integer doInBackground(String... params) { InputStream is = null; RandomAccessFile saveFile = null; File file = null; try { long downloadedLength = 0; // 記錄下載的檔案長度 String dowloadUrl = params[0]; // 從URL中解析出下載的檔名 String fileName = dowloadUrl.substring(dowloadUrl.lastIndexOf("/")); // 將檔案下載的指定位置 String directory = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOWNLOADS).getPath(); // 判斷檔案是否存在,已經存在的就無需下載了 file = new File(directory + fileName); if (file.exists()) { // 如果已存在,讀取已下載的位元組數,用於啟動斷點下載功能 downloadedLength = file.length(); } long contentLength = getContentLength(dowloadUrl); if (contentLength == 0) { return TYPE_FAILED; }else if(contentLength == downloadedLength){ // 已下載的位元組和檔案總位元組相等,說明已經下載完成了 return TYPE_SUCCESS; } OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder() // 新增header用於告訴伺服器我們想從哪個位元組開始下載,開始斷點下載,知道從哪個位元組開始下載 .addHeader("RANGE", "bytes=" + downloadedLength + "-") .url(dowloadUrl) .build(); Response response = client.newCall(request).execute(); if (response != null) { // 使用jiava檔案流的方式,不斷的從網路讀取資料,不斷的寫入本地 is = response.body().byteStream(); saveFile = new RandomAccessFile(file, "rw"); saveFile.seek(downloadedLength); byte[] b = new byte[1024]; int total = 0; int len; while ((len = is.read(b)) != -1) { if (isCanceled) { return TYPE_CANCELED; }else if (isPaused) { return TYPE_PAUSED; }else { total += len; saveFile.write(b, 0, len); // 計算已下載的百分比 int progress = (int) ((total + downloadedLength) * 100 / contentLength); publishProgress(progress); } } response.body().close(); return TYPE_SUCCESS; } } catch (Exception e) { e.printStackTrace(); } finally { try { if (is != null) { is.close(); } if (saveFile != null) { saveFile.close(); } if (isCanceled && file != null) { file.delete(); } } catch (Exception e) { e.printStackTrace(); } } return TYPE_FAILED; } // 獲取當前下載的進度 @Override protected void onProgressUpdate(Integer... values) { int progress = values[0]; if (progress > lastProgress) { listener.onProgress(progress); lastProgress = progress; } } // 獲取是否下載完成 @Override protected void onPostExecute(Integer integer) { switch (integer) { case TYPE_SUCCESS: listener.onSuccess(); break; case TYPE_FAILED: listener.onFailed(); break; case TYPE_PAUSED: listener.onPaused(); break; case TYPE_CANCELED: listener.onCanceled(); break; default: break; } } public void pauseDownload() { isPaused = true; } public void cancelDownload() { isCanceled = true; } private long getContentLength(String downloadUrl) throws IOException { OkHttpClient client = new OkHttpClient(); Request request = new Request.Builder().url(downloadUrl).build(); Response response = client.newCall(request).execute(); if (response != null && response.isSuccessful()) { long contentLength = response.body().contentLength(); response.close(); return contentLength; } return 0; } }

三、定義服務

package com.mycompany.servicebestpractice;
import android.app.Notification;
import android.app.NotificationManager;
import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.graphics.BitmapFactory;
import android.os.Binder;
import android.os.Environment;
import android.os.IBinder;
import android.support.annotation.Nullable;
import android.support.v4.app.NotificationCompat;
import android.widget.Toast;
import java.io.File;
public class DownloadService extends Service {
private DownloadTask downloadTask;
    private String downloadUrl;
    private DownloadListener listener = new DownloadListener() {
@Override
        public void onProgress(int progress) {
getNotificationManager().notify(1, getNotification("下載中。。。", progress));
}
@Override
        public void onSuccess() {
downloadTask = null;
// 下載成功時將前臺的服務通知關閉,並建立一個下載成功的通知
stopForeground(true);
getNotificationManager().notify(1, getNotification("Download success", -1));
Toast.makeText(DownloadService.this, "下載成功", Toast.LENGTH_SHORT).show();
}
@Override
        public void onFailed() {
downloadTask = null;
// 下載失敗時將前臺的服務通知關閉,並建立一個下載失敗的通知
stopForeground(true);
getNotificationManager().notify(1, getNotification("Download success", -1));
Toast.makeText(DownloadService.this, "下載失敗", Toast.LENGTH_SHORT).show();
}
@Override
        public void onPaused() {
downloadTask = null;
Toast.makeText(DownloadService.this, "下載暫停", Toast.LENGTH_SHORT).show();
}
@Override
        public void onCanceled() {
downloadTask = null;
stopForeground(true);
Toast.makeText(DownloadService.this, "下載取消", Toast.LENGTH_SHORT).show();
}
    };
    private DownloadBinder mBinder = new DownloadBinder();
    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
return mBinder;
}
class DownloadBinder extends Binder {
public void startDownload(String url) {
if (downloadTask == null) {
downloadUrl = url;
downloadTask.execute(downloadUrl);
startForeground(1, getNotification("Downloading...", 0));
Toast.makeText(DownloadService.this, "Downloading...",Toast.LENGTH_SHORT).show();
}
        }
public void pauseDownload() {
if (downloadTask != null) {
downloadTask.pauseDownload();
}
        }
public void cancelDownload() {
if (downloadTask != null) {
downloadTask.cancelDownload();
} else {
if (downloadUrl != null) {
// 取消下載是需將檔案刪除,並將通知關閉
String fileName = downloadUrl.substring(downloadUrl.lastIndexOf("/"));
String dirdectory = Environment.getExternalStoragePublicDirectory(Environment
.DIRECTORY_DOWNLOADS).getPath();
File file = new File(dirdectory + fileName);
                    if (file.exists()) {
                        file.delete();
}
getNotificationManager().cancel(1);
stopForeground(true);
Toast.makeText(DownloadService.this, "取消", Toast.LENGTH_SHORT).show();
}
            }
        }
    }
private NotificationManager getNotificationManager() {
return (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
}
private Notification getNotification(String title, int progress) {
Intent intent = new Intent(this, MainActivity.class);
PendingIntent pi = PendingIntent.getActivity(this, 0, intent, 0);
NotificationCompat.Builder builder = new NotificationCompat.Builder(this);
builder.setSmallIcon(R.mipmap.ic_launcher);
builder.setLargeIcon(BitmapFactory.decodeResource(getResources(), R.mipmap.ic_launcher));
builder.setContentIntent(pi);
builder.setContentTitle(title);
        if (progress > 0) {
            builder.setContentText(progress + "%");
builder.setProgress(100, progress, false);
}
return builder.build();
}
}

四、呼叫

package com.mycompany.servicebestpractice;
import android.content.ComponentName;
import android.content.Intent;
import android.content.ServiceConnection;
import android.content.pm.PackageManager;
import android.os.IBinder;
import android.support.annotation.NonNull;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import java.util.jar.Manifest;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private DownloadService.DownloadBinder downloadBinder;
    private ServiceConnection connection = new ServiceConnection() {
@Override
        public void onServiceConnected(ComponentName name, IBinder service) {
downloadBinder = (DownloadService.DownloadBinder) service;
}
@Override
        public void onServiceDisconnected(ComponentName name) {
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
Button startDownload = (Button) findViewById(R.id.start_download);
Button pauseDownload = (Button) findViewById(R.id.pause_download);
Button cancleDownload = (Button) findViewById(R.id.cancel_download);
startDownload.setOnClickListener(this);
pauseDownload.setOnClickListener(this);
cancleDownload.setOnClickListener(this);
Intent intent = new Intent(this, DownloadService.class);
startService(intent); // 啟動服務
bindService(intent, connection, BIND_AUTO_CREATE); // 繫結服務
if (ContextCompat.checkSelfPermission(MainActivity.this, android.Manifest.permission.WRITE_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(MainActivity.this, new String[]{
android.Manifest.permission.WRITE_EXTERNAL_STORAGE
}, 1);
}
    }
@Override
    public void onClick(View v) {
if (downloadBinder == null) {
return;
}
switch (v.getId()) {
case R.id.start_download:
String url = "https://raw.githubusercontent.com/guolindev/eclipse/master/ec;o[se=inst-win.exe";
downloadBinder.startDownload(url);
                break;
            case R.id.pause_download:
downloadBinder.pauseDownload();
                break;
            case R.id.cancel_download:
downloadBinder.cancelDownload();
                break;
            default:
                break;
}
    }
@Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions
            
           

相關推薦

Android---服務最佳實踐整版下載例項

一、定義回撥介面 public interface DownloadListener { /* * 介面類,使用回撥 */ void onProgress(int progress); void onSuccess(); void on

React 伺服器渲染原理解析與實踐整版

第1章 伺服器端渲染基礎本章主要講解客戶端與伺服器端渲染的概念,分析客戶端渲染和伺服器端渲染的利弊,帶大家對伺服器端渲染有一個粗淺認識。1-1 課程導學1-2 什麼是伺服器端渲染1-3 什麼是客戶端渲染1-4 React 客戶端渲染的優勢與弊端第2章 React中的伺服器

影象和圖形的最佳實踐WWDC 2018 session 219

該篇部落格記錄觀看WWDC2018中Session219《Image And Graphics Best Practices》的內容及一些理解。 該Session主要講述了關於有效使用圖形內容的一些技術和策略。主要分三個方面: 從UIImage和UIIma

018、容器命名最佳實踐 2019-01-09 週三

參考 https://www.cnblogs.com/CloudMan6/p/6885700.html     學會了映象的構建,下面研究如何在多個Docker Host上使用映象       

android studio xposed教程含jar下載地址

0x01 什麼是xposed? Xposed是一款可以在不修改APK的情況下影響程式執行的框架服務,基於Xposed能夠製作出許多功能強大的模組,且在功能不衝突的情況下同時運作。 xposed是一個框架,可以通過xposed installer安裝,具體安裝方法我就不在這裡詳述了,需要的同學請自行搜

《JAVA併發程式設計實踐中文整版》電子書附下載連結+30個總結JVM虛擬機器的技術文排版好收藏版

技術書閱讀方法論 一.速讀一遍(最好在1~2天內完成) 人的大腦記憶力有限,在一天內快速看完一本書會在大腦裡留下深刻印象,對於之後複習以及總結都會有特別好的作用。 對於每一章的知識,先閱讀標題,弄懂大概講的是什麼主題,再去快速看一遍,不懂也沒有關係,但是一定要在不懂的

下載Android原始碼流程整版

  要在Linux環境下操作,要在Linux環境下操作,要在Linux環境下操作~~ 不要想在Windows環境下操作,因為會有各種問題。Windows環境的童鞋又不想裝雙系統的可以跟著下面的操作,Linux的童鞋可以直接跳過看。Mac的童鞋就略過~~~

SpringCloud入門最佳實踐Rest微服務構建案例工程模組

介紹 承接著我們的springmvc+mybatis+mysql初級高階課程,以Dept部門模組做一個微服務通用案例Consumer消費(Client)通過REST呼叫Provider提供者(Serv

Office2016 32/64位簡體中文整版下載含啟用工具

沒錯!你沒有看錯,這個是真的微軟官方釋出的office2016最新版本,給你帶來2016全新體驗,完美結合windows10的最新最強大的辦公軟體-Office2016版本。。 office2016你馬上下載軟體支援:64位和32位,所以大家都可以下載後選

人工智慧實踐:Tensorflow筆記整版

  入門課程,比較基礎   第一講 帶著大家梳理人工智慧領域的基本概念:比如什麼是人工智慧、什麼機器學習、什麼是深度學習,他們的發展歷史是什麼,能用他們做什麼。課後,助教會帶領大家安裝Ubuntu系統、Python直譯器 和 Tensorflow環境,把同學們的電腦進行改造

服務架構上雲最佳實踐轉自阿里中介軟體

摘要:7月27日,雲棲社群、阿里中介軟體舉辦了首屆阿里巴巴中介軟體技術峰會,揭祕阿里10年分散式技術乾貨。在首屆阿里巴巴中介軟體技術峰會上,具有10年研發經驗的阿里巴巴中介軟體技術專家李顏良結合EDAS團隊上雲兩年多以來積累的經驗為大家分享瞭如何進行微服務拆分、微服務架構上雲最佳實踐以及微服務架構常用的模式,

深度學習之神經網路CNN/RNN/GAN (演算法原理+實戰) 整版下載

第1章 課程介紹 深度學習的導學課程,主要介紹了深度學習的應用範疇、人才需求情況和主要演算法。對課程章節、課程安排、適用人群、前提條件以及學習完成後達到的程度進行了介紹,讓同學們對本課程有基本的認識。 第2章 神經網路入門 本次實戰課程的入門課程。對機器學習和深

二叉搜尋樹的原始碼分析學習 筆記整版 包含原始碼和visio下載

上篇部落格介紹了二叉搜尋樹的建立,插入結點,遍歷結點,查詢結點,最大結點,最小結點,後繼結點。 那麼這篇部落格要重點介紹二叉搜尋樹的節點刪除函式,一些資料結構的書籍裡介紹的二叉搜尋樹刪除節點的方法說的非常之模糊,能把一個老司機說成萌新。 二叉搜尋樹刪除結點

深度學習FPGA實現基礎知識5(網友一致認可的----Deep Learning深度學習學習筆記整理及整版下載)

需求說明:深度學習FPGA實現知識儲備 來自:http://blog.csdn.net/zouxy09/article/details/8775360/ Deep Learning(深度學習)

教你如何使用android studio釋出release 版本整版

想必還有人對如何在android studio (以下簡稱as)釋出release版本的app而狂刷百度吧?都是過來人,我很理解這種心情,百度到的基本是半成品,為什麼這麼說呢?百度一下,你就知道,好了

Android OkHttp實現HttpDns的最佳實踐非攔截器

之前寫過一篇文章 Android 使用OkHttp支援HttpDNS,該文章中使用的是OkHttp的攔截器來實現HttpDNS。在請求發出去之前,將URL中的域名替換成ip,再往Header中新增Host。這種方式有以下優點。 上層方便控制哪些請求使用了Ht

字符串函數---atof()函數具體解釋及實現整版

記錄 == include als 技術 整數 ast fill 跳過 atof()函數 atof():double atof(const char *str ); 功 能: 把字符串轉換成浮點數 str:要轉換的字符串。 返回值:每一個函數返回 double 值。此值

免費的Lucene 原理與代碼分析整版下載

一個個 圖片 重新 修改時間 結果 參數 擴展 提取 要點 Lucene是一個基於Java的高效的全文檢索庫。那麽什麽是全文檢索,為什麽需要全文檢索?目前人們生活中出現的數據總的來說分為兩類:結構化數據和非結構化數據。很容易理解,結構化數據是有固定格式和結構的或者有限長度的

SpringCloud的最佳實踐個人觀點,讀書總結,請多指教!

vcg back 實踐 一個 1.2 設計 -s ron dmg 前言 這個綜合例子創建了 6個微服務應用 一個服務註冊中心 SvcReg(EurekaServer,可以作為ConfigClient) 一個配置中心 CfgMgr + git目錄存儲配置(ConfigSe

css最佳實踐reset.css

frame pla family after thead article tle fieldset san html, body, div, span, object, iframe,h1, h2, h3, h4, h5, h6, p, blockquote, pre,ab