Урок 94. Service. Подробно про onStartCommand

Обсуждение уроков
AlexVinn
Сообщения: 81
Зарегистрирован: 04 апр 2014, 04:56

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение AlexVinn » 03 май 2014, 11:46

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

[syntax=java5] if ((flags & START_FLAG_REDELIVERY) == START_FLAG_REDELIVERY)
Log.d(LOG_TAG, "START_FLAG_REDELIVERY");
if ((flags & START_FLAG_RETRY) == START_FLAG_RETRY)
Log.d(LOG_TAG, "START_FLAG_RETRY");[/syntax]

(нет в логах значения флага)
Хелп, плз.
Log
05-03 04:39:17.074: D/myLogs(1757): MyService onCreate
05-03 04:39:17.074: D/myLogs(1757): MyService onStartCommand, name = value
05-03 04:39:17.084: D/myLogs(1757): MyRun#1 create
05-03 04:39:17.084: D/myLogs(1757): MyRun#1 start
05-03 04:39:32.134: D/myLogs(1757): MyService onDestroy
05-03 04:39:32.144: D/myLogs(1757): MyRun#1 end, stopSelfResult(1) = true

MyService.java
[syntax=java5]package com.example.p0942_servicekillservernofrag;

import java.util.concurrent.TimeUnit;

import android.app.Service;
import android.content.Intent;
import android.os.IBinder;
import android.util.Log;

public class MyService extends Service {

final String LOG_TAG = "myLogs";

public void onCreate() {
super.onCreate();
Log.d(LOG_TAG, "MyService onCreate");
}

public void onDestroy() {
super.onDestroy();
Log.d(LOG_TAG, "MyService onDestroy");
}

public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(LOG_TAG,
"MyService onStartCommand, name = "
+ intent.getStringExtra("name"));
readFlags(flags);
MyRun mr = new MyRun(startId);
new Thread(mr).start();
return START_STICKY;
}

public IBinder onBind(Intent arg0) {
return null;
}

void readFlags(int flags) {
Log.d(LOG_TAG, "flags");
if ((flags & START_FLAG_REDELIVERY) == START_FLAG_REDELIVERY)
Log.d(LOG_TAG, "START_FLAG_REDELIVERY");
if ((flags & START_FLAG_RETRY) == START_FLAG_RETRY)
Log.d(LOG_TAG, "START_FLAG_RETRY");
}

class MyRun implements Runnable {

int startId;

public MyRun(int startId) {
this.startId = startId;
Log.d(LOG_TAG, "MyRun#" + startId + " create");
}

public void run() {
Log.d(LOG_TAG, "MyRun#" + startId + " start");
try {
TimeUnit.SECONDS.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
stop();
}

void stop() {
Log.d(LOG_TAG, "MyRun#" + startId + " end, stopSelfResult("
+ startId + ") = " + stopSelfResult(startId));
}
}
}
[/syntax]
Тут должна быть подпись.

olademar
Сообщения: 1
Зарегистрирован: 07 июл 2014, 21:39

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение olademar » 07 июл 2014, 21:48

Подскажите, пожалуйста, почему система не видит флаги: START_FLAG_RETRY или START_FLAG_REDELIVERY и константы: START_NOT_STICKY, START_STICKY, START_REDELIVER_INTENT, т.е. лог с выводом флагов в методе readFlag() отсутствует. Если процесс убить при любой возвращаемой константе в методе onStartCommand, процесс не оживает.

Анэрон
Сообщения: 3
Зарегистрирован: 25 июл 2014, 10:58

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение Анэрон » 25 июл 2014, 11:09

Для начала большое спасибо автору за уроки очень много почерпнул. Фактически всему учился по этим урокам. Прошу совета есть сервис который переодически берёт кординаты и отправляет их на сервер. Также он передаёт данные в активность. Реализация задержки происходит обычным бесконечным циклом ну понятное дело с условием на его остановку. И задержкой slep.По факту всё работает. Но очевидно происходит утечка памяти. На реальном девайсе. И следовательно через определённое время втечении часа или получаса приложение убивается системой. Вопрос как мне отловить утечку памяти. Или как переделать сервис чтобы переодически повторял какое-либо действие. Буду очень признателен за совет.

