AlarmManager и BroadcastReceiver вместо Service - это плохо? (Тайм-аут) - PullRequest
14 голосов
/ 25 июня 2010

ОБЩАЯ ИНФОРМАЦИЯ:

Мне нужно обновлять некоторые данные из Интернета, примерно каждый час, даже когда мое приложение закрыто.Обновление самих данных занимает от 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);
}

My 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...
    }
}

В Манифесте, который у меня есть:

<receiver android:name="com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA" android:process=":remote" />

ПРОБЛЕМА:

Тревога срабатывает вовремя, и обновление начинается, но затем, примерно через 10 секунд, оно останавливается (Тайм-аут):

06-25 11: 55: 05.278: WARN / ActivityManager (76): тайм-аут широковещательной рассылки BroadcastRecord {44bb4348 null} - receive=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: INFO / Process (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-обновление1)

Вопросы:

  1. Почему этот тайм-аут?Есть ли простой способ избежать этого?
  2. Правильно ли я настроил свой BroadcastReceiver в манифесте?Нужно ли что-то добавлять (чтобы избежать этого тайм-аута)?
  3. Должен ли я обязательно обратиться за услугами для такого рода функций "Обновить из Интернета"?(учитывая эту статью: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) Если ДА (я должен переключиться на сервис): Любые хорошие фрагменты кода / учебник для этого ...

Как всегда, спасибо за вашу помощь.

H.

Ответы [ 3 ]

18 голосов
/ 25 июня 2010

Почему этот тайм-аут?

Вы работаете в главном потоке приложения.Вы не можете работать в главном потоке приложений дольше, чем на несколько секунд.Кроме того, при этом вы наносите ущерб производительности устройства (поскольку вы работаете с приоритетом переднего плана ), например, вызываете потерю частоты кадров в играх или видео.

Есть ли простой способ избежать этого?

Не выполнять значительную работу (> 100 мс) в главном потоке приложения.Ваш BroadcastReceiver делегат на IntentService, возможно, WakefulIntentService.

Правильно ли я настроил свой BroadcastReceiver в манифесте?

Пожалуйста, пожалуйста, пожалуйста, пожалуйста, избавьтесь от android:process=:remote.Вам это не нужно, оно вам не помогает, и это еще больше снижает производительность устройства.

Должен ли я обязательно обратиться за услугами для такого рода функций "Обновить из Интернета"?(учитывая эту статью: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) Если ДА (я должен переключиться на службу): любые хорошие фрагменты кода / учебника для этого ...

ИМХО, да. И снова,Я написал это сообщение в блоге. Например, см. Проект WakefulIntentService.

1 голос
/ 25 июня 2010

Для информации, я пробовал с новым потоком, и он работает, когда на Wi-Fi (требуется около 1 30 ", чтобы обновить данные, когда телефон спит, он не" убит "!

//let's try with a new separate thread ?
        new Thread(new Runnable() {
            public void run() {
                Refresh_HIST_DATA();
            }
          }).start();

но НЕ на мобильном телефоне (GPRS), так как его убивают примерно через 10 секунд!

На данный момент это полу-решение, и я попробую решение CommonsWare для более чистого / более устойчивого подхода ...

Давайте посмотрим, работает ли новое решение для потоков всегда нормально или это просто удача (я тестировал только пару часов) ...

Если у кого-то есть еще предложения, пожалуйста, оставьте их.

0 голосов
/ 28 августа 2012

вместо темы.Вы можете запустить AsyncTask с помощью метода onRecive () вашего широковещательного приемника.Это не будет блокировать поток пользовательского интерфейса.Я сам делал то же самое в своих проектах, которые имеют ту же природу, т.е. они должны публиковать данные каждые 1 час.

public void onReceive(Context context, Intent intent) {
        // start your Asynctask from here. which will post data in doInBackground() method
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...