Android: сохранение фоновой службы (предотвращение процесса смерти)

У меня есть служба, которая определяется как:

public class SleepAccelerometerService extends Service implements SensorEventListener 

По сути, я делаю приложение, которое контролирует активность акселерометра по разным причинам, пока пользователь спит со своим телефоном / устройством на кровати. Это долгое обслуживание, которое НЕ ДОЛЖНО быть убито ночью. В зависимости от того, сколько фоновых приложений и периодических процессов происходит ночью, андроид иногда убивает мой процесс, тем самым заканчивая мой сервис. Пример:

 10-04 03:27:41.673: INFO/ActivityManager(1269): Process com.androsz.electricsleep (pid 16223) has died. 10-04 03:27:41.681: INFO/WindowManager(1269): WIN DEATH: Window{45509f98 com.androsz.electricsleep/com.androsz.electricsleep.ui.SleepActivity paused=false} 

Я не хочу заставлять пользователя иметь «SleepActivity» или какую-то другую активность в моем приложении в качестве переднего плана. Я не могу периодически запускать свою службу, потому что она постоянно перехватывает onSensorChanged.

Какие-нибудь советы? Исходный код находится здесь: http://code.google.com/p/electricsleep/

Для Android 2.0 или более поздней версии вы можете использовать метод startForeground() для запуска службы на переднем плане.

В документации указано следующее :

startForeground(int, Notification) сервис может использовать startForeground(int, Notification) для startForeground(int, Notification) службы в состояние переднего плана, где система считает, что это то, что пользователь активно осознает и, следовательно, не является кандидатом на убийство при низком уровне памяти. (Теоретически возможно, что служба будет убита при чрезвычайном давлении памяти из текущего приложения переднего плана, но на практике это не должно быть проблемой.)

В первую очередь это связано с тем, что убийство службы будет нарушать работу пользователя, например, убийство службы музыкального плеера прекратит воспроизведение музыки.

Вам нужно будет предоставить Notification методу, который отображается в панели уведомлений в разделе «Продолжить».

Когда вы связываете свою Службу с деятельностью с BIND_AUTO_CREATE, ваша служба убивается сразу после того, как ваша деятельность разрушена и несвязана. Это не зависит от того, как вы внедрили свой метод unBSD Services, он все равно будет убит.

Другой способ – запустить службу с помощью метода startService из вашей деятельности. Таким образом, даже если ваша активность будет уничтожена, ваш сервис не будет уничтожен или даже приостановлен, но вы должны приостановить / уничтожить его самостоятельно, если это необходимо.

Как уже указывал Дэйв , вы можете запустить свой Service с приоритетом переднего плана. Но эта практика должна использоваться только тогда, когда это абсолютно необходимо, т. Е. Когда это вызовет плохой пользовательский опыт, если Служба будет убита Android. Это то, что на самом деле означает «передний план»: ваше приложение каким-то образом находится на переднем плане, и пользователь сразу заметил бы его, если он был убит (например, потому, что он воспроизводил песню или видео).

В большинстве случаев запрашивать приоритет переднего плана для вашего Сервиса является контрацептивным!

Почему это? Когда Android решает убить Service , он делает это, потому что ему не хватает ресурсов (обычно ОЗУ). Основываясь на разных классах приоритетов, Android решает, какие запущенные процессы и включенные в них сервисы прекращаются, чтобы освободить ресурсы. Это здоровый процесс, который вы хотите добиться, чтобы пользователь имел приятный опыт. Если вы запросите приоритет переднего плана, без веской причины, просто чтобы ваш сервис не был убит, он, скорее всего, вызовет плохой пользовательский опыт. Или вы можете гарантировать, что ваш сервис остается в минимальном потреблении ресурсов и не имеет утечек памяти? 1

Android предоставляет липкие сервисы для обозначения сервисов, которые необходимо перезапустить после некоторого льготного периода, если они были убиты. Этот перезапуск обычно происходит через несколько секунд.

Изображение, которое вы хотите написать клиенту XMPP для Android. Если вы запрашиваете приоритет переднего плана для Service который содержит ваше соединение XMPP? Определенно нет, нет абсолютно никаких оснований для этого. Но вы хотите использовать START_STICKY качестве флага возврата для метода onStartCommand вашего сервиса. Чтобы ваш сервис был остановлен, когда есть давление на ресурс, и возобновляется, как только ситуация вернется к норме.

