AlarmManager和BroadcastReceiver而不是Service - 那很糟糕吗? (超时)

时间:2010-06-25 10:44:53

标签: android service broadcastreceiver alarmmanager

背景信息:

我需要大约每小时左右更新网络上的一些数据,即使我的应用已关闭。更新数据本身大约需要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...
    }
}

在Manifest中我有:

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

问题:

警报会按时触发并且更新开始,但是大约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:INFO / Process(76):   发送信号。 PID:819 SIG:9

     

06-25 11:55:05.298:   INFO / ActivityManager(76):进程   com.cousinHub.myapp:remote(pid 819)   已经死了。

ps:奇怪的是,在我的HTC Hero(仍然在Android 1.5 - API Level 4上)大约10秒后,这个“超时”不会发生,但在我的Nexus One(2.1-update1)

问题:

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

    小时。

3 个答案:

答案 0 :(得分: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项目。

答案 1 :(得分: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的解决方案,以实现更清洁/更可持续的方法......

让我们看一下新的线程解决方案是否能够正常运行,或者只是运气(我只在几个小时内测试过)...

如果其他人有其他建议,请发布。

答案 2 :(得分:0)

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

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