2010-06-25 8 views
13

ФОН INFO:AlarmManager и BroadcastReceiver вместо службы - это плохо? (Таймаут)

мне нужно обновить некоторые данные из Интернета, примерно каждый час или около того, даже когда мое приложение закрыто. Обновление самих данных занимает от 40 секунд до 1 минуты. Затем он сохраняется как Serializable для файла. Этот файл читается при запуске моего приложения.

ЭТО ПОДХОД Я ВЗЯЛ НА МОМЕНТ (не используя службы)

использовать 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... 
    } 
} 

В манифесте у меня есть:

<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} - [email protected]

06-25 11: 55: 05,278: WARN/ActivityManager (76): Приемник во время тайм-аута: ResolveInfo {44bb42c0 com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA р = 0 о = 0 м = 0x0}

06-25 11: 55: 05.278: INFO/Process (76): Сигнал отправки. ПИД: 819 Sig: 9

06-25 11: 55: 05,298: ИНФОРМАЦИЯ/ActivityManager (76): Процесс com.cousinHub.myapp: удаленный (PID 819) умер.

пс: как ни странно, это "Тайм-аут" не происходит примерно через 10 секунд на моем HTC Hero (до сих пор на Android 1.5 - Уровень API 4), а также на моем Nexus One (2,1-Update1)

Вопросы:

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

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

H.

ответ

18

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

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

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

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

Я правильно настроил свой трансляционный приемник в манифесте?

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

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

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

+0

и WakefulIntentService смогут «жить» более 30 секунд и обновлять все мои данные? будет ли он иметь доступ к файлу, который будет читать мое приложение? – Hubert

+0

"и WakefulIntentService сможет« жить »более 30 секунд и обновлять все мои данные?» ['IntentService'] (http://developer.android.com/reference/android/app/IntentService.html) будет жить так долго, как ваш' onHandleIntent() '(или' doWakefulWork() 'в' WakefulIntentService') выполняет свою работу. «будет ли у него доступ к файлу, который будет читать мое приложение?» Как и ваш «BroadcastReceiver» сегодня, предположительно. Обратите внимание, что я не являюсь вам и поэтому не писал ваш код, поэтому я понятия не имею, что этот «файл, который будет читать мое приложение». – CommonsWare

+0

Последний вопрос, если я могу: как лучше всего получить доступ к контексту приложения (mContext => возможно, «Контекст mContext = (Контекст) getApplicationContext();») в AppService.doWakefulWork? Целью является доступ к моим приложениям «Предпочтения» с pref = PreferenceManager.getDefaultSharedPreferences (mContext); и мои файлы с «FileOutputStream fOut = mContext.openFileOutput (Globals.mFileName, Context.MODE_WORLD_READABLE); – Hubert

1

Для информации, я попытался с новым потоком, и он работает, когда на 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 в для более чистого/более устойчивого подхода ...

Давайте посмотрим, работает ли новое решение нитей хорошо или просто удача (I ' проверено только в течение пары часов) ...

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

+0

новое решение нити не всегда работайте, поэтому избегайте! Тогда пойдем на решение CommonsWare. – Hubert

0

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

public void onReceive(Context context, Intent intent) { 
     // start your Asynctask from here. which will post data in doInBackground() method 
}