Идея иметь сервис ВСЕГДА работает в фоновом режиме на Android, это просто неправильно в 99% случаев.
Система должна «выключить» CPU и переключиться на низкий уровень использования батареи.
Вы говорите, что у вас есть служба на основе местоположения. Я предполагаю, что вы используете Google Play Services FusedLocationProvider
, если не , вы должны.
FusedLocationProvider
позволяет зарегистрировать изменения местоположения с помощью PendingIntent
. Это означает, что ваши службы не должны запускаться все время, просто нужно зарегистрироваться для изменения местоположения, а затем реагировать, когда придет новое местоположение и сделает все.
См. FusedLocationProviderApi
official documentation.
Чтобы начать прослушивание геоданных
- подключения к
GoogleClient
с помощью LocationServices.API
API
- Создайте свой
LocationRequest
в соответствии с вашими потребностями (см the doc)
- Вызов
requestLocationUpdates()
используя PendingIntent
версию
Чтобы прекратить слушать
- подключение к
GoogleClient
с помощью LocationServices.API
API
- Вызова
removeLocationUpdates()
используя тот же PendingIntent
Вашего PendingIntent может запустить другую службу для обработки нового местоположения.
Например, делать это от службы:
public void startMonitoringLocation(Context context) {
GoogleApiClient client = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API)
.build()
ConnectionResult connectionResult = mApiClient.blockingConnect();
if (connectionResult.isSuccess()) {
LocationServices.FusedLocationApi
.requestLocationUpdates(client, buildLocationRequest(), buildPendingIntent(context));
} else {
handleConnectionFailed(context);
}
}
Затем служба может немедленно прекратить.
При первом запуске этого кода WILL терпит неудачу. Соединение с клиентом google обычно требует от пользователя выполнения некоторых действий. Метод ConnectionResult.hasResolution()
вернет true, если это так. В противном случае причина - это нечто иное, и вы не можете оправиться от него. Значит, единственное, что вы можете сделать, это сообщить пользователю, что функция не будет работать или иметь хороший резерв.
ConnectionResult.getResolution()
дать вам PendingIntent
вам нужно использовать Activity
и startIntentSenderForResult()
метод на Activity
разрешить это намерение. Поэтому вы должны создать Notification
, начиная с Activity
, чтобы решить эту проблему, и в конце звоните Service
.
Обычно я просто начинаю Activity
, посвященный выполнению всей работы. Это намного проще, но вы не хотите называть connectBlocking()
. Отъезд this о том, как это сделать.
Вы можете спросить, почему бы не запрашивать обновления местоположения непосредственно в Activity
. Это на самом деле отлично, если вам не нужен монитор местоположения для автоматического запуска с устройства, даже если пользователь явно не открыл приложение.
<receiver android:name=".BootCompletedBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
Таким образом, вы можете просто запустить службу, чтобы подключаться и запрашивать обновления местоположения при перезагрузке устройства.
Пример того, как вы можете создать свой запрос местоположения:
public LocationRequest buildLocationRequest() {
LocationRequest locRequest = LocationRequest.create();
// Use high accuracy
locRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
// how often do you need to check for the location
// (this is an indication, it's not exact)
locRequest.setInterval(REQUIRED_INTERVAL_SEC * 1000);
// if others services requires the location more often
// you can still receive those updates, if you do not want
// too many consider setting this lower limit
locRequest.setFastestInterval(FASTEST_INTERVAL_SEC * 1000);
// do you care if the user moved 1 meter? or if he move 50? 1000?
// this is, again, an indication
locRequest.setSmallestDisplacement(SMALLEST_DISPLACEMENT_METERS);
return locRequest;
}
И ожидающие рассмотрения намерения:
public PendingIntent buildPendingIntent(Context context) {
Intent intent = new Intent(context, LocationUpdateHandlerService.class);
intent.setAction(ACTION_LOCATION_UPDATE);
intent.setPackage(context.getPackageName());
return PendingIntent.getService(context, REQUEST_CODE, intent, PendingIntent.FLAG_CANCEL_CURRENT);
}
Ваш LocationUpdateHandlerService
может быть IntentService
, если вам нужно, чтобы сделать работу в фоновом режиме:
@Override
protected void onHandleIntent(Intent intent) {
if (intent != null) {
Bundle extras = intent.getExtras();
if (extras != null && extras.containsKey(FusedLocationProviderApi.KEY_LOCATION_CHANGED)) {
Location location = extras.getParcelable(FusedLocationProviderApi.KEY_LOCATION_CHANGED);
handleLocationChanged(location);
} else {
Log.w(TAG, "Didn't receive any location update in the receiver");
}
}
}
Но также может быть трансляцией o Все, что вам подходит.
Если бы я должен был догадаться, Google поймал этот хак и заблокировал его. – CommonsWare
есть. Думаю тоже такой же. Но по этой причине мой клиент заблокировал мой проект :( –
вы можете использовать обратные вызовы, сделать обратный вызов и вызвать его в методе onTaskRemoved, реализация будет в действии и перезапустить службу. – Fakher