Ich schrieb vor kurzem eine davon und beschlossen, es keine gute Idee ist, einen Hintergrunddienst laufen zu lassen. Es wird wahrscheinlich sowieso vom Betriebssystem heruntergefahren, oder es könnte sein. Was ich getan habe, war einen Filter für den Boot-Intent zu verwenden und dann einen Alarm über den Alarm-Manager zu setzen, so dass meine App in regelmäßigen Abständen neu gestartet wurde, und dann wurden die Daten gesendet. In der Android-Dokumentation finden Sie gute Informationen zu Diensten und zum Alarmmanager.
Zuerst habe ich einen Broadcast-Empfänger erstellt, der einfach meinen Dienst startet, wenn eine Internetverbindung geöffnet wird (ich bin nur interessiert, wenn eine Verbindung besteht - Sie könnten auch nach dem Boot-Ereignis filtern). Der Start-Empfänger muss von kurzer Dauer sein, so starten Sie einfach Ihren Service:
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);
}
}
Im Manifest habe ich:
<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>
Beachten Sie, wie ich einen Filter für meine eigenen Alarm haben, das, was ist erlaubt ich, um den Dienst zu schließen und es neu zu starten, nachdem es seine Arbeit getan hat.
Die Spitze von meinem Monitor-Dienst wie folgt aussieht:
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);
// reload our data
if (mPulseUrl == null) {
mPulseUrl = getString(R.string.urlPulse);
}
AppGlobal.logDebug("Monitor service OnStart.");
executeLogger();
}
executeLogger eine AsyncTask beginnt, was wahrscheinlich ist, ich übermäßig vorsichtig zu sein (das war nur mein dritte Android-App). Die AsyncTask die GPS-Daten packt, sendet sie an das Internet und setzt schließlich den nächsten Alarm:
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> {
// TODO: create two base service urls, one for debugging and one for live.
@Override
protected Void doInBackground(Void... arg0) {
try {
// if we have no data connection, no point in proceeding.
NetworkInfo ni = cnnxManager.getActiveNetworkInfo();
if (ni == null || !ni.isAvailable() || !ni.isConnected()) {
AppGlobal
.logWarning("No usable network. Skipping pulse action.");
return null;
}
///grab and log data
} catch (Exception e) {
AppGlobal.logError(
"Unknown error in background pulse task. Error: '%s'.",
e, e.getMessage());
} finally {
// always set the next wakeup alarm.
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;
}
}
merke ich, dass ich nicht stopSelf bin() aufgerufen, nachdem der Alarm ausgelöst, so wird mein Service herumsitzen nichts zu tun, es sei denn Herunterfahren von der op sys. Da ich der einzige Benutzer dieser App bin, ist das egal, aber für eine öffentliche App, die Idee ist, dass Sie den Alarm für das nächste Intervall dann stopSelf zum Schließen einstellen.
Aktualisieren Siehe den Kommentar von @juozas über die Verwendung von 'alarms.setRepeating()'.
Dank einer Million. Ich konnte den Service aufbauen, starten und stoppen. Ich muss jetzt sicherstellen, dass das System es nicht tötet und dass es bei Bedarf aufgerufen wird. – Mark
Denken Sie daran, dass das Betriebssystem Ihren Dienst regelmäßig stoppt (und neu startet), wie er es für richtig hält: http://developer.android.com/reference/android/app/Service.html#ProcessLifecycle – jscharf
jscharf, wie kann ich das sicherstellen? Der Service wird garantiert regelmäßig aufgerufen und nur dann ausgeführt, bis der Benutzer eine bestimmte Aktion ausführt, um die Anrufe zu beenden? Ich suche einen Alarm und gehe durch die Dokumentation, wie man sie benutzt ... – Mark