Аватара пользователя
neoksi
Сообщения: 712
Зарегистрирован: 26 июл 2012, 10:42
Контактная информация:

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение neoksi » 25 июл 2014, 13:10

Анэрон писал(а):Для начала большое спасибо автору за уроки очень много почерпнул. Фактически всему учился по этим урокам. Прошу совета есть сервис который переодически берёт кординаты и отправляет их на сервер. Также он передаёт данные в активность. Реализация задержки происходит обычным бесконечным циклом ну понятное дело с условием на его остановку. И задержкой slep.По факту всё работает. Но очевидно происходит утечка памяти. На реальном девайсе. И следовательно через определённое время втечении часа или получаса приложение убивается системой. Вопрос как мне отловить утечку памяти. Или как переделать сервис чтобы переодически повторял какое-либо действие. Буду очень признателен за совет.
Тебе нужно пересмотреть саму логику процесса. Держать постоянно работающий сервис в памяти, тебе не даст система.
Для выполнения время от времени какой-либо операции, нужно создавать связку из AlarmManager - > BroadcastReceiver - > Service.

Схема следующая:
1) Создаешь задачу в AlarmManager кидать броадкас через определенные промежутки времени;
2) Ловишь броадкаст и если нужно запускаешь сервис;
3) Выполняешь нужные операции в сервисе без каких-либо таймеров;
4) Освобождаешь ресурсы.

Анэрон
Сообщения: 3
Зарегистрирован: 25 июл 2014, 10:58

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение Анэрон » 28 июл 2014, 12:44

neoksi писал(а):
Анэрон писал(а):Для начала большое спасибо автору за уроки очень много почерпнул. Фактически всему учился по этим урокам. Прошу совета есть сервис который переодически берёт кординаты и отправляет их на сервер. Также он передаёт данные в активность. Реализация задержки происходит обычным бесконечным циклом ну понятное дело с условием на его остановку. И задержкой slep.По факту всё работает. Но очевидно происходит утечка памяти. На реальном девайсе. И следовательно через определённое время втечении часа или получаса приложение убивается системой. Вопрос как мне отловить утечку памяти. Или как переделать сервис чтобы переодически повторял какое-либо действие. Буду очень признателен за совет.
Тебе нужно пересмотреть саму логику процесса. Держать постоянно работающий сервис в памяти, тебе не даст система.
Для выполнения время от времени какой-либо операции, нужно создавать связку из AlarmManager - > BroadcastReceiver - > Service.

Схема следующая:
1) Создаешь задачу в AlarmManager кидать броадкас через определенные промежутки времени;
2) Ловишь броадкаст и если нужно запускаешь сервис;
3) Выполняешь нужные операции в сервисе без каких-либо таймеров;
4) Освобождаешь ресурсы.
А если есть данные которые в сервисе должны переходить из одной итерации в другую к примеру шаг. Синглетоном тут как я уже понимаю не получится

Aleator
Сообщения: 1
Зарегистрирован: 21 сен 2014, 23:06

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение Aleator » 30 окт 2014, 02:42

Та же проблема, что и у olademar. "Подскажите, пожалуйста, почему система не видит флаги: START_FLAG_RETRY или START_FLAG_REDELIVERY и константы: START_NOT_STICKY, START_STICKY, START_REDELIVER_INTENT, т.е. лог с выводом флагов в методе readFlag() отсутствует. Если процесс убить при любой возвращаемой константе в методе onStartCommand, процесс не оживает". Уже и перепечатывал код, и просто копировал. Результат один и тот же.

Аватара пользователя
mitra
Сообщения: 10
Зарегистрирован: 18 ноя 2014, 11:22

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение mitra » 21 ноя 2014, 12:44

Здравствуйте.
Aleator писал(а):Та же проблема, что и у olademar. ... Если процесс убить при любой возвращаемой константе в методе onStartCommand, процесс не оживает"...
У меня похожая ситуация:
1) Если сервис не убивать, он выполняет свою задачу, но остается висеть в списке процессов.
2) Если сервис убить, он не оживает.
Версия SDK:

Код: Выделить всё

    <uses-sdk
            android:minSdkVersion="19"
            android:targetSdkVersion="19"/>
