14

背景资料:

即使我的应用程序关闭,我也需要大约每小时左右更新一次网络上的一些数据。数据本身的更新大约需要 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.class负责从 Web 更新数据:

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} 超时-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 级别 4 上)大约 10 秒后不会发生,但在我的 Nexus One(2.1-update1)上很好

问题 :

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

一如既往,感谢您的帮助。

H。

4

3 回答 3

18

为什么这个超时?

您正在主应用程序线程上运行。您不能在主应用程序线程上运行超过几秒钟。此外,在这样做的同时,您会损害设备的性能(因为您正在以前台优先级运行),例如导致游戏或视频中的帧率丢失。

有什么简单的方法可以避免这种情况吗?

不要在主应用程序线程上做大量工作(>100ms)。让你的BroadcastReceiver代表参加一个IntentService,也许是一个WakefulIntentService

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

拜托拜托拜托请摆脱android:process=:remote。你不需要它,它对你没有帮助,它会进一步降低设备的性能。

我绝对应该为这种“从 Web 刷新”功能寻求服务吗?(考虑这篇文章: http ://www.androidguys.com/2009/09/09/diamonds-are-forever-services-are-not/ )如果是(我应该切换到服务):任何好的代码片段/本教程...

恕我直言,是的。再一次,我写了那篇博客文章。例如,请参阅WakefulIntentService项目。

于 2010-06-25T11:37:09.903 回答
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 的解决方案,以实现更清洁/更可持续的方法......

让我们看看新的线程解决方案是一直正常工作还是只是运气好(我只测试了几个小时)......

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

于 2010-06-25T13:49:20.283 回答
0

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

public void onReceive(Context context, Intent intent) {
        // start your Asynctask from here. which will post data in doInBackground() method
}
于 2012-08-28T06:56:20.817 回答