Урок 93. Service. Передача данных в сервис. Методы остановки сервиса
Урок 93. Service. Передача данных в сервис. Методы остановки сервиса
В этом уроке:
- передаем данные в сервис
- рассматриваем методы остановки сервиса stopSelf и stopSelfResult
Click here to read this article!
- передаем данные в сервис
- рассматриваем методы остановки сервиса stopSelf и stopSelfResult
Click here to read this article!
Последний раз редактировалось damager82 22 май 2017, 23:42, всего редактировалось 4 раза.
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Несмотря на обилие нового материла (чего стоит только экзэкутер), всё классно объяснено. Делаю сейчас приложение, основным элементом которого будет сервис, который запускается из главного активити и через заданный (опять же в активити) интервал спрашивает координаты у геолокационного сервиса и отсылает их гет-запросом на сервер (естественно не в потоке активити). Наверное неделю уже курю тему Сервисы на разных сайтах и никак не могу определиться по некоторым вопросам ( где лучше создавать слушатель координат, с помощью чего удобнее и рациональнее общаться с сервисом (хэндлы,биндинг или AIDL )?) Вы не наставите на путь истинный? Или возможно я поспешил и после следующих уроков мне всё станет ясно.. тогда прошу простить за нетерпение.
Re: Урок 93. Service. Передача данных в сервис. Методы остан
на мой взгляд проще и удобней общаться при помощи AIDL, давно с ним не работал, но в проектах активно его используем.
R.id.team
Политика на форуме запрещена
Политика на форуме запрещена
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Спасибо! Интересно в уроках он есть..? Ладно так или иначе буду уроки смотреть здесь.rezak90 писал(а):на мой взгляд проще и удобней общаться при помощи AIDL, давно с ним не работал, но в проектах активно его используем.
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Не, в уроках только локальный биндинг. AIDL чуть сложнее,но смысл тот же.brucemax писал(а):Спасибо! Интересно в уроках он есть..? Ладно так или иначе буду уроки смотреть здесь.rezak90 писал(а):на мой взгляд проще и удобней общаться при помощи AIDL, давно с ним не работал, но в проектах активно его используем.
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Уроки все прочитал по сервисам, но пишу тут, потому что тут раскрывается моя проблема.
А все-таки как решать задачу, когда последний сервис сработав раньше первого более долгоиграющего убьет сервис и что делать? Никак не могу понять.
Если я в сервисе стартую таймер на разовое выполнение, мне сервис нужно убивать сразу (он по сути мне не нужен более) или после срабатывания таймера? Спасибо
А все-таки как решать задачу, когда последний сервис сработав раньше первого более долгоиграющего убьет сервис и что делать? Никак не могу понять.
Если я в сервисе стартую таймер на разовое выполнение, мне сервис нужно убивать сразу (он по сути мне не нужен более) или после срабатывания таймера? Спасибо
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Использовать binding.dubok79 писал(а):Уроки все прочитал по сервисам, но пишу тут, потому что тут раскрывается моя проблема.
А все-таки как решать задачу, когда последний сервис сработав раньше первого более долгоиграющего убьет сервис и что делать? Никак не могу понять.
Первое что приходит, что лучше оставить до завершения таймера, ибо это будет гарантом, что система ничего не удалит.. Но я могу ошибаться.Если я в сервисе стартую таймер на разовое выполнение, мне сервис нужно убивать сразу (он по сути мне не нужен более) или после срабатывания таймера? Спасибо
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Друзья! Не убивается уведомление =( Ставил везде, где мог stopService(...) - не работает.
Смотрите код, пожалуйста.
public class MyService extends Service {
NotificationManager nm;
ExecutorService es;
final String TAG = "ServiceLog";
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
es = Executors.newFixedThreadPool(1);
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
Log.d(TAG, "startID = " + startId);
srv s = new srv(startId);
es.execute(s);
new Thread(s).start();
sendNotif();
return START_STICKY;
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onDestroy() {
super.onDestroy();
// stopSelf();
stopService(new Intent(this, MyService.class));
Log.d(TAG, "onDestroy");
}
@SuppressLint("NewApi")
void sendNotif() {
Intent in = new Intent(this, MainActivity.class);
PendingIntent pin = PendingIntent.getActivity(this, 0, in, 0);
Notification notif = new Notification.Builder(this)
.setContentTitle("Программа запущена")
.setContentText("Нажмите, чтобы открыть приложение")
.setSmallIcon(R.drawable.ic_launcher)
.addAction(0, "Открыть приложение", pin)
.build();
// ставим флаг, чтобы уведомление пропало после нажатия
notif.flags |= Notification.FLAG_ONGOING_EVENT;
// отправляем
nm.notify(1, notif);
}
public class srv implements Runnable {
final String TAG = "SrvLog";
int startID;
public srv(int startID){
this.startID = startID;
}
public void run() {
Log.d(TAG, "Service started with id = " + startID);
stop();
}
public void stop() {
stopSelf(startID);
}
}
}
Смотрите код, пожалуйста.
public class MyService extends Service {
NotificationManager nm;
ExecutorService es;
final String TAG = "ServiceLog";
public void onCreate() {
super.onCreate();
Log.d(TAG, "onCreate");
nm = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
es = Executors.newFixedThreadPool(1);
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "onStartCommand");
Log.d(TAG, "startID = " + startId);
srv s = new srv(startId);
es.execute(s);
new Thread(s).start();
sendNotif();
return START_STICKY;
}
@Override
public IBinder onBind(Intent arg0) {
return null;
}
public void onDestroy() {
super.onDestroy();
// stopSelf();
stopService(new Intent(this, MyService.class));
Log.d(TAG, "onDestroy");
}
@SuppressLint("NewApi")
void sendNotif() {
Intent in = new Intent(this, MainActivity.class);
PendingIntent pin = PendingIntent.getActivity(this, 0, in, 0);
Notification notif = new Notification.Builder(this)
.setContentTitle("Программа запущена")
.setContentText("Нажмите, чтобы открыть приложение")
.setSmallIcon(R.drawable.ic_launcher)
.addAction(0, "Открыть приложение", pin)
.build();
// ставим флаг, чтобы уведомление пропало после нажатия
notif.flags |= Notification.FLAG_ONGOING_EVENT;
// отправляем
nm.notify(1, notif);
}
public class srv implements Runnable {
final String TAG = "SrvLog";
int startID;
public srv(int startID){
this.startID = startID;
}
public void run() {
Log.d(TAG, "Service started with id = " + startID);
stop();
}
public void stop() {
stopSelf(startID);
}
}
}
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Привет всем!
Есть Service, в onStartCommand возвращаю START_REDELIVER_INTENT для восстановления незавершенных вызовов, сохраняя Intent. В onStartCommand создаю новый поток и запихиваю его в пул ExecutorService для поочередного выполнения (executor = Executors.newFixedThreadPool(1)), сохраняя startId в классе потока. По завершению работы потока (в run()) вызываю stopSelfResult(startId). Поток знает свой startId.
Из Activity делаю 2 вызова запуска сервиса, соответственно в сервисе 2 раза срабатывает onStartCommand и создает 2 потока с startId 1 и 2. По завершению первого потока (startId = 1) stopselfResult = false, по завершению второго потока stopselfResult = true, т.к. startId=2 является последним вызовом и сервис останавливается. Все ок.
Проблема в следующем :
Ничего не меняю в вызовах. Специально убиваю приложение сразу после получения двух вызовов onStartCommand и запуска первого потока (startId = 1). Жду когда сервис восстановится и восстановит незавершенные вызовы.. так и происходит.. Сервис создается (onCreate()), 2 раза срабатывает onStartCommand (на входе имею startId = 1 и startId = 2 и восстановленные Intent-ы), создаются потоки и отсылаются на выполнение в ExecutorService. По завершению первого потока (startId = 1) stopselfResult = false, по завершению второго потока (startId = 2)... внимание... stopselfResult = false... и соответственно сервис НЕ ОСТАНАВЛИВАЕТСЯ.. Как так?? Сервис останавливает только принудительный вызов stopselfResult(3).... Но откуда взялся третий вызов onStartCommand ? StartId были только 1 и 2.
Друзья, подскажите, почему так происходит..
Есть Service, в onStartCommand возвращаю START_REDELIVER_INTENT для восстановления незавершенных вызовов, сохраняя Intent. В onStartCommand создаю новый поток и запихиваю его в пул ExecutorService для поочередного выполнения (executor = Executors.newFixedThreadPool(1)), сохраняя startId в классе потока. По завершению работы потока (в run()) вызываю stopSelfResult(startId). Поток знает свой startId.
Из Activity делаю 2 вызова запуска сервиса, соответственно в сервисе 2 раза срабатывает onStartCommand и создает 2 потока с startId 1 и 2. По завершению первого потока (startId = 1) stopselfResult = false, по завершению второго потока stopselfResult = true, т.к. startId=2 является последним вызовом и сервис останавливается. Все ок.
Проблема в следующем :
Ничего не меняю в вызовах. Специально убиваю приложение сразу после получения двух вызовов onStartCommand и запуска первого потока (startId = 1). Жду когда сервис восстановится и восстановит незавершенные вызовы.. так и происходит.. Сервис создается (onCreate()), 2 раза срабатывает onStartCommand (на входе имею startId = 1 и startId = 2 и восстановленные Intent-ы), создаются потоки и отсылаются на выполнение в ExecutorService. По завершению первого потока (startId = 1) stopselfResult = false, по завершению второго потока (startId = 2)... внимание... stopselfResult = false... и соответственно сервис НЕ ОСТАНАВЛИВАЕТСЯ.. Как так?? Сервис останавливает только принудительный вызов stopselfResult(3).... Но откуда взялся третий вызов onStartCommand ? StartId были только 1 и 2.
Друзья, подскажите, почему так происходит..
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Т.е. мы в данном примере не имеем никакой возможности "сказать" чтобы при вызове второго stopSelf сервис не убивался?
Почему нельзя проверять счётчик и отменять stop?
Почему нельзя проверять счётчик и отменять stop?
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Поэкспериментировал с кодом, сделал чтобы сервис не убивался.
[syntax=java]import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
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 TAG = "mylog";
ExecutorService es;
Object someRes;
ArrayList<Integer> userPool;
ArrayList<Integer> userPoolFinish;
public void onCreate() {
super.onCreate();
Log.d(TAG, "MyService onCreate");
es = Executors.newFixedThreadPool(3);
someRes = new Object();
userPool = new ArrayList<Integer>();
userPoolFinish = new ArrayList<Integer>();
}
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "MyService onDestroy");
someRes = null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "MyService onStartCommand");
userPool.add(startId);
int time = intent.getIntExtra("time", 1);
MyRun mr = new MyRun(time, startId);
es.execute(mr);
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent arg0) {
return null;
}
class MyRun implements Runnable {
int time;
int startId;
public MyRun(int time, int startId) {
this.time = time;
this.startId = startId;
Log.d(TAG, "MyRun#" + startId + " create");
}
public void run() {
Log.d(TAG, "MyRun#" + startId + " start, time = " + time);
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Log.d(TAG,
"MyRun#" + startId + " someRes = " + someRes.getClass());
} catch (NullPointerException e) {
Log.d(TAG, "MyRun#" + startId + " error, null pointer");
}
stop();
}
void stop() {
//Log.d(TAG, "MyRun#" + startId + " end, stopSelfResult("
// + startId + ") = " + stopSelfResult(startId));
userPoolFinish.add(startId);
Log.d(TAG, "startId= " + startId);
if (userPool.size() == userPoolFinish.size())
{
for (int i = 0 ; i < userPool.size(); i++) {
Log.d(TAG, "userPool.get(i): " + userPool.get(i));
Log.d(TAG, "MyRun#" + userPool.get(i) + " end, stopSelf(" + userPool.get(i)
+ ")");
stopSelf(userPool.get(i));
Log.d(TAG, "MyRun ------ " + userPool.get(i) + " end, stopSelfResult("
+ userPool.get(i) + ") = " + stopSelfResult(userPool.get(i)));
}
Log.d(TAG, "stopSelfResult(1) = " + stopSelfResult(1));
Log.d(TAG, "stopSelfResult(2) = " + stopSelfResult(2));
Log.d(TAG, "stopSelfResult(3) = " + stopSelfResult(3));
}
}
}
}[/syntax]
Лог
[syntax=xml]12-05 16:09:07.721: D/mylog(985): MyService onCreate
12-05 16:09:07.730: D/mylog(985): MyService onStartCommand
12-05 16:09:07.730: D/mylog(985): MyRun#1 create
12-05 16:09:07.741: D/mylog(985): MyService onStartCommand
12-05 16:09:07.741: D/mylog(985): MyRun#2 create
12-05 16:09:07.741: D/mylog(985): MyRun#1 start, time = 7
12-05 16:09:07.741: D/mylog(985): MyService onStartCommand
12-05 16:09:07.752: D/mylog(985): MyRun#3 create
12-05 16:09:07.752: D/mylog(985): MyRun#2 start, time = 2
12-05 16:09:07.761: D/mylog(985): MyRun#3 start, time = 4
12-05 16:09:09.784: D/mylog(985): MyRun#2 someRes = class java.lang.Object
12-05 16:09:09.784: D/mylog(985): startId= 2
12-05 16:09:11.791: D/mylog(985): MyRun#3 someRes = class java.lang.Object
12-05 16:09:11.791: D/mylog(985): startId= 3
12-05 16:09:14.766: D/mylog(985): MyRun#1 someRes = class java.lang.Object
12-05 16:09:14.766: D/mylog(985): startId= 1
12-05 16:09:14.766: D/mylog(985): userPool.get(i): 1
12-05 16:09:14.766: D/mylog(985): MyRun#1 end, stopSelf(1)
12-05 16:09:14.784: D/mylog(985): MyRun ------ 1 end, stopSelfResult(1) = false
12-05 16:09:14.784: D/mylog(985): userPool.get(i): 2
12-05 16:09:14.784: D/mylog(985): MyRun#2 end, stopSelf(2)
12-05 16:09:14.784: D/mylog(985): MyRun ------ 2 end, stopSelfResult(2) = false
12-05 16:09:14.791: D/mylog(985): userPool.get(i): 3
12-05 16:09:14.791: D/mylog(985): MyRun#3 end, stopSelf(3)
12-05 16:09:14.791: D/mylog(985): MyService onDestroy
12-05 16:09:14.801: D/mylog(985): MyRun ------ 3 end, stopSelfResult(3) = false
12-05 16:09:14.801: D/mylog(985): stopSelfResult(1) = false
12-05 16:09:14.801: D/mylog(985): stopSelfResult(2) = false
12-05 16:09:14.801: D/mylog(985): stopSelfResult(3) = false[/syntax]
Видим, что stopSelfResult() вернул false, для всех потоков.
Кто остановил сервис?
[syntax=java]import java.util.ArrayList;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
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 TAG = "mylog";
ExecutorService es;
Object someRes;
ArrayList<Integer> userPool;
ArrayList<Integer> userPoolFinish;
public void onCreate() {
super.onCreate();
Log.d(TAG, "MyService onCreate");
es = Executors.newFixedThreadPool(3);
someRes = new Object();
userPool = new ArrayList<Integer>();
userPoolFinish = new ArrayList<Integer>();
}
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "MyService onDestroy");
someRes = null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
Log.d(TAG, "MyService onStartCommand");
userPool.add(startId);
int time = intent.getIntExtra("time", 1);
MyRun mr = new MyRun(time, startId);
es.execute(mr);
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent arg0) {
return null;
}
class MyRun implements Runnable {
int time;
int startId;
public MyRun(int time, int startId) {
this.time = time;
this.startId = startId;
Log.d(TAG, "MyRun#" + startId + " create");
}
public void run() {
Log.d(TAG, "MyRun#" + startId + " start, time = " + time);
try {
TimeUnit.SECONDS.sleep(time);
} catch (InterruptedException e) {
e.printStackTrace();
}
try {
Log.d(TAG,
"MyRun#" + startId + " someRes = " + someRes.getClass());
} catch (NullPointerException e) {
Log.d(TAG, "MyRun#" + startId + " error, null pointer");
}
stop();
}
void stop() {
//Log.d(TAG, "MyRun#" + startId + " end, stopSelfResult("
// + startId + ") = " + stopSelfResult(startId));
userPoolFinish.add(startId);
Log.d(TAG, "startId= " + startId);
if (userPool.size() == userPoolFinish.size())
{
for (int i = 0 ; i < userPool.size(); i++) {
Log.d(TAG, "userPool.get(i): " + userPool.get(i));
Log.d(TAG, "MyRun#" + userPool.get(i) + " end, stopSelf(" + userPool.get(i)
+ ")");
stopSelf(userPool.get(i));
Log.d(TAG, "MyRun ------ " + userPool.get(i) + " end, stopSelfResult("
+ userPool.get(i) + ") = " + stopSelfResult(userPool.get(i)));
}
Log.d(TAG, "stopSelfResult(1) = " + stopSelfResult(1));
Log.d(TAG, "stopSelfResult(2) = " + stopSelfResult(2));
Log.d(TAG, "stopSelfResult(3) = " + stopSelfResult(3));
}
}
}
}[/syntax]
Лог
[syntax=xml]12-05 16:09:07.721: D/mylog(985): MyService onCreate
12-05 16:09:07.730: D/mylog(985): MyService onStartCommand
12-05 16:09:07.730: D/mylog(985): MyRun#1 create
12-05 16:09:07.741: D/mylog(985): MyService onStartCommand
12-05 16:09:07.741: D/mylog(985): MyRun#2 create
12-05 16:09:07.741: D/mylog(985): MyRun#1 start, time = 7
12-05 16:09:07.741: D/mylog(985): MyService onStartCommand
12-05 16:09:07.752: D/mylog(985): MyRun#3 create
12-05 16:09:07.752: D/mylog(985): MyRun#2 start, time = 2
12-05 16:09:07.761: D/mylog(985): MyRun#3 start, time = 4
12-05 16:09:09.784: D/mylog(985): MyRun#2 someRes = class java.lang.Object
12-05 16:09:09.784: D/mylog(985): startId= 2
12-05 16:09:11.791: D/mylog(985): MyRun#3 someRes = class java.lang.Object
12-05 16:09:11.791: D/mylog(985): startId= 3
12-05 16:09:14.766: D/mylog(985): MyRun#1 someRes = class java.lang.Object
12-05 16:09:14.766: D/mylog(985): startId= 1
12-05 16:09:14.766: D/mylog(985): userPool.get(i): 1
12-05 16:09:14.766: D/mylog(985): MyRun#1 end, stopSelf(1)
12-05 16:09:14.784: D/mylog(985): MyRun ------ 1 end, stopSelfResult(1) = false
12-05 16:09:14.784: D/mylog(985): userPool.get(i): 2
12-05 16:09:14.784: D/mylog(985): MyRun#2 end, stopSelf(2)
12-05 16:09:14.784: D/mylog(985): MyRun ------ 2 end, stopSelfResult(2) = false
12-05 16:09:14.791: D/mylog(985): userPool.get(i): 3
12-05 16:09:14.791: D/mylog(985): MyRun#3 end, stopSelf(3)
12-05 16:09:14.791: D/mylog(985): MyService onDestroy
12-05 16:09:14.801: D/mylog(985): MyRun ------ 3 end, stopSelfResult(3) = false
12-05 16:09:14.801: D/mylog(985): stopSelfResult(1) = false
12-05 16:09:14.801: D/mylog(985): stopSelfResult(2) = false
12-05 16:09:14.801: D/mylog(985): stopSelfResult(3) = false[/syntax]
Видим, что stopSelfResult() вернул false, для всех потоков.
Кто остановил сервис?
Когда выкладываете код на форум - код оформляйте. Редактор - поищите слова Geshi Syntax -Java. (или xml)
Свои сообщения можно редактировать - кнопка edit.
Свои сообщения можно редактировать - кнопка edit.
Re: Урок 93. Service. Передача данных в сервис. Методы остан
штука смотрю совершенно не предсказуемая, вот еще пример:)
создаю сервис и запускаю на 30 секунд, во время работы делаю stopService - сервис продолжает работать.
закрываю активити - сервис работает, но даже после того как отработал не уничтожился.
опять открываю активити, запускаю сервис, делаю stopService и выхожу из активити
сервис как и в прошлый рас работает
запускаю опять активити, запускаю сервис и у меня уже 2 сервиса спамят лог:)
в общем успешно уничтожился, только когда дождался как он отработает и после этого сделал stopService
создаю сервис и запускаю на 30 секунд, во время работы делаю stopService - сервис продолжает работать.
закрываю активити - сервис работает, но даже после того как отработал не уничтожился.
опять открываю активити, запускаю сервис, делаю stopService и выхожу из активити
сервис как и в прошлый рас работает
запускаю опять активити, запускаю сервис и у меня уже 2 сервиса спамят лог:)
в общем успешно уничтожился, только когда дождался как он отработает и после этого сделал stopService
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Это как в Java, если запустить поток с while(true), то interrupt его ни фига не прервет. Кстати, кто знает, как остановить такой поток?
Простите за тупую аналогию))
Простите за тупую аналогию))
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: Урок 93. Service. Передача данных в сервис. Методы остан
interrupt - это флаг потоку, который надо проверять и думать, когда остановить поток. Раньше был stop, но останавливать в произвольный момент времени поток не есть хорошо, поэтому придумали этот флаг. Каждый раз при начале цикла, либо логической цепочки, можно проверять данный флаг.
Еще как вариант, бросать return false внутри цикла и выходить с него.
еще как вариант, если используется Thread.sleep, то тот де вроде interrupt, Либо join (не помню). Тогда вылетет исключение и поток завершится. То, что вылетет исключение - это нормально в данном случае.
Еще как вариант, бросать return false внутри цикла и выходить с него.
еще как вариант, если используется Thread.sleep, то тот де вроде interrupt, Либо join (не помню). Тогда вылетет исключение и поток завершится. То, что вылетет исключение - это нормально в данном случае.
- Mikhail_dev
- Сообщения: 2386
- Зарегистрирован: 09 янв 2012, 14:45
- Откуда: Самара
Re: Урок 93. Service. Передача данных в сервис. Методы остан
У вас утечка. Почитайте данную статью - http://habrahabr.ru/post/222199/штука смотрю совершенно не предсказуемая, вот еще пример:)
создаю сервис и запускаю на 30 секунд, во время работы делаю stopService - сервис продолжает работать.
закрываю активити - сервис работает, но даже после того как отработал не уничтожился.
опять открываю активити, запускаю сервис, делаю stopService и выхожу из активити
сервис как и в прошлый рас работает
запускаю опять активити, запускаю сервис и у меня уже 2 сервиса спамят лог:)
в общем успешно уничтожился, только когда дождался как он отработает и после этого сделал stopService
Re: Урок 93. Service. Передача данных в сервис. Методы остан
Стало любопытно. Идея с вводом счетчика для отлова потоков правильная,
только мне не нужен НЕ убиваемый сервис как у пользователя выше.
Вот мой вариант кода полностью годный для примера. Там много тэгов для разностороннего учета.
Самое забавное если не занулять объект в блоке уничтожения сервиса, он доступен после. Как-то неправильно...
только мне не нужен НЕ убиваемый сервис как у пользователя выше.
Вот мой вариант кода полностью годный для примера. Там много тэгов для разностороннего учета.
Код: Выделить всё
public class MyService extends Service {
final String TAG = "mylog";
ExecutorService es;
Object someRes;
int EndId = 0;
int WorkCount = 0;
Boolean OnStop = false;
public void onCreate() {
super.onCreate();
Log.d(TAG, "MyService onCreate");
es = Executors.newFixedThreadPool(3);
someRes = new Object();
}
public void onDestroy() {
super.onDestroy();
Log.d(TAG, "MyService onDestroy");
OnStop = true;
someRes = null;
}
public int onStartCommand(Intent intent, int flags, int startId) {
EndId++;
WorkCount += startId;
Log.d(TAG, "MyService onStartCommand");
int time = intent.getIntExtra("time", 1);
MyRun mr = new MyRun(time, startId);
es.execute(mr);
return super.onStartCommand(intent, flags, startId);
}
public IBinder onBind(Intent arg0) {
return null;
}
class MyRun implements Runnable {
int time;
int startId;
public MyRun(int time, int startId) {
this.time = time;
this.startId = startId;
Log.d(TAG, "MyRun#" + startId + " create");
}
public void run() {
if (OnStop) {
Log.d(TAG, "MyRun#" + startId + " start, service destroyed, Exit.");
return;
}
Log.d(TAG, "MyRun#" + startId + " start, time = " + time);
try { TimeUnit.SECONDS.sleep(time); }
catch (InterruptedException e) { e.printStackTrace(); }
if (OnStop) {
Log.d(TAG, "MyRun#" + startId + " after SLEEP, service destroyed, Exit.");
return;
}
try {Log.d(TAG,"MyRun#" + startId + " someRes = " + someRes.getClass());
} catch (NullPointerException e) { Log.d(TAG, "MyRun#" + startId + " error, null pointer"); }
stop();
}
void stop() {
if (OnStop) {
Log.d(TAG, "MyRun#" + startId + " end, + service destroyed..");
} else
if (WorkCount == startId) {
Log.d(TAG, "MyRun#" + startId + " last end, stopSelfResult("+ EndId + ") = " + stopSelfResult(EndId));
} else {
WorkCount -= startId;
Log.d(TAG, "MyRun#" + startId + " end, Wait for stop previus");
}
}
}
}
Re: Урок 93. Service. Передача данных в сервис. Методы остан
1. странно видеть имена переменных с большой буквыNialon писал(а): int WorkCount = 0;
WorkCount += startId;
2. WorkCount увеличивается не на +1, а на значение startId, то есть +1 +2 +3, выглядит подозрительно
-
- Сообщения: 42
- Зарегистрирован: 25 янв 2015, 18:57
Re: Урок 93. Service. Передача данных в сервис. Методы остан
К слову о том, почему автор пишет, что "Но на самом деле алгоритм чуть другой. Сервис останавливается, когда последний полученный (а не последний обработанный) вызов выполняет метод stopSelf(startId). А при этом могут продолжать работать ранее полученные вызовы. Почему так сделано – я не знаю."
Согласно официальным докам(https://developer.android.com/guide/com ... l#Stopping),
"If your service handles multiple requests to onStartCommand() concurrently, you shouldn't stop the service when you're done processing a start request, as you might have received a new start request (stopping at the end of the first request would terminate the second one). To avoid this problem, you can use stopSelf(int) to ensure that your request to stop the service is always based on the most recent start request. That is, when you call stopSelf(int), you pass the ID of the start request (the startId delivered to onStartCommand()) to which your stop request corresponds. Then, if the service receives a new start request before you are able to call stopSelf(int), the ID does not match and the service does not stop."
"Если ваш сервис обрабатывает множество запросов одновременно (onStartCommand()), вам не следует останавливать сервис, когда завершилась обработка запроса, так как сервис может принять новый запрос (остановка сервиса в конце первого запроса завершит и второй). Чтобы избежать этого, можно использовать stopSelf(int) чтобы удостовериться, что ваш запрос на остановку сервиса всегда базируется на самом последнем запросе старта. Поэтому, когда вы вызываете метод stopSelf(int), вы передаете id запроса старта(которое потом попадает в onStartCommand(), к которому относится ваш запрос на остановку. Тогда, если сервис получит новый запрос на старт перед тем как у вас есть возможность вызвать stopSelft(int), ID не совпадет и сервис не остановится)."
Надеюсь, кому-то помог.
Согласно официальным докам(https://developer.android.com/guide/com ... l#Stopping),
"If your service handles multiple requests to onStartCommand() concurrently, you shouldn't stop the service when you're done processing a start request, as you might have received a new start request (stopping at the end of the first request would terminate the second one). To avoid this problem, you can use stopSelf(int) to ensure that your request to stop the service is always based on the most recent start request. That is, when you call stopSelf(int), you pass the ID of the start request (the startId delivered to onStartCommand()) to which your stop request corresponds. Then, if the service receives a new start request before you are able to call stopSelf(int), the ID does not match and the service does not stop."
"Если ваш сервис обрабатывает множество запросов одновременно (onStartCommand()), вам не следует останавливать сервис, когда завершилась обработка запроса, так как сервис может принять новый запрос (остановка сервиса в конце первого запроса завершит и второй). Чтобы избежать этого, можно использовать stopSelf(int) чтобы удостовериться, что ваш запрос на остановку сервиса всегда базируется на самом последнем запросе старта. Поэтому, когда вы вызываете метод stopSelf(int), вы передаете id запроса старта(которое потом попадает в onStartCommand(), к которому относится ваш запрос на остановку. Тогда, если сервис получит новый запрос на старт перед тем как у вас есть возможность вызвать stopSelft(int), ID не совпадет и сервис не остановится)."
Надеюсь, кому-то помог.
Re: Урок 93. Service. Передача данных в сервис. Методы остановки сервиса
Не смог заменит логи на тосты и вывести в UI, жаль...