significa - notificaciones en segundo plano android studio
Android AlarmManager.setExactAndAllowWhileIdle() y WakefulBroadcastReceiver No funciona en algunos dispositivos nuevos fabricados y de bajo precio (4)
Creo que esta pregunta se hace muchas veces en el stackoverflow
de stackoverflow
pero aún así muchas personas que luchan por resolverla.
En mi aplicación para Android, tengo que activar el dispositivo cada media hora para obtener la ubicación actual y enviarla al servidor. Para esto, he usado AlarmManager
con el método setExactAndAllowWhileIdle()
y WakefulBroadcastReceiver
. Funciona bien en casi todos los dispositivos estándar / populares como Samsung, LG (Nexus), Sony, Panasonic, Lenovo, Motorola, Micro max, etc. Pero algunos otros dispositivos, en su mayoría, dispositivos de China no admiten o no pueden permitir que el dispositivo se active. desde el modo doze con setExactAndAllowWhileIdle()
. Lo he probado en el leeco letV (Android OS 6.1)
que no permite que el administrador de alarmas se leeco letV (Android OS 6.1)
en intervalos específicos.
Mi parte del código que he mencionado a continuación:
UserTrackingReceiverIntentService.java
public class UserTrackingReceiverIntentService extends IntentService {
public static final String TAG = "UserTrackingReceiverIntentService";
Context context;
public UserTrackingReceiverIntentService() {
super("UserTrackingReceiverIntentService");
}
@TargetApi(Build.VERSION_CODES.M)
@Override
protected void onHandleIntent(Intent intent) {
this.context = this;
if (!Util.isMyServiceRunning(LocationService.class, context)) {
context.startService(new Intent(context, LocationService.class));
}
Calendar calendar = Calendar.getInstance();
//********************************** SETTING NEXT ALARM *********************************************
Intent intentWakeFullBroacastReceiver = new Intent(context, SimpleWakefulReceiver.class);
PendingIntent sender = PendingIntent.getBroadcast(context, 1001, intentWakeFullBroacastReceiver, 0);
AlarmManager alarmManager = (AlarmManager) context.getSystemService(context.ALARM_SERVICE);
if (calendar.get(Calendar.MINUTE) >= 0 && calendar.get(Calendar.MINUTE) < 30) {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, 30);
calendar.set(Calendar.SECOND, 0);
} else if (calendar.get(Calendar.MINUTE) >= 30) {
if (calendar.get(Calendar.HOUR_OF_DAY) == 23) {
calendar.set(Calendar.HOUR_OF_DAY, 0);
calendar.add(Calendar.DAY_OF_MONTH, 1);
} else {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY) + 1);
}
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
} else {
calendar.set(Calendar.HOUR_OF_DAY, calendar.get(Calendar.HOUR_OF_DAY));
calendar.set(Calendar.MINUTE, 0);
calendar.set(Calendar.SECOND, 0);
}
//MARSHMALLOW OR ABOVE
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
alarmManager.setExactAndAllowWhileIdle(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), sender);
}
//LOLLIPOP 21 OR ABOVE
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
AlarmManager.AlarmClockInfo alarmClockInfo = new AlarmManager.AlarmClockInfo(calendar.getTimeInMillis(), sender);
alarmManager.setAlarmClock(alarmClockInfo, sender);
}
//KITKAT 19 OR ABOVE
else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
alarmManager.setExact(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), sender);
}
//FOR BELOW KITKAT ALL DEVICES
else {
alarmManager.set(AlarmManager.RTC_WAKEUP,
calendar.getTimeInMillis(), sender);
}
Util.registerHeartbeatReceiver(context);
SimpleWakefulReceiver.completeWakefulIntent(intent);
}
}
Cada vez que esté por encima del servicio, configure la siguiente alarma después de 30 minutos una vez que haya llamado.
public class SimpleWakefulReceiver extends WakefulBroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
// This is the Intent to deliver to our service.
Calendar calendar = Calendar.getInstance();
Intent service = new Intent(context, UserTrackingReceiverIntentService.class);
Date date = new Date();
SimpleDateFormat sdf = new SimpleDateFormat("yyyy/MM/dd HH:mm:ss");
String DateTime = sdf.format(date);
DateTime = Util.locatToUTC(DateTime);
service.putExtra("date", String.valueOf(DateTime));
String latitude = Util.ReadSharePrefrence(context, "track_lat");
String longitude = Util.ReadSharePrefrence(context, "track_lng");
service.putExtra("lat", latitude);
service.putExtra("lon", longitude);
Log.i("SimpleWakefulReceiver", "Starting service @ " + calendar.get(Calendar.HOUR_OF_DAY) + " : " + calendar.get(Calendar.MINUTE) + " : " + calendar.get(Calendar.SECOND));
// Start the service, keeping the device awake while it is launching.
startWakefulService(context, service);
}
}
Como he cambiado algunas configuraciones manualmente desde el dispositivo leeco letV
como Configuraciones> Batería> Alinear activación> Deshabilite ambas opciones. Si se habilita la batería puede ignorar forzar las activaciones de las aplicaciones.
Mis preguntas:
¿Qué pasó en este tipo de dispositivos? ¿Por qué no permiten que la alarma se dispare en un intervalo de tiempo específico?
En algunos dispositivos como la alarma de Gionee s plus que se dispara 2-3 minutos tarde ... ¿por qué?
android.net.conn.CONNECTIVITY_CHANGE
receptor deandroid.net.conn.CONNECTIVITY_CHANGE
amplia para escuchar cuando cambia la conectividad de la red ... ¿Qué hacer cuando no funciona en algunos dispositivos como Gionee s plus?Hay muchas variaciones en la configuración de optimización de la batería para varios fabricantes ... ¿Puede dañar los servicios en segundo plano de nuestra aplicación si es la solución para esto?
En mi aplicación para Android, tengo que activar el dispositivo cada 15 minutos para obtener la ubicación actual y enviarla al servidor. Lo he probado en Xiaomi Mi 5s (Android 6.0.1). Cuando cierro la aplicación, la aplicación entra en suspensión :( AlarmManager
con setExactAndAllowWhileIdle()
no funciona ¯/_(ツ)_/¯
Sí, funciona bien en casi todos los dispositivos estándar / populares como Samsung, LG (Nexus 5X), Sony, Motorola, Pixel ...
MI SOLUCIÓN :
La entrada de manifiesto para cada tipo de elemento componente ( <activity>
, <service>
, <receiver>
y <provider>
) admite un atributo android:process
que puede especificar un proceso en el que ese componente debería ejecutarse.
Necesita agregar esta cadena android:process=":service"
en su AndroidManifest.xml
Me gusta esto:
...
<receiver
android:name="your.full.packagename.MyWakefulReceiver"
android:process=":service"
android:enabled="true"/>
<service
android:name="your.full.packagename.MyLocationService"
android:process=":service"/>
<service
android:name="your.full.packagename.MySendService"
android:process=":service"
android:exported="false" />
...
He probado esta solución en Xiaomi Mi 5s. Es trabajo !!!
En mi humilde opinión, parece que el firmware de Xiaomi destruye el proceso principal cada vez que el usuario sale de la aplicación ...
Estoy de acuerdo contigo. Pero creo que deberías probar con JobScheduler una vez. Encontrará la documentación oficial https://developer.android.com/reference/android/app/job/JobScheduler.html mejor ejemplo que encuentro https://github.com/googlesamples/android-JobScheduler No tengo la prueba De acuerdo a mi tienes que intentar esto.
EDITAR
Si desea ejecutar su aplicación en modo dormido en la versión 6.0 o posterior, tiene que hacer una lista blanca de su aplicación.
https://www.bignerdranch.com/blog/diving-into-doze-mode-for-developers/
https://developer.android.com/training/monitoring-device-state/doze-standby.html
Imtiyaz
Hola, tengo el mismo problema durante las pruebas en Xiomi phone.leeco No tengo mucha idea. El teléfono Xiomi tiene su propio sistema operativo que es MIUI. Cuando borramos la RAM, se borran todas las aplicaciones, excepto algunas de las aplicaciones registradas en el sistema operativo. Al igual que Whatsapp y facebook algunas otras aplicaciones famosas.
He probado Service, Alarm Manager y Scheduler pero no he tenido éxito.
Proporcionan una forma específica de ejecutar los servicios manualmente. He comprobado que Leeco utiliza el sistema operativo Android.
Solución para MIUI 7.0 => Seguridad => Inicio automático => seleccione las aplicaciones que desea ejecutar en segundo plano => Reiniciar Después de reiniciar, su dispositivo debería poder ejecutar los servicios de su aplicación en segundo plano como lo hacen otros dispositivos Android.
Descripción detallada de inicio automático de MIUI
Según mi opinión, puedes probar con los Servicios y luego verificar si funciona o no.
Gracias espero que tengas un poco de ayuda de esto.
Probablemente estos teléfonos chinos hayan deshabilitado la activación de la aplicación para recibir eventos de alarma para conservar la vida útil de la batería. Sé que algunos fabricantes chinos no activan la aplicación para recibir notificaciones automáticas si se cerraron antes para ahorrar batería. Por lo tanto, hasta que la aplicación se abra de nuevo manualmente, el sistema operativo no la activará para ningún procesamiento de eventos.
Sin embargo este comportamiento puede ser cambiado. Verifique la configuración de administración de energía y cambie según corresponda para permitir que las aplicaciones se activen a intervalos regulares o cuando sea necesario. Creo que podría ser el modo restringido o algo similar.