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

hw5 #66

Open
wants to merge 2 commits into
base: master
Choose a base branch
from
Open

hw5 #66

Changes from 1 commit
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
Prev Previous commit
activity changed with usage of service
baba-beda committed Dec 27, 2015
commit 960dde27e3f249aab0170cf70e95ce58bf989193
77 changes: 60 additions & 17 deletions .idea/workspace.xml

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

3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
@@ -18,6 +18,9 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>

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

</manifest>
188 changes: 56 additions & 132 deletions app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java
Original file line number Diff line number Diff line change
@@ -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<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;
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";
}