studio - ubicacion en segundo plano android
¿Necesita un ejemplo de código sobre cómo ejecutar un servicio de Android para siempre en segundo plano, incluso cuando el dispositivo está inactivo, como Whatsapp? (5)
He intentado varias maneras de lograr esto, pero mi servicio eventualmente muere.
Quiero usar AlarmManager para activar una clase cada hora. Incluso si el dispositivo está inactivo, debería enviar una alerta, vibración o sonido de LED parpadeante. En cualquier caso, debería funcionar para siempre.
Me he dado cuenta de que Whatsapp siempre se está ejecutando, aunque mato todas las aplicaciones en ejecución, borro la memoria, pongo el dispositivo en modo de suspensión y aún recibo mensajes y alertas. ¿Cómo lo están haciendo? Quiero hacer lo mismo con mi aplicación.
Desde que publiqué esta pregunta, he implementado dos enfoques diferentes para esta solución en varias aplicaciones.
ENFOQUE 1
Este extracto proviene de una aplicación en la que utilizo notificaciones push, que necesitan llamadas instantáneas de activación para el dispositivo. Aquí lo que hago es
- usar el permiso WAKE_LOCK y
- usar una clase abstracta de Wakelocker
- Úsalo en una actividad según sea necesario:
Manifiesto:
<uses-permission android:name="android.permission.WAKE_LOCK" />
Clase de WakeLocker:
public abstract class WakeLocker {
private static PowerManager.WakeLock wakeLock;
public static void acquire(Context context) {
if (wakeLock != null) wakeLock.release();
PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
wakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK |
PowerManager.ACQUIRE_CAUSES_WAKEUP |
PowerManager.ON_AFTER_RELEASE, "WakeLock");
wakeLock.acquire();
}
public static void release() {
if (wakeLock != null) wakeLock.release(); wakeLock = null;
}
}
Ejemplo de clase de actividad:
private final BroadcastReceiver receiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
// Waking up mobile if it is sleeping
WakeLocker.acquire(getApplicationContext());
// do something
WakeLocker.release();
}
ENFOQUE 2
Lo mejor es cuando quieres dar el control de Android al despertar, y puedes vivir con despertar periódicamente tu código. Simplemente use un AlarmManager para invocar una clase de Servicio a intervalos regulares. Aquí hay un código de mi aplicación LifeLog24:
Actividad principal
Intent ll24 = new Intent(context, AlarmReceiverLifeLog.class);
PendingIntent recurringLl24 = PendingIntent.getBroadcast(context, 0, ll24, PendingIntent.FLAG_CANCEL_CURRENT);
AlarmManager alarms = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarms.setRepeating(AlarmManager.RTC_WAKEUP, first_log.getTime(), AlarmManager.INTERVAL_HOUR, recurringLl24); // Log repetition
Clase de alarma
public class AlarmReceiverLifeLog extends BroadcastReceiver {
private static final String TAG = "LL24";
static Context context;
@Override
public void onReceive(Context context, Intent intent) {
Log.v(TAG, "Alarm for LifeLog...");
Intent ll24Service = new Intent(context, LifeLogService.class);
context.startService(ll24Service);
}
}
y LifeLogService.class es donde hago mis cosas. La alarma se activa cada hora en este caso y activa el BroadcastReceiver que a su vez ejecuta el servicio. Hay más en esto, para asegurarse de que el servicio no se ejecute dos veces y así sucesivamente, pero obtendrá el punto de cómo se realiza. Y AlarmManager es la mejor manera de hacerlo, ya que no te preocupas por el uso de la batería, etc. y Android se encarga de activar tu Servicio a intervalos regulares.
Es muy simple.
pasos:
1.crear una clase de servicio.
2.crear una clase BroadcastReceiver
3. llamar a BroadReceiver en el método de servicio onDestroy
4.En el método onReceive del servicio de inicio de clase BroadReceiver una vez más.
Aquí está el código
Archivo de manifiesto: `
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".LauncherActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<service
android:name=".utilities.NotificationService"
android:enabled="true">
</service>
<receiver
android:name=".utilities.RestartService"
android:enabled="true"
android:exported="true"
android:label="RestartServiceWhenStopped"
android:permission="android.permission.RECEIVE_BOOT_COMPLETED">
<intent-filter>
<action android:name="RestartService" />
</intent-filter>
</receiver>
</application>
`
Clase de servicio
public class NotificationService extends Service {
public NotificationService() {
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}
@Override
public void onDestroy() {
super.onDestroy();
Intent restartService = new Intent("RestartService");
sendBroadcast(restartService);
}
}
Clase BroadcastReceiver
public class RestartService extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
context.startService(new Intent(context,NotificationService.class));
}
}
Puede utilizar una función startForeground (int, Notificación) ver aquí y here
Un servicio iniciado puede usar la API startForeground (int, Notification) para poner el servicio en un estado de primer plano, donde el sistema considera que es algo que el usuario conoce activamente y, por lo tanto, no es un candidato para matar cuando hay poca memoria. (En teoría, todavía es posible que el servicio se cancele bajo una presión de memoria extrema de la aplicación de primer plano actual, pero en la práctica esto no debería ser una preocupación).
Siga estos sencillos pasos para mantener el servicio vivo para siempre en un dispositivo Android. 1. Llame a un servicio utilizando el administrador de alarmas. 2. devuelve START_STICKY en el método onStart. 3. En on destroy, llame al administrador de alarmas y reinicie el servicio utilizando el método startService. 4. (Opcional) Repita el punto número 3 en el método onTaskRemoved.
Solicitar WakeLock parcial.
<uses-permission android:name="android.permission.WAKE_LOCK" />
PowerManager pm = (PowerManager) getSystemService(Context.POWER_SERVICE);
mWakeLock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK, "My Tag");
mWakeLock.acquire();
onStartCommand retrun START_STICKY:
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
super.onStartCommand(intent, flags, startId);
return START_STICKY;
}