Ich bin gerade dabei, eine App zu erstellen, die der integrierten App SMS ähnelt.
Was ich brauche:
Was ich versucht habe:
- Ausführen eines regulären Dienstes, der gut funktioniert hat, bis Android den Dienst beendet
- mit dem AlarmManager die 5 min. Intervallaufruf an einen Dienst. Aber ich konnte das nicht schaffen.
ein Dienst, der immer in .__ ausgeführt wird. der Hintergrund
Dies ist nicht möglich im wahrsten Sinne des Begriffs, wie Sie festgestellt haben. Es ist auch schlechtes Design .
alle 5 min. Der Dienst prüft die aktueller Standort des Geräts und ruft einen Webdienst auf
Verwenden Sie AlarmManager
.
mit dem AlarmManager machen Sie die 5 Mindest. Intervallaufruf an einen Dienst. Aber ich konnte diese Arbeit nicht machen.
Hier ist ein Beispielprojekt , das zeigt, wie ein Projekt verwendet wird, zusammen mit der Verwendung von WakefulIntentService
, damit Sie wach bleiben, während Sie versuchen, den gesamten Web-Service zu erledigen.
Wenn Sie weiterhin Probleme damit haben, öffnen Sie eine neue Frage zu den spezifischen Dingen, auf die Sie mit AlarmManager
stoßen, die Ihnen Kummer bereiten.
Eine meiner Apps macht etwas sehr Ähnliches. Um den Dienst nach einer bestimmten Zeit aufzuwecken, empfehle ich postDelayed()
Habe ein Handlerfeld:
private final Handler handler = new Handler();
und eine Auffrischung Runnable
private final Runnable refresher = new Runnable() {
public void run() {
// some action
}
};
Sie können Ihre Benachrichtigungen in der Runable abfeuern.
Beim Service-Bau und nach jeder Ausführung starten Sie es wie folgt:
handler.postDelayed(refresher, /* some delay in ms*/);
Entferne in onDestroy()
den Beitrag
handler.removeCallbacks(refresher);
Um den Dienst beim Booten zu starten, benötigen Sie einen Autostarter. Das geht in dein Manifest
<receiver Android:name="com.example.ServiceAutoStarter">
<intent-filter>
<action Android:name="Android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
und der ServiceAutoStarter
sieht so aus:
public class ServiceAutoStarter extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context, UpdateService.class));
}
}
Es ist schwierig, das Betriebssystem davon abzuhalten, den Dienst zu beenden. Ihre Anwendung kann auch einen RuntimeException
haben und abstürzen, oder Ihre Logik kann zum Stillstand kommen.
In meinem Fall schien es hilfreich zu sein, den Dienst auf dem Bildschirm immer mit einem BroadcastReceiver
zu aktualisieren. Wenn also die Update-Kette blockiert wird, wird sie wiederbelebt, wenn der Benutzer das Telefon verwendet.
Im Dienste:
private BroadcastReceiver screenOnReceiver;
In Ihrem Dienst onCreate()
screenOnReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Some action
}
};
registerReceiver(screenOnReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON));
Heben Sie dann die Registrierung Ihres Dienstes auf onDestroy()
mit auf
unregisterReceiver(screenOnReceiver);
Sie können dies mit einer einfachen Implementierung tun:
public class LocationTrace extends Service implements LocationListener{
// The minimum distance to change Updates in meters
private static final long MIN_DISTANCE_CHANGE_FOR_UPDATES = 10; // 10 meters
private static final int TWO_MINUTES = 100 * 10;
// The minimum time between updates in milliseconds
private static final long MIN_TIME_BW_UPDATES = 1000 * 10; // 30 seconds
private Context context;
double latitude;
double longitude;
Location location = null;
boolean isGPSEnabled = false;
boolean isNetworkEnabled = false;
protected LocationManager locationManager;
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
this.context = this;
get_current_location();
// Toast.makeText(context, "Lat"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show();
return START_STICKY;
}
@Override
public void onLocationChanged(Location location) {
if((location != null) && (location.getLatitude() != 0) && (location.getLongitude() != 0)){
latitude = location.getLatitude();
longitude = location.getLongitude();
if (!Utils.getuserid(context).equalsIgnoreCase("")) {
Double[] arr = { location.getLatitude(), location.getLongitude() };
// DO ASYNCTASK
}
}
}
@Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
@Override
public void onProviderEnabled(String provider) {
}
@Override
public void onProviderDisabled(String provider) {
}
/*
* Get Current Location
*/
public Location get_current_location(){
locationManager = (LocationManager) context.getSystemService(Context.LOCATION_SERVICE);
isGPSEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
isNetworkEnabled = locationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
if(!isGPSEnabled && !isNetworkEnabled){
}else{
if (isGPSEnabled) {
if (location == null) {
locationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
location = locationManager.getLastKnownLocation(LocationManager.GPS_PROVIDER);
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
// Toast.makeText(context, "Latgps"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show();
}
}
}
}
if (isNetworkEnabled) {
locationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,
MIN_TIME_BW_UPDATES,
MIN_DISTANCE_CHANGE_FOR_UPDATES, this);
if (locationManager != null) {
if (location != null) {
latitude = location.getLatitude();
longitude = location.getLongitude();
// Toast.makeText(context, "Latgps1"+latitude+"long"+longitude,Toast.LENGTH_SHORT).show();
}
}
}
}
return location;
}
public double getLatitude() {
if(location != null){
latitude = location.getLatitude();
}
return latitude;
}
public double getLongitude() {
if(location != null){
longitude = location.getLongitude();
}
return longitude;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onDestroy() {
if(locationManager != null){
locationManager.removeUpdates(this);
}
super.onDestroy();
}
}
Sie können den Service so starten:
/*--Start Service--*/
startService(new Intent(Splash.this, LocationTrace.class));
Im Manifest:
<service Android:name=".LocationTrace">
<intent-filter Android:priority="1000">
<action Android:name="Android.location.PROVIDERS_CHANGED"/>
<category Android:name="Android.intent.category.DEFAULT"/>
</intent-filter>
</service>
mit diesen drei Schritten können Sie die meisten Android-Geräte alle 5 Minuten aufwecken:
1. stell deinen alternativen AlarmManager für verschiedene APIs ein:
AlarmManager am = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(getApplicationContext(), OwnReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(getApplicationContext(), 0, i, 0);
if (Build.VERSION.SDK_INT >= 23) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
else if (Build.VERSION.SDK_INT >= 19) {
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
2. Erstellen Sie Ihren eigenen statischen BroadcastReceiver:
public static class OwnReceiver extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
//do all of your jobs here
AlarmManager am = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, OwnReceiver.class);
PendingIntent pi = PendingIntent.getBroadcast(context, 0, i, 0);
if (Build.VERSION.SDK_INT >= 23) {
am.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
else if (Build.VERSION.SDK_INT >= 19) {
am.setExact(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
} else {
am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + (1000 * 60 * 5), pi);
}
}
}
3. <receiver>
zu AndroidManifest.xml
hinzufügen:
<receiver Android:name=".OwnReceiver" />