我最近写了一个类似的东西,但是我决定不再让后台服务一直运行。毕竟操作系统可能会关闭它。我的做法是使用启动意图过滤器并设置闹钟,通过闹钟管理器以固定时间间隔重新启动我的应用程序,然后发送数据。在Android文档中可以找到关于服务和闹钟管理器的相关信息。
首先,我创建了一个广播接收器,当打开网络连接时简单地启动我的服务(因为我只对连接感兴趣 - 你可能还想过滤启动事件)。启动接收器必须是短暂的,所以只需启动您的服务即可。
public class LaunchReceiver extends BroadcastReceiver {
public static final String ACTION_PULSE_SERVER_ALARM =
"com.proofbydesign.homeboy.ACTION_PULSE_SERVER_ALARM";
@Override
public void onReceive(Context context, Intent intent) {
AppGlobal.logDebug("OnReceive for " + intent.getAction());
AppGlobal.logDebug(intent.getExtras().toString());
Intent serviceIntent = new Intent(AppGlobal.getContext(),
MonitorService.class);
AppGlobal.getContext().startService(serviceIntent);
}
}
在清单文件中,我有以下内容:
<receiver
android:name="LaunchReceiver"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
<intent-filter>
<action android:name="com.proofbydesign.homeboy.ACTION_PULSE_SERVER_ALARM" />
</intent-filter>
</receiver>
注意我为自己的闹钟设置了一个过滤器,这允许我在服务完成工作后关闭并重新启动它。
我的监视器服务顶部如下:
public class MonitorService extends Service {
private LoggerLoadTask mTask;
private String mPulseUrl;
private HomeBoySettings settings;
private DataFile dataFile;
private AlarmManager alarms;
private PendingIntent alarmIntent;
private ConnectivityManager cnnxManager;
@Override
public void onCreate() {
super.onCreate();
cnnxManager = (ConnectivityManager)
getSystemService(Context.CONNECTIVITY_SERVICE);
alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent intentOnAlarm = new Intent(
LaunchReceiver.ACTION_PULSE_SERVER_ALARM);
alarmIntent = PendingIntent.getBroadcast(this, 0, intentOnAlarm, 0);
}
@Override
public void onStart(Intent intent, int startId) {
super.onStart(intent, startId);
if (mPulseUrl == null) {
mPulseUrl = getString(R.string.urlPulse);
}
AppGlobal.logDebug("Monitor service OnStart.");
executeLogger();
}
executeLogger启动一个异步任务,这可能是我过于谨慎(这是我第三个Android应用程序)。异步任务获取GPS数据,将其发送到互联网,最后设置下一个闹钟:
private void executeLogger() {
if (mTask != null
&& mTask.getStatus() != LoggerLoadTask.Status.FINISHED) {
return;
}
mTask = (LoggerLoadTask) new LoggerLoadTask().execute();
}
private class LoggerLoadTask extends AsyncTask<Void, Void, Void> {
@Override
protected Void doInBackground(Void... arg0) {
try {
NetworkInfo ni = cnnxManager.getActiveNetworkInfo();
if (ni == null || !ni.isAvailable() || !ni.isConnected()) {
AppGlobal
.logWarning("No usable network. Skipping pulse action.");
return null;
}
} catch (Exception e) {
AppGlobal.logError(
"Unknown error in background pulse task. Error: '%s'.",
e, e.getMessage());
} finally {
int interval;
if (settings == null
|| settings.getPulseIntervalSeconds() == -1) {
interval = Integer
.parseInt(getString(R.string.pulseIntervalSeconds));
} else {
interval = settings.getPulseIntervalSeconds();
}
long timeToAlarm = SystemClock.elapsedRealtime() + interval
* 1000;
alarms.set(AlarmManager.ELAPSED_REALTIME_WAKEUP, timeToAlarm,
alarmIntent);
}
return null;
}
}
我注意到在设置闹钟后没有调用stopSelf()方法,所以除非被操作系统关闭,否则我的服务将一直闲置。虽然我是这个应用程序的唯一用户,但对于公共应用程序来说,你应该设置下一个时间间隔的闹钟然后调用stopSelf()方法关闭服务。
更新 请查看@juozas的评论,关于使用'alarms.setRepeating()'。
setRepeating()
的建议是使用setInexactRepeating()
(这样可以简化你的代码)- 我的问题是:即使手机进入睡眠状态这个方法是否仍然有效? - Mr_and_Mrs_D