AlarmManager и BroadcastReceiver вместо службы-это плохо? (Таймаут)
СПРАВОЧНАЯ ИНФОРМАЦИЯ:
мне нужно обновить некоторые данные из интернета, примерно каждый час или около того, даже когда мое приложение закрывается. Обновление данных занимает около 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.класс!--5--> заботится об обновлении данных из интернета:
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...
}
}
в Манифесте у меня есть :
<receiver android:name="com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA" android:process=":remote" />
:
будильник срабатывает вовремя, и обновление начинается, но затем примерно через 10 секунд он останавливается (тайм-аут):
06-25 11:55:05.278: WARN/ActivityManager (76): время ожидания трансляции BroadcastRecord{44bb4348 ноль} - приемник=андроид.ОС.BinderProxy@44bcc670
06-25 11:55:05.278: Предупреждение / 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: пульт дистанционного управления (pid 819) умер.
ps: как ни странно, этот "тайм-аут" не происходит примерно через 10 секунд на моем HTC Hero (все еще на Android 1.5 - API Level 4), но хорошо на моем Nexus One (2.1-update1)
вопросы :
- почему этот тайм-аут ? Есть простой способ избежать этого ?
- правильно ли я настроил свой BroadcastReceiver в манифесте ? Нужно ли мне что-то добавить (чтобы избежать этого тайм-аута) ?
- должен ли я абсолютно пойти на службу для такого рода Функциональность "обновить из интернета"? (рассматривая эту статью:http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) Если да (я должен переключиться на службу): любые хорошие фрагменты кода/учебника для этого ...
как всегда, спасибо за вашу помощь.
Х.
3 ответов
почему этот тайм-аут ?
вы работаете в основном потоке приложения. Вы не можете работать в основном потоке приложения более нескольких секунд. Кроме того, делая это, вы вредите производительности устройства (потому что вы запуск с приоритетом переднего плана), например, вызывая потерю частоты кадров в играх или видео.
любой простой способ избежать этого ?
не делайте значительную работу (>100мс) в главном потоке приложения. Ваш BroadcastReceiver
передать IntentService
, возможно a WakefulIntentService
.
Я настроил свой BroadcastReceiver правильно в манифесте ?
пожалуйста, пожалуйста, пожалуйста, пожалуйста, пожалуйста, избавьтесь от android:process=:remote
. Вам это не нужно, это вам не помогает, и это ухудшает производительность устройства еще больше.
Я должен поехать на сервис для такого рода "обновления из интернета" функциональность ? (учитывая это статья : http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) Если да (я должен переключиться на службу): Любые хорошие фрагменты кода / tutorial для этот...
ИМХО, да. Опять же, я написал этот пост в блоге. Пример см. В разделе 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 для более чистого/более устойчивого подхода...
давайте посмотрим, работает ли новое решение потока всегда хорошо или просто повезло (у меня проверял только в течение пары часов) ...
Если у кого-то еще есть другое предложение, пожалуйста, опубликуйте его.
вместо ниток. Вы можете запустить AsyncTask из вашего широковещательного приемника onRecive() метод. Это не будет блокировать поток пользовательского интерфейса. Я сам сделал то же самое в своих проектах, которые имеют тот же характер, т. е. он должен публиковать данные каждые 1 час.
public void onReceive(Context context, Intent intent) {
// start your Asynctask from here. which will post data in doInBackground() method
}