¿Cómo ejecutar siempre un servicio en segundo plano?

Estoy en el proceso de crear una aplicación similar a la aplicación de SMS incorporada.

Lo que necesito:

  • Un servicio que siempre se está ejecutando en segundo plano
  • Cada 5 min. El servicio comprueba la ubicación actual del dispositivo y llama a un servicio web
  • Si se cumplen ciertos criterios, el servicio debe generar una notificación (al igual que la aplicación de SMS)
  • Cuando se hace clic en la notificación, el usuario es llevado a la aplicación (al igual que la aplicación de SMS)
  • Cuando la aplicación está instalada, el servicio debe iniciarse
  • Cuando se reinicie el dispositivo, se debe iniciar el servicio

Lo que he intentado:
– ejecutar un servicio regular que funcionó bien hasta que Android mata el servicio
– utilizando el AlarmManager para hacer el 5 min. Llamada de intervalo a un servicio. Pero no pude hacer que esto funcione.

Un servicio que siempre se está ejecutando en segundo plano

Esto no es posible en ningún sentido real del término, como usted ha descubierto. También es un mal diseño .

Cada 5 min. El servicio comprueba la ubicación actual del dispositivo y llama a un servicio web

Utilice AlarmManager .

Utilizando el AlarmManager el hacer el 5 min. Llamada de intervalo a un servicio. Pero no pude hacer que esto funcione.

Aquí hay un ejemplo de proyecto que muestra cómo usar uno, junto con el uso de WakefulIntentService para que permanezca despierto mientras intenta hacer todo el servicio Web.

Si tiene problemas continuos con él, abra una nueva pregunta sobre las cosas específicas que está encontrando con AlarmManager que le están dando pena.

Una de mis aplicaciones hace algo muy similar. Para despertar el servicio después de un período dado recomiendo postDelayed()

Tener un campo de manejador:

 private final Handler handler = new Handler(); 

Y una actualización Runnable

 private final Runnable refresher = new Runnable() { public void run() { // some action } }; 

Usted puede disparar sus notificaciones en el runnable.

En la construcción del servicio, y después de cada ejecución empieza así:

 handler.postDelayed(refresher, /* some delay in ms*/); 

En onDestroy() quitar la entrada

 handler.removeCallbacks(refresher); 

Para iniciar el servicio en el arranque, necesita un arrancador automático. Esto va en su manifiesto

 <receiver android:name="com.example.ServiceAutoStarter"> <intent-filter> <action android:name="android.intent.action.BOOT_COMPLETED" /> </intent-filter> </receiver> 

Y el ServiceAutoStarter tiene este aspecto:

 public class ServiceAutoStarter extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { context.startService(new Intent(context, UpdateService.class)); } } 

Detener el sistema operativo de matar el servicio es difícil. También su aplicación puede tener una RuntimeException y un accidente, o su lógica puede detener.

En mi caso, parecía ayudar a actualizar siempre el servicio en la pantalla con un BroadcastReceiver . Así que si la cadena de actualizaciones se estancó, será resucitado a medida que el usuario use su teléfono.

En el servicio:

 private BroadcastReceiver screenOnReceiver; 

En su servicio onCreate()

 screenOnReceiver = new BroadcastReceiver() { @Override public void onReceive(Context context, Intent intent) { // Some action } }; registerReceiver(screenOnReceiver, new IntentFilter(Intent.ACTION_SCREEN_ON)); 

A continuación, onDestroy() el registro de su servicio en onDestroy() con

 unregisterReceiver(screenOnReceiver); 

Puede hacerlo mediante una implementación sencilla:

 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(); } } 

Usted puede comenzar el servicio por esto:

 /*--Start Service--*/ startService(new Intent(Splash.this, LocationTrace.class)); 

En manifiesto:

  <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> 
FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.