/* * This source is part of the * _____ ___ ____ * __ / / _ \/ _ | / __/___ _______ _ * / // / , _/ __ |/ _/_/ _ \/ __/ _ `/ * \___/_/|_/_/ |_/_/ (_)___/_/ \_, / * /___/ * repository. * * Copyright (C) 2014-2015 Carmen Alvarez (c@rmen.ca) * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package ca.rmen.android.networkmonitor.app.speedtest; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.net.MalformedURLException; import java.net.URL; import java.net.URLConnection; import android.net.TrafficStats; import android.os.AsyncTask; import android.support.annotation.NonNull; import ca.rmen.android.networkmonitor.Constants; import ca.rmen.android.networkmonitor.app.speedtest.SpeedTestResult.SpeedTestStatus; import ca.rmen.android.networkmonitor.util.Log; /** * Downloads a file and calculates the download speed. */ public class SpeedTestDownload { private static final String TAG = Constants.TAG + SpeedTestDownload.class.getSimpleName(); // The maximum connection and read timeout private static final int TIMEOUT = 5000; interface SpeedTestDownloadCallback { void onSpeedTestResult(@NonNull SpeedTestResult result); } public static void download(SpeedTestDownloadConfig config, SpeedTestDownloadCallback callback) { new AsyncTask<SpeedTestDownloadConfig, Void, SpeedTestResult>(){ @Override protected SpeedTestResult doInBackground(SpeedTestDownloadConfig... speedTestDownloadConfigs) { return download(speedTestDownloadConfigs[0]); } @Override protected void onPostExecute(@NonNull SpeedTestResult speedTestResult) { callback.onSpeedTestResult(speedTestResult); } }.execute(config); } @NonNull public static SpeedTestResult download(SpeedTestDownloadConfig config) { Log.v(TAG, "download " + config); URL url; try { url = new URL(config.url); } catch (MalformedURLException e) { Log.e(TAG, "download: incorrect url " + config.url, e); return new SpeedTestResult(0, 0, 0, SpeedTestStatus.INVALID_FILE); } SpeedTestStatus status = SpeedTestStatus.UNKNOWN; InputStream inputStream = null; OutputStream outputStream = null; long totalRead = 0; long before = System.currentTimeMillis(); long rxBytesBefore = TrafficStats.getTotalRxBytes(); try { URLConnection connection = url.openConnection(); Log.v(TAG, "Opened connection"); outputStream = new FileOutputStream(config.file); connection.setConnectTimeout(TIMEOUT); connection.setReadTimeout(TIMEOUT); connection.addRequestProperty("Cache-Control", "no-cache"); connection.setUseCaches(false); Log.v(TAG, "Will open input stream"); inputStream = connection.getInputStream(); byte[] buffer = new byte[1048576]; int read; do { read = inputStream.read(buffer); if (read > 0) outputStream.write(buffer, 0, read); totalRead += read; } while (read > 0); if (totalRead > 0) status = SpeedTestStatus.SUCCESS; long after = System.currentTimeMillis(); long rxBytesAfter = TrafficStats.getTotalRxBytes(); SpeedTestResult result = new SpeedTestResult(rxBytesAfter - rxBytesBefore, totalRead, after - before, status); Log.v(TAG, "success: " + result); return result; } catch (Throwable t) { Log.d(TAG, "download: Caught an exception", t); long after = System.currentTimeMillis(); return new SpeedTestResult(0, totalRead, after - before, SpeedTestStatus.FAILURE); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { Log.w(TAG, "download: Could not close stream", e); } } if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { Log.w(TAG, "download: Could not close stream", e); } } Log.v(TAG, "download: END"); } } }