我试图每30秒开始一次服务(即使应用程序关闭)。但它立即一个接一个地运行。我是第一次通过以下方式开始服务:
Intent i= new Intent(this, MyService.class);
this.startService(i);
我的服务是
public class MyService extends Service {
public static String READ_NEMAD_URL = "http://...";
@Override
public void onStart(Intent intent, int startId) {
ReadNemad task = new ReadNemad("GCAZ92");
task.execute();
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
Calendar cal = Calendar.getInstance();
Intent intent1 = new Intent(this, MyService.class);
PendingIntent pintent = PendingIntent.getService(this, 0, intent1, 0);
AlarmManager alarm = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
// Start every 30 seconds
alarm.setRepeating(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(),
30 * 1000, pintent);
}
private class ReadNemad extends AsyncTask<String, Void, String> {
//Do Somethings
return response;
}
@Override
public void onPostExecute(String response) {
stopSelf();
}
}
}
为什么服务本身运行?我怎样才能将其修复为每30秒运行一次?
答案 0 :(得分:2)
我试图每30秒开始一次服务(即使是 该应用程序已关闭)。但它会立即一个接一个地运行。
这是我认为非常错误的做法。服务(其来源)用于很长的任务和处理一些数据。它非常适合您希望拥有“永远”运行的案例。
您所描述的是正常行为 - 您可以非常简单地测试它 - 在设置中打开正在运行的服务,然后在任务管理器中关闭您的应用程序并快速查看您的服务 - 将在启动后立即停止。
所以我认为你的想法设计不好。如果你想每30秒启动一些代码片段,最好使用例如Handler(只有Handler或Handler in Service),好的指定BroadcastReceivers - 操纵发送正确的广播及其处理等
服务的主要目的是在后台运行,直到应用程序无法运行,您不应该尝试更改它(它不是非常有效)。
我想到的一种可能的方法(假设你想要每30秒做一次)是使用Handler并且每30秒发送一次新的广播就可以了。
答案 1 :(得分:1)
创建一个广播接收器,在接收到来自AlarmManager
的广播后启动您的服务:
public class SyncAlarm extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent data) {
// set alarm to start service
Calendar calendar = new GregorianCalendar();
calendar.setTimeInMillis(System.currentTimeMillis());
Calendar cal = new GregorianCalendar();
cal.set(Calendar.DAY_OF_YEAR, calendar.get(Calendar.DAY_OF_YEAR));
cal.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
// start service after an hour
cal.set(Calendar.MINUTE, calendar.get(Calendar.MINUTE) + 60);
cal.set(Calendar.SECOND, calendar.get(Calendar.SECOND));
cal.set(Calendar.MILLISECOND, calendar.get(Calendar.MILLISECOND));
cal.set(Calendar.DATE, calendar.get(Calendar.DATE));
cal.set(Calendar.MONTH, calendar.get(Calendar.MONTH));
// set alarm to start service again after receiving broadcast
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, SyncAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
am.cancel(pendingIntent);
am.set(AlarmManager.RTC, cal.getTimeInMillis(), pendingIntent);
intent = new Intent(context, Reminder.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startService(intent);
}
}
启动应用程序时第一次启动广播接收器:
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent intent = new Intent(context, SyncAlarm.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_ONE_SHOT);
am.cancel(pendingIntent);
am.set(AlarmManager.RTC, System.currentTimeMillis(), pendingIntent);
还要将此添加到您的清单文件:
<receiver android:name=".SyncAlarm" >
</receiver>
如果您希望在资源可用时立即由Android系统启动您的服务,而不是通过AlarmManager接收广播,那么您也应该参与此START_STICKY。
回答了类似的问题here。
答案 2 :(得分:0)
代码中的错误是将cal.getTimeInMillis()
放入setRepeating
。
AlarmManager
's documentation说:
triggerAtMillis - &gt;使用适当的时钟(取决于报警类型),报警首先应该以毫秒为单位的时间。
所以你强迫它“现在”开始。