Каждая незаконченная задача - это минус. Но каждый зачеркнутый минус - это плюс.

kaaa
Сообщения: 4
Зарегистрирован: 04 ноя 2014, 22:23

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение kaaa » 25 янв 2015, 22:05

Все уроки до этого прошел, а с этим уже больше недели мучаюсь над этим уроком. При нажатии на кнопку система ругается. Помогите кто нибудь. Пожалуйста.
Логи
01-25 18:56:15.195: E/AndroidRuntime(3572): FATAL EXCEPTION: main
01-25 18:56:15.195: E/AndroidRuntime(3572): java.lang.RuntimeException: Unable to instantiate service ru.servicekillserver.MyService: java.lang.ClassNotFoundException: Didn't find class "ru.servicekillserver.MyService" on path: /data/app/ru.servicekillserver-2.apk

Аватара пользователя
doter.ua
Сообщения: 1106
Зарегистрирован: 23 ноя 2013, 16:08
Откуда: Ukraine

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение doter.ua » 25 янв 2015, 23:28

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

kaaa
Сообщения: 4
Зарегистрирован: 04 ноя 2014, 22:23

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение kaaa » 25 янв 2015, 23:46

doter.ua писал(а):класс MyService точно существует?
Да, существует. Но меня смущает что когда редактируешь Манифест и заполняешь Name это сервиса (выбираю из того что предлагает), то горит маленький красный крестик. Но раз он предлагает, значит он его видит, этот класс MyService.

kaaa
Сообщения: 4
Зарегистрирован: 04 ноя 2014, 22:23

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение kaaa » 25 янв 2015, 23:49

doter.ua писал(а):класс MyService точно существует?
Ты имеешь ввиду Android Studio?
Если да, то может подскажешь уроки под него, чтобы разобраться. Я его поставил, но все уроки, которые здесь, даже на Eclips тяжело. Боюсь совсем утонуть.

haos111
Сообщения: 3
Зарегистрирован: 24 фев 2015, 16:44

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение haos111 » 24 фев 2015, 16:59

Добрый вечер! Не удается выполнить урок, приложение закрывается с ошибкой:
[syntax=java]Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.example.admin.servicekillserver_94.MyService (has extras) }
at com.example.admin.servicekillclient_94.MainActivity.onClickStart(MainActivity.java:20)[/syntax]

ServiceKillClient Activity:

[syntax=java]public class MainActivity extends Activity {

@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}

public void onClickStart(View view) {
startService(new Intent("com.example.admin.servicekillserver_94.MyService")
.putExtra("name", "value"));
}
}[/syntax]

ServiceKillServer MyService:

[syntax=java]public class MyService extends Service {

final String LOG="myLogs";

@Override
public void onCreate() {
super.onCreate();
Log.d(LOG,"MyService onCreate");
}

@Override
public void onDestroy() {
super.onDestroy();
Log.d(LOG,"MyService onDestroy");
}

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(LOG,"MyService onStartCommand");
readFlags(flags);
MyRun mr=new MyRun(startId);
new Thread(mr).start();
return START_NOT_STICKY;
}

void readFlags(int flags) {
if ((flags&START_FLAG_REDELIVERY)==START_FLAG_REDELIVERY)
Log.d(LOG,"START_FLAG_REDELIVERY");
if ((flags&START_FLAG_RETRY)==START_FLAG_RETRY)
Log.d(LOG,"START_FLAG_RETRY");
}

@Override
public IBinder onBind(Intent intent) {
return null;
}

class MyRun implements Runnable {

int startId;

public MyRun(int startId) {
this.startId=startId;
Log.d(LOG,"MyRun#"+startId+" create");
}

@Override
public void run() {
Log.d(LOG,"MyRun#"+startId+" start");
try {
TimeUnit.SECONDS.sleep(15);
} catch (InterruptedException e) {
e.printStackTrace();
}
stop();
}

void stop() {
Log.d(LOG,"MyRun#"+startId+" end, stopSelfResult("+startId+") = "
+stopSelfResult(startId));
}
}
}[/syntax]

ServiceKillServer Manifest:

[syntax=xml]<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.admin.servicekillserver_94">

