Я думаю, что этот вопрос задают много раз в stackoverflow
, но все еще так много людей пытаются его решить.
В моем приложении для Android я должен разбудить устройство каждые полчаса, чтобы получить текущее местоположение и отправить его на сервер. Для этого я использовал AlarmManager
с методом setExactAndAllowWhileIdle()
и WakefulBroadcastReceiver
. Его работа прекрасна практически во всех стандартных/популярных устройствах, таких как samsung, LG (Nexus), Sony, Panasonic, Lenovo, Motorola, Micro max и т.д. Но некоторые другие устройства в основном китайские устройства не поддерживают или не могут позволить устройству проснуться от режима доз с помощью setExactAndAllowWhileIdle()
. Я протестировал его в устройстве leeco letV (Android OS 6.1)
, которое не позволяет диспетчеру тревоги проснуться в определенный интервал.
Моя часть кода, о которой я упомянул ниже:
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);
}
}
Каждый раз, когда выше службы устанавливают следующий сигнал тревоги через 30 минут после его вызова.
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);
}
}
Как я изменил некоторые настройки вручную с устройства leeco letV
, например "Настройки" > "Аккумулятор" > "Выполнить пробуждение" > "Отключить обе опции". Если он включен, аккумулятор может игнорировать силовые пробуждения из приложений.
Мои вопросы:
-
Что случилось с такими устройствами? Почему они не позволяют тревогу срабатывать в определенный промежуток времени?
-
В некоторых устройствах, таких как Gionee s plus, срабатывание сигнализации на 2-3 минуты позже... почему?
-
android.net.conn.CONNECTIVITY_CHANGE
широковещательный приемник для прослушивания при изменении сетевого подключения..... Что делать, если он не работает на некоторых устройствах, таких как Gionee s plus? -
Существует множество вариантов настройки батареи для разных производителей. Может ли это повредить нашим фоновым службам приложений, если это то, что для решения.