diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..7619236 --- /dev/null +++ b/.gitignore @@ -0,0 +1,28 @@ +### Android template +# Files for the Dalvik VM +*.dex + +# Java class files +*.class + +# Generated files +bin/ +gen/ + +# Gradle files +.gradle/ +build/ + +# Local configuration file (sdk path, etc) +local.properties + +# Proguard folder generated by Eclipse +proguard/ + +# Log Files +*.log + +# Android Studio Navigation editor temp files +.navigation/ + +# Created by .ignore support plugin (hsz.mobi) \ No newline at end of file diff --git a/.idea/.name b/.idea/.name new file mode 100644 index 0000000..c833642 --- /dev/null +++ b/.idea/.name @@ -0,0 +1 @@ +homework5 \ No newline at end of file diff --git a/.idea/compiler.xml b/.idea/compiler.xml new file mode 100644 index 0000000..9a8b7e5 --- /dev/null +++ b/.idea/compiler.xml @@ -0,0 +1,22 @@ + + + + + \ No newline at end of file diff --git a/.idea/copyright/profiles_settings.xml b/.idea/copyright/profiles_settings.xml new file mode 100644 index 0000000..e7bedf3 --- /dev/null +++ b/.idea/copyright/profiles_settings.xml @@ -0,0 +1,3 @@ + + + \ No newline at end of file diff --git a/.idea/gradle.xml b/.idea/gradle.xml new file mode 100644 index 0000000..8d2df47 --- /dev/null +++ b/.idea/gradle.xml @@ -0,0 +1,18 @@ + + + + + + \ No newline at end of file diff --git a/.idea/libraries/appcompat_v7_23_0_1.xml b/.idea/libraries/appcompat_v7_23_0_1.xml new file mode 100644 index 0000000..7898213 --- /dev/null +++ b/.idea/libraries/appcompat_v7_23_0_1.xml @@ -0,0 +1,12 @@ + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/support_annotations_23_0_1.xml b/.idea/libraries/support_annotations_23_0_1.xml new file mode 100644 index 0000000..4b8b4ab --- /dev/null +++ b/.idea/libraries/support_annotations_23_0_1.xml @@ -0,0 +1,11 @@ + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/libraries/support_v4_23_0_1.xml b/.idea/libraries/support_v4_23_0_1.xml new file mode 100644 index 0000000..f35583b --- /dev/null +++ b/.idea/libraries/support_v4_23_0_1.xml @@ -0,0 +1,13 @@ + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/misc.xml b/.idea/misc.xml new file mode 100644 index 0000000..95f0f03 --- /dev/null +++ b/.idea/misc.xml @@ -0,0 +1,46 @@ + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/.idea/modules.xml b/.idea/modules.xml new file mode 100644 index 0000000..384adf8 --- /dev/null +++ b/.idea/modules.xml @@ -0,0 +1,9 @@ + + + + + + + + + \ No newline at end of file diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml new file mode 100644 index 0000000..7f68460 --- /dev/null +++ b/.idea/runConfigurations.xml @@ -0,0 +1,12 @@ + + + + + + \ No newline at end of file diff --git a/.idea/vcs.xml b/.idea/vcs.xml new file mode 100644 index 0000000..35eb1dd --- /dev/null +++ b/.idea/vcs.xml @@ -0,0 +1,6 @@ + + + + + + \ No newline at end of file diff --git a/.idea/workspace.xml b/.idea/workspace.xml new file mode 100644 index 0000000..231bdf9 --- /dev/null +++ b/.idea/workspace.xml @@ -0,0 +1,2002 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + localhost + 5050 + + + + + + + 1451251915537 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/app.iml b/app/app.iml new file mode 100644 index 0000000..63a8c51 --- /dev/null +++ b/app/app.iml @@ -0,0 +1,97 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml index 34fb554..2ae00ab 100644 --- a/app/src/main/AndroidManifest.xml +++ b/app/src/main/AndroidManifest.xml @@ -18,6 +18,9 @@ + + diff --git a/app/src/main/java/ru/ifmo/android_2015/homework5/Downloader.java b/app/src/main/java/ru/ifmo/android_2015/homework5/Downloader.java new file mode 100644 index 0000000..c9479a9 --- /dev/null +++ b/app/src/main/java/ru/ifmo/android_2015/homework5/Downloader.java @@ -0,0 +1,79 @@ +package ru.ifmo.android_2015.homework5; + +import android.app.IntentService; +import android.content.Intent; +import android.support.v4.content.LocalBroadcastManager; + +import java.io.File; +import java.io.IOException; + +/** + * Created by anton on 28/12/15. + */ +public class Downloader extends IntentService implements ProgressCallback { + + public static final String ACTION_DOWNLOAD = "ru.ifmo.android_2015.homework5.action.DOWNLOAD"; + public static final String BROADCAST_ACTION = "ru.ifmo.android_2015.homework5.action.BROADCAST"; + public static final String PARAM_URL = "ru.ifmo.android_2015.homework5.extra.URL"; + public static final String PARAM_TITLE = "ru.ifmo.android_2015.homework5.extra.TITLE"; + public static final String PARAM_PROGRESS = "ru.ifmo.android_2015.homework5.extra.PROGRESS"; + + private int progress; + private DownloadState downloadState; + + public Downloader() { + super("Downloader"); + } + + @Override + protected void onHandleIntent(Intent intent) { + if (intent == null) { + return; + } + + final String action = intent.getAction(); + if(action.equals(ACTION_DOWNLOAD)) { + final String paramURL = intent.getStringExtra(PARAM_URL); + this.downloadState = DownloadState.DOWNLOADING; + progress = 0; + broadcastProgress(); + try { + File destination = FileUtils.createTempExternalFile(this, ".gz"); + DownloadUtils.downloadFile(paramURL, destination, this); + } catch (IOException e) { + this.downloadState = DownloadState.FAILED; + broadcastProgress(); + return; + } + this.downloadState = DownloadState.COMPLETED; + this.progress = 100; + broadcastProgress(); + } + } + + @Override + public void onProgressChanged(int progress) { + this.progress = progress; + broadcastProgress(); + } + + private void broadcastProgress() { + Intent intent = new Intent(BROADCAST_ACTION); + intent.putExtra(PARAM_TITLE, this.downloadState.titleResID); + intent.putExtra(PARAM_PROGRESS, this.progress); + LocalBroadcastManager.getInstance(this).sendBroadcast(intent); + } + + enum DownloadState { + DOWNLOADING(R.string.downloading), + COMPLETED(R.string.done), + FAILED(R.string.error); + + final int titleResID; + + DownloadState(int titleResID) { + this.titleResID = titleResID; + } + + } +} diff --git a/app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java b/app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java index 8810d30..2b48c9d 100644 --- a/app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java +++ b/app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java @@ -1,9 +1,14 @@ package ru.ifmo.android_2015.homework5; import android.app.Activity; +import android.app.ActivityManager; +import android.content.BroadcastReceiver; import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; import android.os.AsyncTask; import android.os.Bundle; +import android.support.v4.content.LocalBroadcastManager; import android.util.Log; import android.widget.ProgressBar; import android.widget.TextView; @@ -23,12 +28,12 @@ public class InitSplashActivity extends Activity { private static final String CITIES_GZ_URL = "https://www.dropbox.com/s/d99ky6aac6upc73/city_array.json.gz?dl=1"; + private static final String TITLE = "TITLE"; // Индикатор прогресса private ProgressBar progressBarView; // Заголовок private TextView titleTextView; - // Выполняющийся таск загрузки файла - private DownloadFileTask downloadTask; + private BroadcastReceiver receiver; @Override @SuppressWarnings("deprecation") @@ -43,149 +48,68 @@ protected void onCreate(Bundle savedInstanceState) { progressBarView.setMax(100); if (savedInstanceState != null) { - // Пытаемся получить ранее запущенный таск - downloadTask = (DownloadFileTask) getLastNonConfigurationInstance(); + Log.d(TAG, "Service has started"); } - if (downloadTask == null) { - // Создаем новый таск, только если не было ранее запущенного таска - downloadTask = new DownloadFileTask(this); - downloadTask.execute(); - } else { - // Передаем в ранее запущенный таск текущий объект Activity - downloadTask.attachActivity(this); + else if (!isRunning(Downloader.class)) { + Log.d(TAG, "Download started"); + Intent intent = new Intent(this, Downloader.class); + intent.setAction(Downloader.ACTION_DOWNLOAD); + intent.putExtra(Downloader.PARAM_URL, CITIES_GZ_URL); + startService(intent); } - } - - @Override - @SuppressWarnings("deprecation") - public Object onRetainNonConfigurationInstance() { - // Этот метод вызывается при смене конфигурации, когда текущий объект - // Activity уничтожается. Объект, который мы вернем, не будет уничтожен, - // и его можно будет использовать в новом объекте Activity - return downloadTask; - } - - /** - * Состояние загрузки в DownloadFileTask - */ - enum DownloadState { - DOWNLOADING(R.string.downloading), - DONE(R.string.done), - ERROR(R.string.error); - - // ID строкового ресурса для заголовка окна прогресса - final int titleResId; - - DownloadState(int titleResId) { - this.titleResId = titleResId; - } - } - - /** - * Таск, выполняющий скачивание файла в фоновом потоке. - */ - static class DownloadFileTask extends AsyncTask - implements ProgressCallback { - - // Context приложения (Не Activity!) для доступа к файлам - private Context appContext; - // Текущий объект Activity, храним для обновления отображения - private InitSplashActivity activity; - - // Текущее состояние загрузки - private DownloadState state = DownloadState.DOWNLOADING; - // Прогресс загрузки от 0 до 100 - private int progress; - - DownloadFileTask(InitSplashActivity activity) { - this.appContext = activity.getApplicationContext(); - this.activity = activity; + else { + Log.d(TAG, "Waiting for runnig service to finish"); } - - /** - * Этот метод вызывается, когда новый объект Activity подключается к - * данному таску после смены конфигурации. - * - * @param activity новый объект Activity - */ - void attachActivity(InitSplashActivity activity) { - this.activity = activity; - updateView(); - } - - /** - * Вызываем на UI потоке для обновления отображения прогресса и - * состояния в текущей активности. - */ - void updateView() { - if (activity != null) { - activity.titleTextView.setText(state.titleResId); - activity.progressBarView.setProgress(progress); + receiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + updateView(intent); } - } + }; + IntentFilter filter = new IntentFilter(Downloader.BROADCAST_ACTION); + LocalBroadcastManager.getInstance(this).registerReceiver(receiver, filter); + } - /** - * Вызывается в UI потоке из execute() до начала выполнения таска. - */ - @Override - protected void onPreExecute() { - updateView(); + private void updateView(Intent intent) { + if (intent == null) { + return; } + final int titleID = intent.getIntExtra(Downloader.PARAM_TITLE, 0); + final int progress = intent.getIntExtra(Downloader.PARAM_PROGRESS, 0); + titleTextView.setText(titleID); + progressBarView.setProgress(progress); + } - /** - * Скачивание файла в фоновом потоке. Возвращает результат: - * 0 -- если файл успешно скачался - * 1 -- если произошла ошибка - */ - @Override - protected DownloadState doInBackground(Void... ignore) { - try { - downloadFile(appContext, this /*progressCallback*/); - state = DownloadState.DONE; - - } catch (Exception e) { - Log.e(TAG, "Error downloading file: " + e, e); - state = DownloadState.ERROR; - } - return state; - } + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putString(TITLE, titleTextView.getText().toString()); + super.onSaveInstanceState(outState); + } - // Метод ProgressCallback, вызывается в фоновом потоке из downloadFile - @Override - public void onProgressChanged(int progress) { - publishProgress(progress); + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + super.onRestoreInstanceState(savedInstanceState); + if (savedInstanceState != null) { + String s = savedInstanceState.getString(TITLE); + titleTextView.setText(s); } + } - // Метод AsyncTask, вызывается в UI потоке в результате вызова publishProgress - @Override - protected void onProgressUpdate(Integer... values) { - if (values.length > 0) { - int progress = values[values.length - 1]; - this.progress = progress; - updateView(); - } - } + @Override + protected void onDestroy() { + Log.d(TAG, "Destroy"); + LocalBroadcastManager.getInstance(this).unregisterReceiver(receiver); + super.onDestroy(); + } - @Override - protected void onPostExecute(DownloadState state) { - // Проверяем код, который вернул doInBackground и показываем текст в зависимости - // от результата - this.state = state; - if (state == DownloadState.DONE) { - progress = 100; + private boolean isRunning(Class service) { + ActivityManager manager = (ActivityManager) getSystemService(Context.ACTIVITY_SERVICE); + for (ActivityManager.RunningServiceInfo serviceInfo : manager.getRunningServices(Integer.MAX_VALUE)) { + if (service.getName().equals(serviceInfo.service.getClassName())) { + return true; } - updateView(); } + return false; } - - /** - * Скачивает список городов во временный файл. - */ - static void downloadFile(Context context, - ProgressCallback progressCallback) throws IOException { - File destFile = FileUtils.createTempExternalFile(context, "gz"); - DownloadUtils.downloadFile(CITIES_GZ_URL, destFile, progressCallback); - } - private static final String TAG = "InitSplash"; } diff --git a/homework5.iml b/homework5.iml new file mode 100644 index 0000000..ca2428e --- /dev/null +++ b/homework5.iml @@ -0,0 +1,19 @@ + + + + + + + + + + + + + + + + + \ No newline at end of file