<application android:allowBackup="true"
android:label="@string/app_name"
android:icon="@mipmap/ic_launcher"
android:theme="@style/AppTheme">
<service android:name=".MyService">
<intent-filter>
<action android:name="com.example.admin.servicekillserver_94.MyService"/>
<category android:name="android.intent.category.DEFAULT"/>
</intent-filter>
</service>

</application>


</manifest>[/syntax]

В общем все как в уроке. Буду признателен за помощь!

UPD Создал класс сервиса в одном проекте с активити, сервис в отдельном процессе, все работает. может в манифесте активити надо было добавить какие-либо permissions?

Pavel-Pugach
Сообщения: 15
Зарегистрирован: 31 мар 2015, 15:17

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение Pavel-Pugach » 16 апр 2015, 15:56

Урок падает в Android Studio с ошибкой. Что именно нужно изменить что бы работал? На сколько я понял - сервис без активити не запускается.

-----

На AVD 5.0+ валится с ошибкой. Попробовал запустить на 4.4 - приложение уже не вылает, но выдает "Implicit intents with startService are not safe: Intent { act=ru.startandroid.develop.p0942servicekillserver.MyService (has extras) } android.content.ContextWrapper.startService:494 com.example.pavel.ololosh.MainActivity.onClickStart:19 java.lang.reflect.Method.invokeNative:-2"

------
У всех у кого валиться с такой же ошибкой - неявный вызов сервиса не работает в Android 5.0+. Работайте с АПИ ниже и все будет ок.

d.u.a.l
Сообщения: 2
Зарегистрирован: 14 мар 2015, 19:56

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение d.u.a.l » 19 май 2015, 23:00

Как убивать процессы в Android Studio? В качестве эмулятора использую Genymotion

kunstkamera
Сообщения: 5
Зарегистрирован: 17 июл 2015, 14:17

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение kunstkamera » 24 июл 2015, 16:12

mitra писал(а):Здравствуйте.
Aleator писал(а):Та же проблема, что и у olademar. ... Если процесс убить при любой возвращаемой константе в методе onStartCommand, процесс не оживает"...
У меня похожая ситуация:
1) Если сервис не убивать, он выполняет свою задачу, но остается висеть в списке процессов.
2) Если сервис убить, он не оживает.
Версия SDK:

Код: Выделить всё

    <uses-sdk
            android:minSdkVersion="19"
            android:targetSdkVersion="19"/>
Аналогично. Сервис выполняет работу и висит в списке. Если остановить, он не оживает. Пишу под API 17.

K_Vladimir
Сообщения: 36
Зарегистрирован: 28 июн 2015, 03:13

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение K_Vladimir » 04 авг 2015, 12:18

Доброго всем дня!
Видимо с момента написания урка многое изменилось. Попробуйте переписать readFlags (просто чтобы было понятней):

Код: Выделить всё

void readFlags(int flags) {
        if(flags==1) Log.d(LOG_TAG, "START_FLAG_REDELIVERY");
        if(flags==2) Log.d(LOG_TAG, "START_FLAG_RETRY");
        if(flags==0) Log.d(LOG_TAG, "000000");
        Log.d(LOG_TAG, "Anyway:" + flags);
    }
И вы увидите, что всё время будет приходить 0 во флагах.
А вот в уроке сказано: "На практике я ни разу не встречал значения 0".
Видимо разработчики это пофиксили.

