ИНФОРМАЦИЯ О ФОНЕ:
Я должен обновить некоторые данные из сети о каждом часе или так, даже когда мое приложение закрывается. Обновление самих данных занимает приблизительно 40 секунд к 1 минуте. Это затем сохраняется как сериализуемое в файл. Этот файл читается, когда мое приложение запускается.
ЭТО - ПОДХОД, который я ПРОЯВИЛ В НАСТОЯЩИЙ МОМЕНТ (не использующий Сервис)
используйте AlarmManager и BroadcastReceiver как это:
private void set_REFRESH_DATA_Alarm(){
mContext = Main.this;
alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
broadcast_intent = new Intent(mContext,
RepeatingAlarmReceiver_REFRESH_DATA.class);
pendingIntent = PendingIntent.getBroadcast(mContext, 0, broadcast_intent, 0);
// do a REFRESH every hour, starting for the first time in 30 minutes from now ...
Calendar now = Calendar.getInstance();
long triggerAtTime = now.getTimeInMillis()+ (1 * 30 * 60 * 1000); // starts in 30 minutes
long repeat_alarm_every = (1 * 60 * 60 * 1000); // repeat every 60 minutes
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, triggerAtTime,
repeat_alarm_every, pendingIntent);
}
Мой RepeatingAlarmReceiver_REFRESH_DATA.class заботится об обновлении Данных из сети:
public class RepeatingAlarmReceiver_REFRESH_DATA extends BroadcastReceiver {
public static Context mContext;
ConnectivityManager mConnectivity;
@Override
public void onReceive(Context context, Intent intent) {
mContext = context;
// if Network connection is OK (Wifi or Mobile) then Load data ...
mConnectivity = (ConnectivityManager) context
.getSystemService(Context.CONNECTIVITY_SERVICE);
Log.i("Hub",
"mConnectivity.getNetworkInfo(0)="
+ mConnectivity.getNetworkInfo(0));
Log.i("Hub",
"mConnectivity.getNetworkInfo(1)="
+ mConnectivity.getNetworkInfo(1));
if ((mConnectivity.getNetworkInfo(0).getState() == NetworkInfo.State.CONNECTED)
|| (mConnectivity.getNetworkInfo(1).getState() == NetworkInfo.State.CONNECTED)) {
Log.i("Hub", "Connectivity OK ...");
Refresh_HIST_DATA();
} else {
// else Show Dialog "No network connection" ...
Log.i("Hub",
"No network connection for the moment... will try again later!");
}
}
// =========================================================================
private void Refresh_HIST_DATA() {
Log.i("Hub", "Refresh_HIST_DATA()... Starting ...");
// etc...
}
}
В Декларации я имею:
ПРОБЛЕМА:
Предупреждение запущено вовремя, и обновление запускается, но затем приблизительно после 10 секунд оно останавливается (Тайм-аут):
06-25 11:55:05.278: WARN/ActivityManager (76): Тайм-аут широковещательной передачи BroadcastRecord {44bb4348 пустой указатель} - receiver=android.os. BinderProxy@44bcc670
06-25 11:55:05.278: WARN/ActivityManager (76): Получатель во время тайм-аута: ResolveInfo {44bb42c0 com.cousinHub.myapp. RepeatingAlarmReceiver_REFRESH_DATA p=0 o=0 m=0x0}
06-25 11:55:05.278: ИНФОРМАЦИЯ/ПРОЦЕСС (76): Отправка сигнала. PID: 819 SIG: 9
06-25 11:55:05.298: INFO/ActivityManager (76): com.cousinHub.myapp:remote Процесса (pid 819) умер.
PS: странно достаточно этого "Тайм-аута" не происходит приблизительно после 10 секунд на моем HTC Hero (все еще на Android 1.5 - уровень API 4), но хорошо на моем (2.1-update1) Nexus One
Вопросы:
Как всегда, спасибо за Вашу справку.
H.
Почему этот тайм-аут?
Вы работаете в основном потоке приложения. Вы не можете работать в основном потоке приложения дольше нескольких секунд. Кроме того, при этом вы снижаете производительность устройства (потому что вы работаете с приоритетом переднего плана ), например, вызывая потерю частоты кадров в играх или видео.
Есть ли простой способ избежать этого?
Не выполняйте значительную работу (> 100 мс) в основном потоке приложения. Пусть ваш BroadcastReceiver
делегирует IntentService
, возможно, WakefulIntentService
.
Настроил ли я свой BroadcastReceiver? правильно в манифесте?
Пожалуйста, пожалуйста, пожалуйста, избавьтесь от android: process =: remote
. Он вам не нужен, он вам не помогает и еще больше снижает производительность устройства.
Стоит ли мне обращаться за Услугами? для такого рода «Обновить из Интернета» функциональность? (учитывая это статья : http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/ ) Если ДА (я должен переключиться на услугу): Любые хорошие фрагменты кода / учебника для это ...
ИМХО, да. Опять же, я написал это сообщение в блоге. Для примера см. Проект WakefulIntentService
.
Для информации, я попробовал с новым потоком, и он работает, когда на Wifi (занимает около 1'30" для обновления данных, когда телефон спит, он не "убивается"!
//let's try with a new separate thread ?
new Thread(new Runnable() {
public void run() {
Refresh_HIST_DATA();
}
}).start();
но НЕ работает на мобильном (GPRS), так как его убивают примерно через 10 секунд!
На данный момент это полурешение, и я попробую решение CommonsWare для более чистого/более устойчивого подхода...
Посмотрим, работает ли решение с новым потоком всегда хорошо или это просто удача (я тестировал только в течение пары часов) ...
Если у кого-то есть другое предложение, пожалуйста, опубликуйте его.