使用 AlarmManager 定期启动服务
Start service periodically with AlarmManager
根据这些示例:here and here,我试图创建定期启动的服务。
首先我创建了服务:
public class MonitorService extends IntentService {
private static final String TAG = "MonitorService";
public MonitorService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d("TAG", "Service method was fired.");
}
}
接下来我创建了 Receiver:
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "MyReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "MyReceiver on receive");
Intent i = new Intent(context, MonitorService.class);
context.startService(i);
}
}
我在 MainActivity 中为此添加了启动方法:
public void scheduleAlarm() {
Intent intent = new Intent(getApplicationContext(), MyReceiver.class);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
long firstMillis = System.currentTimeMillis();
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// 1s is only for testing
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, 1000, pIntent);
}
这当然是在 onCreate
方法中调用的。
而且我没有忘记更改 AndroidManifest:
<receiver
android:name=".MyReceiver"
android:process=":remote" >
</receiver>
<service
android:name=".MonitorService"
android:exported="false" />
不幸的是,结果是我的日志中没有发生任何事情。
所以我有两个问题。
问题
- 如何解决无法启动服务的问题?
- 如果我将
scheduleAlarm
方法添加到 onCreate
它会在我每次启动我的应用程序时调用,仅在第一次启动应用程序时启动此方法的最佳方法是什么?
编辑
根据@Lasse 的提示,我开始调试,发现 Log.d 不工作,当我将其更改为 Log.i 时,记录了来自 MonitorService 的信息。
但是...调试不会在 MyReceiver 中的断点处停止,将 Log.d 更改为 Log.i 也没有帮助。当然 MonitorService 正在触发,这很奇怪。
此外,1000 毫秒的时间会导致每分钟触发一次服务,也许这是最短时间,现在更改为 AlarmManager.INTERVAL 并不重要。
编辑 2
我终于从服务和接收方都获得了日志。我试了很多次,之后就可以了,但我不知道为什么。
但是随之而来的另一个问题出现了——当我的服务是 运行
时我收到警告
W/art: Suspending all threads took: 21.787ms
我认为服务是 运行 背景,所以不管它有多长,我应该关注这个警告吗?
已编辑
关于第一个问题:
从 developer website
看到这个
setInexactRepeating(), you have to use one of the AlarmManager interval constants--in this case, AlarmManager.INTERVAL_DAY.
因此将您的 1000 更改为常量的使用
关于您的其他问题,您可以覆盖应用程序对象并在那里启动它。这样它只会在启动应用程序时被调用。
根据这些示例:here and here,我试图创建定期启动的服务。
首先我创建了服务:
public class MonitorService extends IntentService {
private static final String TAG = "MonitorService";
public MonitorService() {
super(TAG);
}
@Override
protected void onHandleIntent(Intent intent) {
Log.d("TAG", "Service method was fired.");
}
}
接下来我创建了 Receiver:
public class MyReceiver extends BroadcastReceiver {
private static final String TAG = "MyReceiver";
@Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "MyReceiver on receive");
Intent i = new Intent(context, MonitorService.class);
context.startService(i);
}
}
我在 MainActivity 中为此添加了启动方法:
public void scheduleAlarm() {
Intent intent = new Intent(getApplicationContext(), MyReceiver.class);
final PendingIntent pIntent = PendingIntent.getBroadcast(this, 0,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
long firstMillis = System.currentTimeMillis();
AlarmManager alarm = (AlarmManager) this.getSystemService(Context.ALARM_SERVICE);
// 1s is only for testing
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, 1000, pIntent);
}
这当然是在 onCreate
方法中调用的。
而且我没有忘记更改 AndroidManifest:
<receiver
android:name=".MyReceiver"
android:process=":remote" >
</receiver>
<service
android:name=".MonitorService"
android:exported="false" />
不幸的是,结果是我的日志中没有发生任何事情。
所以我有两个问题。
问题
- 如何解决无法启动服务的问题?
- 如果我将
scheduleAlarm
方法添加到onCreate
它会在我每次启动我的应用程序时调用,仅在第一次启动应用程序时启动此方法的最佳方法是什么?
编辑
根据@Lasse 的提示,我开始调试,发现 Log.d 不工作,当我将其更改为 Log.i 时,记录了来自 MonitorService 的信息。
但是...调试不会在 MyReceiver 中的断点处停止,将 Log.d 更改为 Log.i 也没有帮助。当然 MonitorService 正在触发,这很奇怪。
此外,1000 毫秒的时间会导致每分钟触发一次服务,也许这是最短时间,现在更改为 AlarmManager.INTERVAL 并不重要。
编辑 2
我终于从服务和接收方都获得了日志。我试了很多次,之后就可以了,但我不知道为什么。 但是随之而来的另一个问题出现了——当我的服务是 运行
时我收到警告 W/art: Suspending all threads took: 21.787ms
我认为服务是 运行 背景,所以不管它有多长,我应该关注这个警告吗?
已编辑
关于第一个问题: 从 developer website
看到这个 setInexactRepeating(), you have to use one of the AlarmManager interval constants--in this case, AlarmManager.INTERVAL_DAY.
因此将您的 1000 更改为常量的使用
关于您的其他问题,您可以覆盖应用程序对象并在那里启动它。这样它只会在启动应用程序时被调用。