19d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanpackage com.android.pmc;
29d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
39d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.app.AlarmManager;
49d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.app.PendingIntent;
59d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.content.BroadcastReceiver;
69d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.content.Context;
79d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.content.Intent;
89d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.os.AsyncTask;
99d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.os.PowerManager;
109d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.os.SystemClock;
119d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport android.util.Log;
129d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
139d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport java.io.InputStream;
149d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport java.net.HttpURLConnection;
159d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanimport java.net.URL;
169d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan/**
179d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan * Call wifi Download data whenever an alarm is received.
189d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan */
199d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tanpublic class WifiDownloadReceiver extends BroadcastReceiver {
209d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private static final int DOWNLOAD_BUFFER_SIZE = 1024 * 4;
219d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
229d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    DownloadTask mDownloadTask;
239d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    PMCMainActivity mPMCMainActivity;
249d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    int mFileCount;
259d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    int mBytesCount;
269d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    long mDownloadStartTime;
279d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    String mDownloadURL;
289d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private Context mContext;
299d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private PowerManager.WakeLock mWakeLock;
309d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private int mAlarmInterval;
319d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private AlarmManager mAlarmManager;
329d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    private PendingIntent mAlarmIntent;
339d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
349d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public WifiDownloadReceiver(PMCMainActivity activity, String url, int interval,
359d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                                AlarmManager alarmManager, PendingIntent alarmIntent) {
369d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mPMCMainActivity = activity;
379d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mDownloadURL = url;
389d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mFileCount = 0;
399d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mBytesCount = 0;
409d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mDownloadStartTime = -1;
419d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mAlarmInterval = interval;
429d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mAlarmManager = alarmManager;
439d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mAlarmIntent = alarmIntent;
449d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
459d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
469d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    @Override
479d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public void onReceive(Context context, Intent intent) {
489d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        if (mDownloadTask != null && mDownloadTask.getStatus() != AsyncTask.Status.FINISHED) {
499d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.e(PMCMainActivity.TAG, "Previous download still running.");
509d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            try {
519d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                mDownloadTask.get();
529d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } catch (Exception e) {
539d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(PMCMainActivity.TAG, "Download cancelled.");
549d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
559d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        } else {
569d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mContext = context;
579d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
589d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "WIFITEST");
599d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            // Acquire the lock
609d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mWakeLock.acquire();
619d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.i(PMCMainActivity.TAG, "Starting Download Task");
629d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mDownloadTask = new DownloadTask();
639d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mDownloadTask.execute(mDownloadURL);
649d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
659d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        scheduleDownload();
669d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
679d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
689d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    /**
699d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * Schedule the next download.
709d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     */
719d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public void scheduleDownload() {
729d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        if (mDownloadStartTime == -1) {
739d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            // Note down the start of all download activity
749d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mDownloadStartTime = System.currentTimeMillis();
759d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
769d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        Log.i(PMCMainActivity.TAG, "Scheduling the next download after " + mAlarmInterval);
779d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mAlarmManager.setAndAllowWhileIdle(AlarmManager.ELAPSED_REALTIME_WAKEUP,
789d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                SystemClock.elapsedRealtime() + mAlarmInterval, mAlarmIntent);
799d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
809d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
819d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    /**
829d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * Cancel the downloads.
839d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     */
849d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public void cancelDownload() {
859d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        mAlarmManager.cancel(mAlarmIntent);
869d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        if (mDownloadTask != null) mDownloadTask.cancel(true);
879d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
889d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
899d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    /**
909d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * Returns an approximate data rate at which we're downloading the files.
919d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     * @return
929d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan     */
939d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    public int getDownloadRate() {
949d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        long durationInMilliSeconds = (System.currentTimeMillis() - mDownloadStartTime);
959d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        int durationInSeconds = (int) (durationInMilliSeconds / 1000);
969d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        return (mBytesCount / durationInSeconds);
979d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
989d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
999d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    class DownloadTask extends AsyncTask<String, Integer, String> {
1009d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        @Override
1019d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        protected String doInBackground(String... sUrl) {
1029d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            //android.os.Debug.waitForDebugger();
1039d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(PMCMainActivity.TAG, "Starting background task for downloading file");
1049d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            HttpURLConnection connection = null;
1059d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            try {
1069d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                URL url = new URL(sUrl[0]);
1079d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                connection = (HttpURLConnection) url.openConnection();
1089d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                connection.connect();
1099d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                // expect HTTP 200 OK, so we don't mistakenly save error report
1109d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                // instead of the file
1119d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                if (connection.getResponseCode() != HttpURLConnection.HTTP_OK) {
1129d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    return "Server returned HTTP " + connection.getResponseCode()
1139d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                            + " " + connection.getResponseMessage();
1149d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                }
1159d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                // this will be useful to display download percentage
1169d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                // might be -1: server did not report the length
1179d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                int fileLength = connection.getContentLength();
1189d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                int bytesRead = downloadFile(connection);
1199d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                if (fileLength != bytesRead) {
1209d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    return "Expected file of size " + fileLength + " but only received "
1219d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                            + bytesRead;
1229d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                }
1239d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.d(PMCMainActivity.TAG, "Downloaded file size " + fileLength);
1249d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                mFileCount += 1;
1259d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                mBytesCount += fileLength;
1269d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                publishProgress(mFileCount, getDownloadRate());
1279d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Thread.sleep(10000);
1289d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } catch (Exception e) {
1299d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(PMCMainActivity.TAG, e.toString());
1309d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                return e.toString();
1319d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } finally {
1329d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                if (connection != null) {
1339d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    connection.disconnect();
1349d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                }
1359d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
1369d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            return null;
1379d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1389d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1399d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        @Override
1409d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        protected void onCancelled(String result) {
1419d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mWakeLock.release();
1429d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1439d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1449d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        @Override
1459d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        protected void onProgressUpdate(Integer... values) {
1469d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            Log.d(PMCMainActivity.TAG, "DownloadTask onProgressUpdate updating the UI");
1479d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mPMCMainActivity.updateProgressStatus("Total file downloaded :: "
1489d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    + values[0].toString() + ", Data rate :: "
1499d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    + values[1].toString() + " bytes/sec");
1509d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1519d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1529d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        @Override
1539d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        protected void onPostExecute(String error) {
1549d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (error != null) {
1559d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(PMCMainActivity.TAG, error);
1569d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                mPMCMainActivity.updateProgressStatus(error);
1579d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
1589d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            mWakeLock.release();
1599d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1609d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan
1619d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        private int downloadFile(HttpURLConnection connection) {
1629d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            if (connection == null) return -1;
1639d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            int totalBytesRead = 0;
1649d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            InputStream inputStream = null;
1659d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            // Just read out the input file, not saving it anywhere in the device
1669d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            try {
1679d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                inputStream = connection.getInputStream();
1689d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                int bytesRead = -1;
1699d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                byte[] buffer = new byte[DOWNLOAD_BUFFER_SIZE];
1709d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                while ((bytesRead = inputStream.read(buffer)) != -1) {
1719d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    totalBytesRead += bytesRead;
1729d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                }
1739d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } catch (Exception e) {
1749d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                Log.e(PMCMainActivity.TAG, "Downloaded failed");
1759d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            } finally {
1769d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                try {
1779d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    if (inputStream != null) inputStream.close();
1789d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                } catch (Exception e) {
1799d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                    Log.e(PMCMainActivity.TAG, "Downloaded close failed");
1809d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan                }
1819d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            }
1829d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan            return totalBytesRead;
1839d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan        }
1849d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan    }
1859d0b4a0f0eed60322b3b48d67c56567c547a92c6Jim Tan}
186