我正在重构一些代码,以便我的应用程序每天在给定时间从网站提取数据。从我的研究来看,似乎AlarmManager
是最合适的方法。
我一直关注的教程是:http://mobile.tutsplus.com/tutorials/android/android-fundamentals-downloading-data-with-services/
到目前为止,AlarmManager
和BroadcastReceiver
似乎正在运作,但Service
似乎永远不会启动(即。onStartCommand
似乎没有被调用)
以下是我到目前为止代码的重要摘要:
MyActivity.java
private void setRecurringAlarm(Context context) {
Calendar updateTime = Calendar.getInstance();
updateTime.setTimeZone(TimeZone.getDefault());
updateTime.set(Calendar.HOUR_OF_DAY, 20);
updateTime.set(Calendar.MINUTE, 30);
Intent downloader = new Intent(context, AlarmReceiver.class);
downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// should be AlarmManager.INTERVAL_DAY (but changed to 15min for testing)
alarmManager.setRepeating(AlarmManager.RTC_WAKEUP, updateTime.getTimeInMillis(), AlarmManager.INTERVAL_FIFTEEN_MINUTES, pendingIntent);
Log.d("MyActivity", "Set alarmManager.setRepeating to: " + updateTime.getTime().toLocaleString());
}
AlarmReceiver.java
public class AlarmReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Intent dailyUpdater = new Intent(context, MyService.class);
context.startService(dailyUpdater);
Log.d("AlarmReceiver", "Called context.startService from AlarmReceiver.onReceive");
}
}
MyService.java
public class MyService extends Service {
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d("MyService", "About to execute MyTask");
new MyTask().execute();
return Service.START_FLAG_REDELIVERY;
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
private class MyTask extends AsyncTask<String, Void, boolean> {
@Override
protected boolean doInBackground(String... strings) {
Log.d("MyService - MyTask", "Calling doInBackground within MyTask");
return false;
}
}
}
的AndroidManifest.xml
<application ...>
...
<service android:name="MyService"></service>
<receiver android:name="AlarmReceiver"></receiver>
</application>
当我在setRecurringAlarm
中触发MyActivity
时,日志按预期打印,同样,每隔15分钟,AlarmReceiver
的日志就会出现。但是,我从未见过MyService
的日志:(
我在日志中看到的示例:
DEBUG/MyActivity(688): Set alarmManager.setRepeating to: Jan 29, 2012 8:30:06 PM
DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive
DEBUG/AlarmReceiver(688): Called context.startService from AlarmReceiver.onReceive
似乎无法弄清楚我做错了什么 - 我对Android Dev Docs的理解是AlarmReceiver
当context.startService(dailyUpdater)
打电话给onStartCommand
时应该调用MyService
在MyService
中,虽然情况似乎并非如此!
我做错了什么导致{{1}}根本无法启动?
答案 0 :(得分:15)
想出来了!
MyService 应该扩展 IntentService ,而不是服务!
通过此更改,这也意味着代替覆盖onStartCommand
而不是覆盖onHandleIntent
(请参阅IntentService上的文档)
所以 MyService 现在看起来像这样:
public class MyService extends IntentService {
public MyService() {
super("MyServiceName");
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d("MyService", "About to execute MyTask");
new MyTask().execute();
}
private class MyTask extends AsyncTask<String, Void, boolean> {
@Override
protected boolean doInBackground(String... strings) {
Log.d("MyService - MyTask", "Calling doInBackground within MyTask");
return false;
}
}
}
注意:从文档中,onBind
的默认实现会返回null
,因此无需覆盖它。
有关延长IntentService
的更多信息:http://developer.android.com/guide/topics/fundamentals/services.html#ExtendingIntentService
答案 1 :(得分:0)
如果你改变你的意图,你可以让AlarmManager立即运行服务,而不是通过BroadcastReceiver:
//Change the intent
Intent downloader = new Intent(context, MyService.class);
downloader.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
//Change to getService()
PendingIntent pendingIntent = PendingIntent.getService(context, 0, downloader, PendingIntent.FLAG_CANCEL_CURRENT);
这可以解决您的问题!
答案 2 :(得分:0)
而不是使用
Intent dailyUpdater = new Intent(context, MyService.class);
使用
Intent dailyUpdater = new Intent(this, MyService.class);
其他建议是直接从闹钟开始服务,而不是发送广播并在广播接收器中启动服务。