Однако, START_FLAG_RETRY за весь урок у меня так и не появился.
08-04 08:49:39.506 2212-2212/? D/myLogs﹕ MyService onCreate
08-04 08:49:39.506 2212-2212/? D/myLogs﹕ MyService onStartCommand, name = value
08-04 08:49:39.506 2212-2212/? D/myLogs﹕ 000000
08-04 08:49:39.506 2212-2212/? D/myLogs﹕ Anyway:0
08-04 08:49:39.506 2212-2212/? D/myLogs﹕ MyRun#1 create
08-04 08:49:39.506 2212-2226/? D/myLogs﹕ MyRun#1 start
08-04 08:49:54.617 2229-2229/? D/myLogs﹕ MyService onCreate
08-04 08:49:54.617 2229-2229/? D/myLogs﹕ MyService onStartCommand, name = value
08-04 08:49:54.617 2229-2229/? D/myLogs﹕ START_FLAG_REDELIVERY
08-04 08:49:54.617 2229-2229/? D/myLogs﹕ Anyway:1
08-04 08:49:54.617 2229-2229/? D/myLogs﹕ MyRun#1 create
08-04 08:49:54.617 2229-2242/? D/myLogs﹕ MyRun#1 start
08-04 08:50:09.627 2229-2229/? D/myLogs﹕ MyService onDestroy
08-04 08:50:09.627 2229-2242/? D/myLogs﹕ MyRun#1 end, stopSelfResult(1) = true
Примечательно, что после отработки методов onDestroy и stopSelfResult
сервис P0942_ServiceKillServer так и остался висеть в Device Monitor.
Но после второй попытки остановить его (естественно 15 сек уже прошло) он стерся из процессов. => Делайте контрольный выстрел)), на всякий случай.

Остался один вопрос:
В AVD выше 17 версии сервис так и не запустился.
Можно ли всё таки запускать сервисы без активити в наши дни? (в новых версиях Android)
Или теперь просто сервис без активити не напишешь?
Может быть я чего-то не до-понимаю. Поправьте если что.

Аватара пользователя
Kirill
Сообщения: 19
Зарегистрирован: 09 сен 2015, 13:53

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение Kirill » 22 сен 2015, 13:06

K_Vladimir писал(а): Остался один вопрос:
В AVD выше 17 версии сервис так и не запустился.
Можно ли всё таки запускать сервисы без активити в наши дни? (в новых версиях Android)
Или теперь просто сервис без активити не напишешь?
Может быть я чего-то не до-понимаю. Поправьте если что.
Pavel-Pugach писал(а): На AVD 5.0+ валится с ошибкой. Попробовал запустить на 4.4 - приложение уже не вылает, но выдает "Implicit intents with startService are not safe: Intent { act=ru.startandroid.develop.p0942servicekillserver.MyService (has extras) } android.content.ContextWrapper.startService:494 com.example.pavel.ololosh.MainActivity.onClickStart:19 java.lang.reflect.Method.invokeNative:-2"
У всех у кого валиться с такой же ошибкой - неявный вызов сервиса не работает в Android 5.0+. Работайте с АПИ ниже и все будет ок.
haos111 писал(а):Добрый вечер! Не удается выполнить урок, приложение закрывается с ошибкой:
[syntax=java]Caused by: java.lang.IllegalArgumentException: Service Intent must be explicit: Intent { act=com.example.admin.servicekillserver_94.MyService (has extras) }
at com.example.admin.servicekillclient_94.MainActivity.onClickStart(MainActivity.java:20)[/syntax]

UPD Создал класс сервиса в одном проекте с активити, сервис в отдельном процессе, все работает. может в манифесте активити надо было добавить какие-либо permissions?

:!: Обратите внимание:
В данном уроке используется implicit (неявный) intent. После API 19 это запрещено что и вызывает java.lang.IllegalArgumentException: Service Intent must be explicit

Проблема и решение описаны здесь: http://stackoverflow.com/questions/2653 ... 2#28151732

Если коротко, то рекомендуется: использовать явные интенты или в интент прописать имя пакета myIntent.setPackage("com.package.with.service");
это пофиксит проблему.


[syntax=java5]
MainActivity.java
...

Intent serviceIntent = new Intent("ru.startandroid.develop.p0942servicekillserver.MyService")
.putExtra("name", "my_super_value");

serviceIntent.setPackage("ru.startandroid.develop.p0942servicekillserver");
startService(serviceIntent);
[/syntax]

более грамотная реализация описана здесь: http://blog.android-develop.com/2014/10 ... gumen.html но смысл тот же.

Аватара пользователя
Kirill
Сообщения: 19
Зарегистрирован: 09 сен 2015, 13:53

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение Kirill » 22 сен 2015, 17:15

damager82 писал(а):В этом уроке:

- рассмотрим подробнее метод onStartCommand

Click here to read this article!
спасибо за интересный урок. Чтобы привести его в актуальное состояние хорошо бы его обновить и перезаписать. Пожелания:

