1. 程式人生 > >Android啟動service下載失敗後stopService,重新啟動service下載出現問題

Android啟動service下載失敗後stopService,重新啟動service下載出現問題

   在Android啟用service後臺下載,使用非同步執行緒進行下載,下載失敗時,關掉service。在重新下載時,重新啟動service,啟動新的非同步執行緒進行下載;因為上一次下載失敗只是啟動了停止了service,但上一個非同步執行緒任務還在繼續執行,此時又有新的執行緒任務執行,導致兩個不同的執行緒訪問同一段程式碼,導致出錯。解決辦法是,上一次下載失敗時,除了關閉service也要cancel掉非同步下載任務的request。

OkHttpClient mOkHttpClient = new OkHttpClient();
// 啟動非同步執行緒訪問網路
public static void enqueue(Request request, Callback responseCallback, GetCallCancelCallback callback) {
        Call call = mOkHttpClient.newCall(request);
        callback.getCall(call);
        call.enqueue(responseCallback);
    }

一下是下載介面,傳入下載的URL,儲存路徑,以及回撥。

// 下載介面
public static void download(String downloadUrl, final String distPath, final DownloadCallback callback) {
        Request request = new Request.Builder().url(downloadUrl).build();
        enqueue(request, new Callback() {
            @Override
            public void onResponse(Response response) {
                if (response.isSuccessful()) {
                    try {
                        InputStream is = response.body().byteStream();
                        long totalSize = response.body().contentLength();
                        FileOutputStream fos = new FileOutputStream(distPath);
                        int len = 0;
                        long downloadSize = 0;
                        byte[] buffer = new byte[1024 * 8];
                        while ((len = is.read(buffer)) != -1) {
                            downloadSize += len;
                            callback.onDownload(downloadSize, totalSize);
                            fos.write(buffer, 0, len);
                        }
                        if (callback != null) {
                            callback.onSuccess(null);
                            return;
                        }
                    } catch (IOException e) {
                        if (callback != null) {
                            callback.onFail(null);
                        }
                    }
                }
                if (callback != null) {
                    callback.onFail(null);
                }
            }

            @Override
            public void onFailure(Request request, IOException arg1) {
                if (callback != null) {
                    callback.onFail(null);
                }
            }
        }, new GetCallCancelCallback() {
            @Override
            public void getCall(Call call) {
                callback.onGetCall(call);  //回撥,取得此時的Call
            }
        });
    }


// service中的關鍵程式碼
download(url, filePath, new NetUtils.DownloadCallback() {
                @Override
                public void onSuccess(String result) {

                     downloadFinish();
                }

                @Override
                public void onDownload(final long downloadSize, final long totalSize) {
                   
                    mHandler.post(new Runnable() {
                        @Override
                        public void run() {
                            EventBus.getDefault().post(new DownloadProgressEvent(downloadSize / 1024, totalSize / 1024));
                        }
                    });
                }

                @Override
                public void onFail(String errorInfo) {
                    //刪掉該檔案
                    LogUtils.error("onDowloadFail", "onDowloadFail");
                    File file = new File(filePath);
                    if (file.exists()) {
                        file.delete();
                    }

                  
                    downloadFinish();
                }

                @Override
                public void onTimeout() {

                    downloadFinish();
                }

                @Override
                public void onGetCall(Call call) {
                    setCall(call);
                }
            });

// 關閉service,取消執行緒中的下載任務
private void downloadFinish() {
        mHandler.post(new Runnable() {
            @Override
            public void run() {
                isRunning = false;
                LogUtils.error("Service", mCall.toString());
                if (mCall != null) {
                    mCall.cancel(); // 取消當前的request
                }
                LogUtils.error("Service", "stop");
                stopSelf();
            }
        });

    }