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

service done #76

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
1 change: 1 addition & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service android:name=".DownloadService" android:exported="false"/>
</application>

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

import android.app.IntentService;
import android.content.Context;
import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;

import java.io.File;
import java.io.IOException;

/**
* Created by 6yry6e on 21.01.2016.
*/
public class DownloadService extends IntentService implements ProgressCallback {
public static final String ACTION_DOWNLOAD = "ru.ifmo.android_2015.homework5.action.DOWNLOAD";
public static final String ACTION_BROADCAST = "ru.ifmo.android.2015.homework5.action.BROADCAST";
public static final String URL_PARAMETER = "ru.ifmo.android.2015.homework5.extra.URL";
public static final String TITLE_PARAMETER = "ru.ifmo.android.2015.homework5.extra.TITLE";
public static final String PROGRESS_PARAMETER = "ru.ifmo.android.2015.homework5.extra.PROGRESS";

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 DownloadState state;
private int progress;

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

public static void addDownload(Context context, String URL) {
Intent intent = new Intent(context, DownloadService.class)
.setAction(ACTION_DOWNLOAD)
.putExtra(URL_PARAMETER, URL);
context.startService(intent);
}

@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
final String action = intent.getAction();
if (action.equals(ACTION_DOWNLOAD)) {
final String URL_param = intent.getStringExtra(URL_PARAMETER);
this.state = DownloadState.DOWNLOADING;
progress = 0;
publishProgress();
try {
download_File(URL_param);
} catch (IOException e) {
this.state = DownloadState.ERROR;
publishProgress();
return;
}
this.state = DownloadState.DONE;
this.progress = 100;
publishProgress();
}
}
}

private void download_File(String URL) throws IOException {
File destination = FileUtils.createTempExternalFile(this, ".gz");
DownloadUtils.downloadFile(URL, destination, this);
}

@Override
public void onProgressChanged(int progress) {
this.progress = progress;
publishProgress();
}

private void publishProgress() {
Intent intent = new Intent(ACTION_BROADCAST)
.putExtra(TITLE_PARAMETER, this.state.titleResId)
.putExtra(PROGRESS_PARAMETER, this.progress);
LocalBroadcastManager.getInstance(this).sendBroadcast(intent);
}
}
185 changes: 43 additions & 142 deletions app/src/main/java/ru/ifmo/android_2015/homework5/InitSplashActivity.java
Original file line number Diff line number Diff line change
@@ -1,16 +1,16 @@
package ru.ifmo.android_2015.homework5;

import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.os.AsyncTask;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.support.v4.content.LocalBroadcastManager;
import android.util.Log;
import android.widget.ProgressBar;
import android.widget.TextView;

import java.io.File;
import java.io.IOException;

/**
* Экран, выполняющий инициализацию при первом запуске приложения. В процессе инициализации
* скачивается файл с данными, нужными для работы приложения. Пока идет инициализация, показывается
Expand All @@ -22,13 +22,11 @@ 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 static final String TAG = "InitSplash";
private static final String TITLE_TEXT = "TITLE_TEXT";
private ProgressBar progressBarView;
// Заголовок
private TextView titleTextView;
// Выполняющийся таск загрузки файла
private DownloadFileTask downloadTask;
private BroadcastReceiver receiver;

@Override
@SuppressWarnings("deprecation")
Expand All @@ -43,149 +41,52 @@ protected void onCreate(Bundle savedInstanceState) {
progressBarView.setMax(100);

if (savedInstanceState != null) {
// Пытаемся получить ранее запущенный таск
downloadTask = (DownloadFileTask) getLastNonConfigurationInstance();
}
if (downloadTask == null) {
// Создаем новый таск, только если не было ранее запущенного таска
downloadTask = new DownloadFileTask(this);
downloadTask.execute();
Log.d(TAG, "Service is already working");
} else {
// Передаем в ранее запущенный таск текущий объект Activity
downloadTask.attachActivity(this);
DownloadService.addDownload(this, CITIES_GZ_URL);
Log.d(TAG, "Download started");
}
}
receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Progress updated");
updateView(intent);
}
};

@Override
@SuppressWarnings("deprecation")
public Object onRetainNonConfigurationInstance() {
// Этот метод вызывается при смене конфигурации, когда текущий объект
// Activity уничтожается. Объект, который мы вернем, не будет уничтожен,
// и его можно будет использовать в новом объекте Activity
return downloadTask;
IntentFilter intentFilter = new IntentFilter(DownloadService.ACTION_BROADCAST);
LocalBroadcastManager.getInstance(this)
.registerReceiver(receiver, intentFilter);
}

/**
* Состояние загрузки в 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 void updateView (Intent intent) {
if (intent != null) {
final int title = intent.getIntExtra(DownloadService.TITLE_PARAMETER, 0);
final int progress = intent.getIntExtra(DownloadService.PROGRESS_PARAMETER, 0);
titleTextView.setText(title);
progressBarView.setProgress(progress);
}
}

/**
* Таск, выполняющий скачивание файла в фоновом потоке.
*/
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);
}

// Метод 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();
@Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
if (savedInstanceState != null) {
String label = savedInstanceState.getString(TITLE_TEXT);
titleTextView.setText(label);
}
}

/**
* Скачивает список городов во временный файл.
*/
static void downloadFile(Context context,
ProgressCallback progressCallback) throws IOException {
File destFile = FileUtils.createTempExternalFile(context, "gz");
DownloadUtils.downloadFile(CITIES_GZ_URL, destFile, progressCallback);
@Override
protected void onSaveInstanceState(Bundle outState) {
outState.putString(TITLE_TEXT, titleTextView.getText().toString());
super.onSaveInstanceState(outState);
}

private static final String TAG = "InitSplash";
}
@Override
protected void onDestroy() {
LocalBroadcastManager.getInstance(this)
.unregisterReceiver(receiver);
super.onDestroy();
}
}