diff --git a/app/src/main/AndroidManifest.xml b/AndroidManifest.xml similarity index 94% rename from app/src/main/AndroidManifest.xml rename to AndroidManifest.xml index 34fb554..98d1d9d 100644 --- a/app/src/main/AndroidManifest.xml +++ b/AndroidManifest.xml @@ -11,6 +11,7 @@ android:label="@string/app_name" android:supportsRtl="true" android:theme="@style/AppTheme" > + diff --git a/app/build.gradle b/app/build.gradle deleted file mode 100644 index c410692..0000000 --- a/app/build.gradle +++ /dev/null @@ -1,24 +0,0 @@ -apply plugin: 'com.android.application' - -android { - compileSdkVersion 23 - buildToolsVersion "23.0.1" - - defaultConfig { - applicationId "ru.ifmo.android_2015.homework_5" - minSdkVersion 14 - targetSdkVersion 23 - versionCode 1 - versionName "1.0" - } - buildTypes { - release { - minifyEnabled false - proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro' - } - } -} - -dependencies { - compile 'com.android.support:appcompat-v7:23.0.1' -} diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro deleted file mode 100644 index b9cb4cd..0000000 --- a/app/proguard-rules.pro +++ /dev/null @@ -1,17 +0,0 @@ -# Add project specific ProGuard rules here. -# By default, the flags in this file are appended to flags specified -# in C:\devtools\android\sdk/tools/proguard/proguard-android.txt -# You can edit the include path and order by changing the proguardFiles -# directive in build.gradle. -# -# For more details, see -# http://developer.android.com/guide/developing/tools/proguard.html - -# Add any project specific keep options here: - -# If your project uses WebView with JS, uncomment the following -# and specify the fully qualified class name to the JavaScript interface -# class: -#-keepclassmembers class fqcn.of.javascript.interface.for.webview { -# public *; -#} 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 deleted file mode 100644 index 8810d30..0000000 --- a/app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java +++ /dev/null @@ -1,191 +0,0 @@ -package ru.ifmo.android_2015.homework5; - -import android.app.Activity; -import android.content.Context; -import android.os.AsyncTask; -import android.os.Bundle; -import android.util.Log; -import android.widget.ProgressBar; -import android.widget.TextView; - -import java.io.File; -import java.io.IOException; - -/** - * Экран, выполняющий инициализацию при первом запуске приложения. В процессе инициализации - * скачивается файл с данными, нужными для работы приложения. Пока идет инициализация, показывается - * сплэш-скрин с индикатором прогресса. - */ -public class InitSplashActivity extends Activity { - - // Урл для скачивания файла с данными, нужными для инициализации приложения при первом запуске. - // GZIP-архив, содержащий список городов в формате JSON. - private static final String CITIES_GZ_URL = - "https://www.dropbox.com/s/d99ky6aac6upc73/city_array.json.gz?dl=1"; - - // Индикатор прогресса - private ProgressBar progressBarView; - // Заголовок - private TextView titleTextView; - // Выполняющийся таск загрузки файла - private DownloadFileTask downloadTask; - - @Override - @SuppressWarnings("deprecation") - protected void onCreate(Bundle savedInstanceState) { - Log.d(TAG, "onCreate"); - super.onCreate(savedInstanceState); - setContentView(R.layout.activity_init_splash); - - titleTextView = (TextView) findViewById(R.id.title_text); - progressBarView = (ProgressBar) findViewById(R.id.progress_bar); - - progressBarView.setMax(100); - - if (savedInstanceState != null) { - // Пытаемся получить ранее запущенный таск - downloadTask = (DownloadFileTask) getLastNonConfigurationInstance(); - } - if (downloadTask == null) { - // Создаем новый таск, только если не было ранее запущенного таска - downloadTask = new DownloadFileTask(this); - downloadTask.execute(); - } else { - // Передаем в ранее запущенный таск текущий объект Activity - downloadTask.attachActivity(this); - } - } - - @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; - } - - /** - * Этот метод вызывается, когда новый объект 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); - } - } - - /** - * Вызывается в UI потоке из execute() до начала выполнения таска. - */ - @Override - protected void onPreExecute() { - updateView(); - } - - /** - * Скачивание файла в фоновом потоке. Возвращает результат: - * 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; - } - - // Метод ProgressCallback, вызывается в фоновом потоке из downloadFile - @Override - public void onProgressChanged(int progress) { - publishProgress(progress); - } - - // Метод 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 onPostExecute(DownloadState state) { - // Проверяем код, который вернул doInBackground и показываем текст в зависимости - // от результата - this.state = state; - if (state == DownloadState.DONE) { - progress = 100; - } - updateView(); - } - } - - /** - * Скачивает список городов во временный файл. - */ - 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/build.gradle b/build.gradle deleted file mode 100644 index be515a8..0000000 --- a/build.gradle +++ /dev/null @@ -1,23 +0,0 @@ -// Top-level build file where you can add configuration options common to all sub-projects/modules. - -buildscript { - repositories { - jcenter() - } - dependencies { - classpath 'com.android.tools.build:gradle:1.3.0' - - // NOTE: Do not place your application dependencies here; they belong - // in the individual module build.gradle files - } -} - -allprojects { - repositories { - jcenter() - } -} - -task clean(type: Delete) { - delete rootProject.buildDir -} diff --git a/gradle.properties b/gradle.properties deleted file mode 100644 index 1d3591c..0000000 --- a/gradle.properties +++ /dev/null @@ -1,18 +0,0 @@ -# Project-wide Gradle settings. - -# IDE (e.g. Android Studio) users: -# Gradle settings configured through the IDE *will override* -# any settings specified in this file. - -# For more details on how to configure your build environment visit -# http://www.gradle.org/docs/current/userguide/build_environment.html - -# Specifies the JVM arguments used for the daemon process. -# The setting is particularly useful for tweaking memory settings. -# Default value: -Xmx10248m -XX:MaxPermSize=256m -# org.gradle.jvmargs=-Xmx2048m -XX:MaxPermSize=512m -XX:+HeapDumpOnOutOfMemoryError -Dfile.encoding=UTF-8 - -# When configured, Gradle will run in incubating parallel mode. -# This option should only be used with decoupled projects. More details, visit -# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects -# org.gradle.parallel=true \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties deleted file mode 100644 index c4e6155..0000000 --- a/gradle/wrapper/gradle-wrapper.properties +++ /dev/null @@ -1,6 +0,0 @@ -#Sun Oct 18 19:27:55 MSK 2015 -distributionBase=GRADLE_USER_HOME -distributionPath=wrapper/dists -zipStoreBase=GRADLE_USER_HOME -zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.4-all.zip diff --git a/java/ru/ifmo/android_2015/homework5/DownloadService.java b/java/ru/ifmo/android_2015/homework5/DownloadService.java new file mode 100644 index 0000000..c4e13a3 --- /dev/null +++ b/java/ru/ifmo/android_2015/homework5/DownloadService.java @@ -0,0 +1,47 @@ +package ru.ifmo.android_2015.homework5; + +import android.app.IntentService; +import android.content.Context; +import android.content.Intent; +import android.util.Log; + +import java.io.File; +import java.io.IOException; + + +public class DownloadService extends IntentService { + public DownloadService() { + super("name"); + } + + @Override + protected void onHandleIntent(Intent intent) { + String url = intent.getStringExtra("url"); + try { + downloadFile(this, url, new ProgressCallback() { + @Override + public void onProgressChanged(int progress) { + sendBroadcast(InitSplashActivity.DownloadState.DOWNLOADING, progress); + } + }); + sendBroadcast(InitSplashActivity.DownloadState.DONE, 100); + } catch (IOException e) { + Log.e("DownloadService", "Failed to download file"); + sendBroadcast(InitSplashActivity.DownloadState.ERROR, 100); + e.printStackTrace(); + } + } + + private void sendBroadcast(InitSplashActivity.DownloadState state, int progress) { + Intent intent = new Intent("MyFilter"); + intent. putExtra("state", state); + intent.putExtra("progress", progress); + sendBroadcast(intent); + } + + static void downloadFile(Context context, String url, + ProgressCallback progressCallback) throws IOException { + File destFile = FileUtils.createTempExternalFile(context, "gz"); + DownloadUtils.downloadFile(url, destFile, progressCallback); + } +} diff --git a/app/src/main/java/ru/ifmo/android_2015/homework5/DownloadUtils.java b/java/ru/ifmo/android_2015/homework5/DownloadUtils.java similarity index 100% rename from app/src/main/java/ru/ifmo/android_2015/homework5/DownloadUtils.java rename to java/ru/ifmo/android_2015/homework5/DownloadUtils.java diff --git a/app/src/main/java/ru/ifmo/android_2015/homework5/FileUtils.java b/java/ru/ifmo/android_2015/homework5/FileUtils.java similarity index 100% rename from app/src/main/java/ru/ifmo/android_2015/homework5/FileUtils.java rename to java/ru/ifmo/android_2015/homework5/FileUtils.java diff --git a/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java b/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java new file mode 100644 index 0000000..e65913f --- /dev/null +++ b/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java @@ -0,0 +1,125 @@ +package ru.ifmo.android_2015.homework5; + +import android.app.Activity; +import android.content.BroadcastReceiver; +import android.content.Context; +import android.content.Intent; +import android.content.IntentFilter; +import android.os.Bundle; +import android.util.Log; +import android.view.View; +import android.widget.ProgressBar; +import android.widget.TextView; + +/** + * Экран, выполняющий инициализацию при первом запуске приложения. В процессе инициализации + * скачивается файл с данными, нужными для работы приложения. Пока идет инициализация, показывается + * сплэш-скрин с индикатором прогресса. + */ +public class InitSplashActivity extends Activity { + + // Урл для скачивания файла с данными, нужными для инициализации приложения при первом запуске. + // GZIP-архив, содержащий список городов в формате JSON. + private static final String CITIES_GZ_URL = + "https://www.dropbox.com/s/d99ky6aac6upc73/city_array.json.gz?dl=1"; + + // Индикатор прогресса + private ProgressBar progressBarView; + // Заголовок + private TextView titleTextView; + + public DownloadState downloadState; + int progress; + private BroadcastReceiver broadcastReceiver; + + @Override + @SuppressWarnings("deprecation") + protected void onCreate(Bundle savedInstanceState) { + Log.d(TAG, "onCreate"); + super.onCreate(savedInstanceState); + setContentView(R.layout.activity_init_splash); + + titleTextView = (TextView) findViewById(R.id.title_text); + progressBarView = (ProgressBar) findViewById(R.id.progress_bar); + + progressBarView.setMax(100); + if (savedInstanceState == null) { + downloadState = DownloadState.DOWNLOADING; + progress = 0; + Intent intent = new Intent(this, DownloadService.class); + intent.putExtra("url", CITIES_GZ_URL); + startService(intent); + } else { + downloadState = (DownloadState) savedInstanceState.getSerializable("state"); + progress = savedInstanceState.getInt("progress"); + updateView(downloadState, progress); + } + + if (downloadState == DownloadState.DOWNLOADING) { + broadcastReceiver = new BroadcastReceiver() { + @Override + public void onReceive(Context context, Intent intent) { + downloadState = (InitSplashActivity.DownloadState) intent.getSerializableExtra("state"); + progress = intent.getIntExtra("progress", 0); + if (downloadState == DownloadState.DONE || downloadState == DownloadState.ERROR) { + unregisterReceiver(this); + } + updateView(downloadState, progress); + } + + }; + registerReceiver(broadcastReceiver, new IntentFilter("MyFilter")); + } + } + + @Override + protected void onSaveInstanceState(Bundle outState) { + outState.putSerializable("state", downloadState); + outState.putInt("progress", progress); + super.onSaveInstanceState(outState); + } + + @Override + protected void onRestoreInstanceState(Bundle savedInstanceState) { + updateView(downloadState, progress); + super.onRestoreInstanceState(savedInstanceState); + } + + public void updateView(DownloadState state, int progress) { + titleTextView.setText(state.titleResId); + if (downloadState != DownloadState.DOWNLOADING) { + progressBarView.setVisibility(View.INVISIBLE); + } else { + progressBarView.setProgress(progress); + } + } + + @Override + protected void onDestroy() { + super.onDestroy(); + unregisterReceiver(broadcastReceiver); + } + + /** + * Состояние загрузки в 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; + } + } + + /** + * Скачивает список городов во временный файл. + */ + + + private static final String TAG = "InitSplash"; +} diff --git a/app/src/main/java/ru/ifmo/android_2015/homework5/ProgressCallback.java b/java/ru/ifmo/android_2015/homework5/ProgressCallback.java similarity index 100% rename from app/src/main/java/ru/ifmo/android_2015/homework5/ProgressCallback.java rename to java/ru/ifmo/android_2015/homework5/ProgressCallback.java diff --git a/app/src/main/res/drawable-xxhdpi/splash_bg.png b/res/drawable-xxhdpi/splash_bg.png similarity index 100% rename from app/src/main/res/drawable-xxhdpi/splash_bg.png rename to res/drawable-xxhdpi/splash_bg.png diff --git a/app/src/main/res/layout/activity_init_splash.xml b/res/layout/activity_init_splash.xml similarity index 100% rename from app/src/main/res/layout/activity_init_splash.xml rename to res/layout/activity_init_splash.xml diff --git a/app/src/main/res/mipmap-hdpi/ic_launcher.png b/res/mipmap-hdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-hdpi/ic_launcher.png rename to res/mipmap-hdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-mdpi/ic_launcher.png b/res/mipmap-mdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-mdpi/ic_launcher.png rename to res/mipmap-mdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xhdpi/ic_launcher.png b/res/mipmap-xhdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-xhdpi/ic_launcher.png rename to res/mipmap-xhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxhdpi/ic_launcher.png b/res/mipmap-xxhdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-xxhdpi/ic_launcher.png rename to res/mipmap-xxhdpi/ic_launcher.png diff --git a/app/src/main/res/mipmap-xxxhdpi/ic_launcher.png b/res/mipmap-xxxhdpi/ic_launcher.png similarity index 100% rename from app/src/main/res/mipmap-xxxhdpi/ic_launcher.png rename to res/mipmap-xxxhdpi/ic_launcher.png diff --git a/app/src/main/res/values/colors.xml b/res/values/colors.xml similarity index 100% rename from app/src/main/res/values/colors.xml rename to res/values/colors.xml diff --git a/app/src/main/res/values/strings.xml b/res/values/strings.xml similarity index 100% rename from app/src/main/res/values/strings.xml rename to res/values/strings.xml diff --git a/app/src/main/res/values/styles.xml b/res/values/styles.xml similarity index 100% rename from app/src/main/res/values/styles.xml rename to res/values/styles.xml diff --git a/settings.gradle b/settings.gradle deleted file mode 100644 index e7b4def..0000000 --- a/settings.gradle +++ /dev/null @@ -1 +0,0 @@ -include ':app'