1. внести в урок описание ошибки из-за implicit intent и способ ее устранения

2. поменять в методе readFlags() способ с битовым максами на всем понятный switch()
[syntax=java5] private void readFlags(int flags) {
switch (flags) {
case START_FLAG_REDELIVERY:
Log.d(LOG_TAG, "readFlags: START_FLAG_REDELIVERY");
break;
case START_FLAG_RETRY:
Log.d(LOG_TAG, "readFlags: START_FLAG_RETRY");
break;
case 0:
Log.d(LOG_TAG, "readFlags: 0");
break;
default:
Log.d(LOG_TAG, "readFlags: ERROR. Unexpected flag returned: " + flags);
}
}[/syntax]

3. Флаги это самое интересное, давайте разбираться:

в первом случае когда:
в оnStartCommand() возвращаем return START_NOT_STICKY; - наш метод readFlags() покажет 0 , и это логично т.к. это первый запуск (а не START_FLAG_RETRY как в уроке)

во втором случае в уроке мы делаем следующее:
строчку лога изменяем и дописываем обращение к интенту:
Log.d(LOG_TAG, "MyService onStartCommand, name = " + intent.getStringExtra("name"));
возвращаемую константу при этом делаем START_STICKY.

вот здесь присутствует ошибка NullPointerException которую почему-то никто не заметил.
логи:
MyRun#1 create
MyRun#1 start
MyService onCreate
MyService onCreate

вопрос: куда делся вызов метода onStartCommand() который должен оставить в логах сообщение "MyService onStartCommand, name = " + intent.getStringExtra("name")) ?
его нет, так как при перезапуске сервиса с константой START_STICKY после onCreate() вызывается метод onStartCommand() с аргументом Intent == null,
соответственно нельзя на null'е вызывать .getStringExtra("name"). Вылетает ошибка и комманда вывода лога не отрабатывается.
В комментариях прозвучало "Но вызов startService, который он получил в прошлый раз, потерян." - он не потерян, он есть, просто интент пришел null и мы его не увидели.

теперь о START_FLAG_RETRY:
Все таки пытаемся его отловить: убираем обращение к пустому интенту, все перезапускаем, останавливаем сервис и получаем еще одну странную вещь:
в логах видно что при повторном вызове onStartCommand флаг приходит все равно нулевой - 0. (а мы ожидаем START_FLAG_RETRY)
Лог:

Код: Выделить всё

09-22 17:03:58.278    6240-6240/? D/myLogs﹕ ____________________
09-22 17:03:58.278    6240-6240/? D/myLogs﹕ MyService.onCreate()
09-22 17:03:58.278    6240-6240/? D/myLogs﹕ MyService.onStartCommand()
09-22 17:03:58.278    6240-6240/? D/myLogs﹕ readFlags: 0
09-22 17:03:58.278    6240-6240/? D/myLogs﹕ MyRun#1 was created in constructor
09-22 17:03:58.279    6240-6262/? D/myLogs﹕ MyRun#1 started
09-22 17:04:05.371    6543-6543/? D/myLogs﹕ ____________________
09-22 17:04:05.371    6543-6543/? D/myLogs﹕ MyService.onCreate()
09-22 17:04:05.372    6543-6543/? D/myLogs﹕ MyService.onStartCommand()
09-22 17:04:05.372    6543-6543/? D/myLogs﹕ readFlags: 0
09-22 17:04:05.372    6543-6543/? D/myLogs﹕ MyRun#2 was created in constructor
09-22 17:04:05.373    6543-6589/? D/myLogs﹕ MyRun#2 started
09-22 17:04:14.097    6726-6726/? D/myLogs﹕ ____________________
09-22 17:04:14.097    6726-6726/? D/myLogs﹕ MyService.onCreate()
09-22 17:04:14.098    6726-6726/? D/myLogs﹕ MyService.onStartCommand()
09-22 17:04:14.098    6726-6726/? D/myLogs﹕ readFlags: 0
09-22 17:04:14.099    6726-6726/? D/myLogs﹕ MyRun#3 was created in constructor
09-22 17:04:14.100    6726-6758/? D/myLogs﹕ MyRun#3 started
почему? это не баг, читаем доки: public static final int START_FLAG_RETRY - This flag is set in onStartCommand(Intent, int, int) if the Intent is a retry because the original attempt never got to or returned from onStartCommand(Intent, int, int).

