背景信息:
我需要大约每小时左右更新网络上的一些数据,即使我的应用已关闭。更新数据本身大约需要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)
问题:
总之,谢谢你的帮助。
小时。
答案 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
}