1 : Я уверен, что многие приложения Android имеют утечки памяти. Это что-то вроде случайного (настольного) программиста.

У меня была аналогичная проблема. На некоторых устройствах через некоторое время Android убивает мое обслуживание и даже startForeground () не помогает. И моему клиенту это не нравится. Мое решение – использовать класс AlarmManager, чтобы убедиться, что служба работает, когда это необходимо. Я использую AlarmManager для создания своего рода сторожевого таймера. Время от времени проверяется, должна ли служба запускаться и перезапускать ее. Также я использую SharedPreferences, чтобы сохранить флаг, должен ли быть запущен сервис.

Создание / отклонение моего сторожевого таймера:

 void setServiceWatchdogTimer(boolean set, int timeout) { Intent intent; PendingIntent alarmIntent; intent = new Intent(); // forms and creates appropriate Intent and pass it to AlarmManager intent.setAction(ACTION_WATCHDOG_OF_SERVICE); intent.setClass(this, WatchDogServiceReceiver.class); alarmIntent = PendingIntent.getBroadcast(this, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT); AlarmManager am=(AlarmManager)getSystemService(Context.ALARM_SERVICE); if(set) am.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis() + timeout, alarmIntent); else am.cancel(alarmIntent); } 

Получение и обработка намерения с сторожевого таймера:

 /** this class processes the intent and * checks whether the service should be running */ public static class WatchDogServiceReceiver extends BroadcastReceiver { @Override public void onReceive(Context context, Intent intent) { if(intent.getAction().equals(ACTION_WATCHDOG_OF_SERVICE)) { // check your flag and // restart your service if it's necessary setServiceWatchdogTimer(true, 60000*5); // restart the watchdogtimer } } } 

Действительно, я использую WakefulBroadcastReceiver вместо BroadcastReceiver . Я дал вам код с BroadcastReceiver, чтобы упростить его.

http://developer.android.com/reference/android/content/Context.html#BIND_ABOVE_CLIENT

Public static final int BIND_ABOVE_CLIENT – добавлен в уровень API 14

Флаг для bindService(Intent, ServiceConnection, int) : указывает, что привязка клиента к этой службе считает сервис более важным, чем само приложение. Когда установлено, платформа попытается убить убийцу из памяти, прежде чем он убьет службу, к которой она привязана, хотя это не гарантируется.

Другие флаги той же группы: BIND_ADJUST_WITH_ACTIVITY, BIND_AUTO_CREATE, BIND_IMPORTANT, BIND_NOT_FOREGROUND, BIND_WAIVE_PRIORITY.

Обратите внимание, что значение BIND_AUTO_CREATE изменилось в ICS, а старые приложения, которые не указывают BIND_AUTO_CREATE , автоматически будут иметь для них флаги BIND_WAIVE_PRIORITY и BIND_ADJUST_WITH_ACTIVITY .

Следите за тем, чтобы ваш сервис был небольшим, что уменьшает вероятность закрытия Android приложения. Вы не можете предотвратить его от убийства, потому что если бы вы могли, тогда люди могли бы легко создавать постоянные шпионские программы

Я работаю над приложением и сталкиваюсь с проблемой убийства моего сервиса при убийстве приложения. Я исследовал Google и обнаружил, что должен сделать это на переднем плане. Ниже приведен код:

 public class UpdateLocationAndPrayerTimes extends Service { Context context; @Override public void onCreate() { super.onCreate(); context = this; } @Override public int onStartCommand(Intent intent, int flags, int startId) { StartForground(); return START_STICKY; } @Override public void onDestroy() { super.onDestroy(); } @Nullable @Override public IBinder onBind(Intent intent) { return null; } private void StartForground() { LocationChangeDetector locationChangeDetector = new LocationChangeDetector(context); locationChangeDetector.getLatAndLong(); Notification notification = new NotificationCompat.Builder(this) .setOngoing(false) .setSmallIcon(android.R.color.transparent) //.setSmallIcon(R.drawable.picture) .build(); startForeground(101, notification); } } 

Хмель, что это может помочь !!!!