Это значит что флаг START_FLAG_RETRY мы получим только в том случае, если метод onStartCommand() или вовсе не вызовится или в самом методе onStartCommand() до return процесс упадет. То есть, это тот крошечный момент, между стартом onCreate() и концом метода onStartCommand(). В ручную чтобы подловить его надо вставлять sleep или использовать System.exit(1) что на уровне системы вырубает процесс.
Вот тогда в логах увидим START_FLAG_RETRY.

получился такой лог:

Код: Выделить всё

09-22 16:48:15.998  21135-21135/? D/myLogs﹕ ____________________
09-22 16:48:15.998  21135-21135/? D/myLogs﹕ MyService.onCreate()
09-22 16:48:15.999  21135-21135/? D/myLogs﹕ MyService.onStartCommand()
09-22 16:48:15.999  21135-21135/? D/myLogs﹕ readFlags: 0
09-22 16:48:16.000  21135-21135/? D/myLogs﹕ MyRun#1 was created in constructor
09-22 16:48:16.001  21135-21160/? D/myLogs﹕ MyRun#1 started
09-22 16:48:35.109  21449-21449/? D/myLogs﹕ ____________________
09-22 16:48:35.109  21449-21449/? D/myLogs﹕ MyService.onCreate()
09-22 16:48:35.109  21449-21449/? D/myLogs﹕ MyService.onStartCommand()
09-22 16:48:35.109  21449-21449/? D/myLogs﹕ readFlags: START_FLAG_RETRY
09-22 16:48:35.110  21449-21449/? D/myLogs﹕ MyRun#1 was created in constructor
09-22 16:48:35.111  21449-21483/? D/myLogs﹕ MyRun#1 started
09-22 16:49:33.182  22355-22355/? D/myLogs﹕ ____________________
09-22 16:49:33.182  22355-22355/? D/myLogs﹕ MyService.onCreate()
09-22 16:49:33.183  22355-22355/? D/myLogs﹕ MyService.onStartCommand()
09-22 16:49:33.183  22355-22355/? D/myLogs﹕ readFlags: START_FLAG_RETRY
09-22 16:49:33.184  22355-22355/? D/myLogs﹕ MyRun#1 was created in constructor
09-22 16:49:33.186  22355-22375/? D/myLogs﹕ MyRun#1 started
интересно, что если убивать процесс в методе onStartCommand() до return то система сделает только две попытки и больше не будет пробовать. Почему? Наверно потому что используется в этих попытках один и тот же startId. и видимо когда он дважды повторяется с константой флагом START_FLAG_RETRY система понимает что это вечный цикл.
В то же время если останавливать процесс как мы до этого делали (после выполнения onStartCommand()) и получали флаг = 0 (см. логи выше) то система каждую попытку дает аргументом в onStartCommand() каждый раз новый startId и "надеется" что на этот раз selfStop() отработает )))



хорошая статьи для закрепления: http://developer.alexanderklimov.ru/and ... theory.php
схема жизненного цикла перезапуска сервиса: http://programador.ru/sticky-service/

PMostovoj
Сообщения: 1
Зарегистрирован: 19 окт 2014, 16:52

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение PMostovoj » 01 ноя 2015, 00:41

Есть неприятный момент.

Если возвращаем START_STICKY - сервис перезапускается при многократных закрытиях-открытиях приложения, и вроде как постоянно. И это хорошо. ;)

НО !
Если возвращаем START_REDELIVER_INTENT :
сервис перезапускается пять раз, на шестой - сервис не перезапускается и это беда ... :((((

К сожалению нужен постоянно работающий сервис, и не нулевой интент. Кто то знает как с сим боротся?

Аватара пользователя
vorskla
Сообщения: 5
Зарегистрирован: 04 дек 2015, 14:53

Re: Урок 94. Service. Подробно про onStartCommand

Сообщение vorskla » 04 дек 2015, 14:57

Процесс после остановки не оживает хотя START_REDELIVER_INTENT. почему это может быть?

Ответить