2010-06-25 121 views
13

背景资料:AlarmManager和BroadcastReceiver而不是服务 - 是不是很糟糕? (超时)

我需要从网络,大约每隔一小时左右,即使我的应用程序被关闭更新一些数据。数据更新本身大约需要40秒到1分钟。然后将它作为Serializable保存到文件中。当我的应用程序启动时读取此文件。

这个是我要做的时刻(不使用服务)

使用AlarmManager和广播接收器像这样的方法:

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]

11月6日至25日:55:05.278: WARN/ActivityManager(76):接收器 超时期间:ResolveInfo {44bb42c0 com.cousinHub.myapp.RepeatingAlarmReceiver_REFRESH_DATA p值= 0°= 0 M =为0x0}

06-25 11:55:05.278:INFO/Process(76): 发送信号。 PID:819 SIG:9

11月6日至25日:55:05.298: INFO/ActivityManager(76):进程 com.cousinHub.myapp:远程(PID 819) 已经死亡。

PS:奇怪的是,这个 “超时” 并不在我的HTC Hero(仍然在Android 1.5 - API等级4)约10秒后发生,但也对我的Nexus One(2.1 UPDATE1)

问题:

  1. 为什么超时?任何简单的方法来避免这一点?
  2. 我在清单中正确设置了我的BroadcastReceiver吗?我是否需要添加一些内容(以避免此超时)?
  3. 我是否应该绝对为这种“从网络刷新”功能提供服务? (考虑这篇文章:http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) 如果是(我应该切换到服务):任何好的代码片段/教程这个...

作为总之,感谢您的帮助。

H.

回答

18

为什么超时?

您正在主应用程序线程上运行。您不能在主应用程序线程上运行超过几秒钟。另外,在做这件事情时,你会损害设备的性能(因为你是running with foreground priority),例如在游戏或视频中造成帧率下降。

任何简单的方法来避免这种情况?

不要在主应用程序线程上做大量的工作(> 100ms)。请您的BroadcastReceiver代表IntentService,或许是WakefulIntentService

我在清单中正确设置了我的BroadcastReceiver 吗?

请请请请请摆脱android:process=:remote。您不需要它,它不会帮助您,并且会进一步降低设备的性能。

我应该绝对去服务 对于这种“从网页刷新” 功能? (考虑到这 文章: http://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/) 如果是(我应该切换到服务): 码/教程 此的任何一个好的片断...

恕我直言,是的。然后,我又写了那篇博文。有关示例,请参阅WakefulIntentService项目。

+0

和WakefulIntentService将能够“活”超过30秒并更新我的所有数据?它是否可以访问我的应用程序将读取的文件? – Hubert 2010-06-25 12:20:08

+0

“,WakefulIntentService将能够”活“超过30秒并更新我的所有数据?” ['IntentService'](http://developer.android.com/reference/android/app/IntentService.html)只要在'WakefulIntentService'中的'onHandleIntent()'(或'doWakefulWork()')正在开展工作。 “它会访问我的应用程序将读取的文件吗?”就像你今天的'BroadcastReceiver'一样,大概是这样。请注意,我不是你,因此没有写你的代码,所以我不知道这个“我的应用程序将读取的文件”是什么。 – CommonsWare 2010-06-25 12:28:34

+0

最后一个问题,如果我可以:如何在AppService.doWakefulWork内最好地访问应用上下文(mContext =>也许“Context mContext =(Context)getApplicationContext();”)?目标是通过“pref = PreferenceManager.getDefaultSharedPreferences(mContext)”访问我的应用程序首选项;“和我的文件“FileOutputStream fOut = mContext.openFileOutput(Globals.mFileName,Context.MODE_WORLD_READABLE);” – Hubert 2010-06-26 06:02:35

1

有关信息,我试图用一个新的线程,它工作时,在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的更清洁/更可持续的办法解决方案...让我们来看看新的线程解决方案是否可以正常工作或者只是运气(I'已经测试只在几个小时)...

如果其他人有另一个建议,请张贴它。

+0

新的线程解决方案不总是工作,所以避免!那么我们来看看CommonsWare的解决方案。 – Hubert 2010-06-26 03:02:37

0

而不是线程。您可以从广播接收器onRecive()方法启动AsyncTask。这不会阻塞UI线程。我自己也在我的项目中做过同样的事情,即它必须每隔1小时发布一次数据。

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