Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Garbage fixed #67

Open
wants to merge 1 commit into
base: master
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .idea/encodings.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

19 changes: 19 additions & 0 deletions .idea/gradle.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

12 changes: 12 additions & 0 deletions .idea/libraries/appcompat_v7_23_0_1.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 11 additions & 0 deletions .idea/libraries/support_annotations_23_0_1.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

13 changes: 13 additions & 0 deletions .idea/libraries/support_v4_23_0_1.xml

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

11 changes: 8 additions & 3 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -2,22 +2,27 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="ru.ifmo.android_2015.homework5" >

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:supportsRtl="true"
android:theme="@style/AppTheme" >

<activity android:name=".InitSplashActivity" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

<service
android:name=".DownloadService"
android:exported="false" >
</service>
</application>

</manifest>
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
package ru.ifmo.android_2015.homework5;

import android.app.IntentService;
import android.content.Intent;

public class DownloadService extends IntentService {

public DownloadService() {
super("DownloadService");
}

@Override
protected void onHandleIntent(Intent intent) {
try {
InitSplashActivity.downloadFile(this, new ProgressCallback() {
@Override
public void onProgressChanged(int progress) {
publishProgress(InitSplashActivity.DownloadState.DOWNLOADING, progress);
}
});
publishProgress(InitSplashActivity.DownloadState.DONE, 100);
} catch (Exception e) {
publishProgress(InitSplashActivity.DownloadState.ERROR, 100);
}
}

private void publishProgress(InitSplashActivity.DownloadState state, int progress) {
Intent intent = new Intent(InitSplashActivity.FILTER);
intent.putExtra(InitSplashActivity.STATE, state);
intent.putExtra(InitSplashActivity.PROGRESS, progress);
sendBroadcast(intent);
}
}
166 changes: 53 additions & 113 deletions app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
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.AsyncTask;
import android.os.Bundle;
import android.util.Log;
Expand All @@ -22,13 +25,16 @@ 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";
public static final String STATE = "state";
public static final String PROGRESS = "progress";
public static final String FILTER = "filter";

// Индикатор прогресса
private ProgressBar progressBarView;
// Заголовок
private TextView titleTextView;
// Выполняющийся таск загрузки файла
private DownloadFileTask downloadTask;
private DownloadState downloadState;
private BroadcastReceiver broadcastReceiver;

@Override
@SuppressWarnings("deprecation")
Expand All @@ -41,28 +47,32 @@ protected void onCreate(Bundle savedInstanceState) {
progressBarView = (ProgressBar) findViewById(R.id.progress_bar);

progressBarView.setMax(100);

if (savedInstanceState != null) {
// Пытаемся получить ранее запущенный таск
downloadTask = (DownloadFileTask) getLastNonConfigurationInstance();
if (savedInstanceState == null) {
downloadState = DownloadState.DOWNLOADING;
Intent intent = new Intent(this, DownloadService.class);
startService(intent);
}
if (downloadTask == null) {
// Создаем новый таск, только если не было ранее запущенного таска
downloadTask = new DownloadFileTask(this);
downloadTask.execute();
} else {
// Передаем в ранее запущенный таск текущий объект Activity
downloadTask.attachActivity(this);
if (downloadState != DownloadState.DONE) {
broadcastReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
switch ((DownloadState)intent.getSerializableExtra(STATE)) {
case DONE:
case ERROR:
unregisterReceiver(this);
break;
default:
updateView((DownloadState)intent.getSerializableExtra(STATE), intent.getIntExtra(PROGRESS, 0));
}
}
};
registerReceiver(broadcastReceiver, new IntentFilter(FILTER));
}
}

@Override
@SuppressWarnings("deprecation")
public Object onRetainNonConfigurationInstance() {
// Этот метод вызывается при смене конфигурации, когда текущий объект
// Activity уничтожается. Объект, который мы вернем, не будет уничтожен,
// и его можно будет использовать в новом объекте Activity
return downloadTask;
private void updateView(DownloadState state, int progress) {
titleTextView.setText(state.titleResId);
progressBarView.setProgress(progress);
}

/**
Expand All @@ -81,103 +91,33 @@ enum DownloadState {
}
}

/**
* Таск, выполняющий скачивание файла в фоновом потоке.
*/
static class DownloadFileTask extends AsyncTask<Void, Integer, DownloadState>
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);
}
@Override
public void onSaveInstanceState(Bundle outBundle) {
outBundle.putInt(PROGRESS, progressBarView.getProgress());
outBundle.putSerializable(STATE, downloadState);
super.onSaveInstanceState(outBundle);
}

// Метод AsyncTask, вызывается в UI потоке в результате вызова publishProgress
@Override
protected void onProgressUpdate(Integer... values) {
if (values.length > 0) {
int progress = values[values.length - 1];
this.progress = progress;
updateView();
}
}
@Override
public void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
downloadState = (DownloadState)savedInstanceState.getSerializable(STATE);
updateView(downloadState, savedInstanceState.getInt(PROGRESS));
}

@Override
protected void onPostExecute(DownloadState state) {
// Проверяем код, который вернул doInBackground и показываем текст в зависимости
// от результата
this.state = state;
if (state == DownloadState.DONE) {
progress = 100;
}
updateView();
}
@Override
public void onDestroy() {
super.onDestroy();
try {
unregisterReceiver(broadcastReceiver);
} catch (Exception e) {}
}

@Override
@SuppressWarnings("deprecation")
public Object onRetainNonConfigurationInstance() {
return broadcastReceiver;
}
/**
* Скачивает список городов во временный файл.
*/
Expand Down