Подтвердить что ты не робот

Как заставить IntentService немедленно остановить кнопку отмены из Activity?

У меня есть IntentService, который запускается из Activity, и я хотел бы иметь возможность немедленно прекратить работу службы с помощью кнопки "cancel" в действии. Как только эта кнопка "отменить" будет нажата, я хочу, чтобы служба прекратила выполнение строк кода.

Я нашел несколько вопросов, подобных этому (т.е. здесь, здесь, здесь, здесь), но нет хороших ответов. Activity.stopService() и Service.stopSelf() немедленно выполните метод Service.onDestroy(), но затем пусть код в onHandleIntent() закончен до полного уничтожения службы.

Поскольку, по-видимому, нет гарантированного способа немедленно прекратить поток обслуживания, единственное рекомендуемое решение, которое я могу найти (здесь), должно быть логическую переменную-член в службе, которая может быть переключена в методе onDestroy(), а затем имеет примерно каждую строку кода в onHandleIntent(), завернутую в свое собственное предложение if if, рассматривающее эту переменную. Это ужасный способ написать код.

Знает ли кто-нибудь лучший способ сделать это в IntentService?

4b9b3361

Ответ 1

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

Объявить службу как отдельный процесс в манифесте:

<service
     android:process=":service"
     ...

И если вы хотите остановить его выполнение, просто убейте этот процесс:

ActivityManager am = (ActivityManager) getSystemService(ACTIVITY_SERVICE);
List<RunningAppProcessInfo> runningAppProcesses = am.getRunningAppProcesses();

Iterator<RunningAppProcessInfo> iter = runningAppProcesses.iterator();

while(iter.hasNext()){
    RunningAppProcessInfo next = iter.next();

    String pricessName = getPackageName() + ":service";

    if(next.processName.equals(pricessName)){
        Process.killProcess(next.pid);
        break;
    }
}

Ответ 2

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

class MyService extends IntentService {
    public static volatile boolean shouldContinue = true;
    public MyService() {
        super("My Service");
    }

    @Override
    protected void onHandleIntent(Intent intent) {
        doStuff();
    }

    private void doStuff() {
        // do something 

        // check the condition
        if (shouldContinue == false) {
            stopSelf();
            return;
        }

       // continue doing something

       // check the condition
       if (shouldContinue == false) {
           stopSelf();
           return;
       }

       // put those checks wherever you need
   }
}

и в своей деятельности сделайте это, чтобы остановить свое обслуживание,

 MyService.shouldContinue = false;

Ответ 3

Я использовал BroadcastReceiver внутри службы, который просто ставит логическое значение stop в true. Пример:

private boolean stop=false;

public class StopReceiver extends BroadcastReceiver {

   public static final String ACTION_STOP = "stop";

   @Override
   public void onReceive(Context context, Intent intent) {
       stop = true;
   }
}


@Override
protected void onHandleIntent(Intent intent) {
    IntentFilter filter = new IntentFilter(StopReceiver.ACTION_STOP);
    filter.addCategory(Intent.CATEGORY_DEFAULT);
    StopReceiver receiver = new StopReceiver();
    registerReceiver(receiver, filter);

    // Do stuff ....

    //In the work you are doing
    if(stop==true){
        unregisterReceiver(receiver);
        stopSelf();
    }
}

Затем из вызова операции:

//STOP SERVICE
Intent sIntent = new Intent();
sIntent.setAction(StopReceiver.ACTION_STOP);
sendBroadcast(sIntent);

Чтобы остановить службу.

PD: Я использую логическое значение, потому что в моем случае я останавливаю службу, находясь в цикле, но вы, вероятно, можете вызвать unregisterReceiver и stopSelf в onReceive.

PD2: не забудьте вызвать unregisterReceiver, если служба завершила его работу нормально или вы получите пропущенную ошибку IntentReceiver.

Ответ 4

В случае IntentService он не останавливается или не принимает какой-либо другой запрос через какое-либо действие до тех пор, пока его метод onHandleIntent не завершит предыдущий запрос.

Если мы снова попытаемся запустить IntentService с помощью другого действия, onHandleIntent будет вызываться только после завершения предыдущего намерения/задачи.

Также stopService(intent); или stopSelf(); не работает, пока метод onHandleIntent() не завершит свою задачу.

Итак, я думаю, что здесь лучше использовать обычный Service здесь.

Надеюсь, это поможет!

Ответ 5

Если вы используете IntentService, то я думаю, что вы застряли над тем, что вы описываете, где код onHandleIntent() должен опросить его сигнал "stop".

Если фоновая задача потенциально длительная, и если вам нужно ее остановить, я думаю, что вам лучше использовать простой Service. На высоком уровне напишите свой Сервис:

  • Представьте "начало" намерения запустить AsyncTask для выполнения фоновой работы, сохранив ссылку на эту недавно созданную AsyncTask.
  • Выставить намерение "отменить" для вызова AsyncTask.cancel(true) или включить onDestroy() invoke AsyncTask.cancel(true).
  • Затем действие может либо отправить намерение "отменить", либо просто вызвать stopService().

В обмен на возможность отмены фоновой работы Служба берет на себя следующие обязанности:

  • AsyncTask doInBackground() должен будет изящно обрабатывать InterruptedException и/или периодически проверять Thread.interrupted() и возвращать "раньше".
  • Служба должна гарантировать, что вызывается stopSelf() (возможно, в AsyncTask onPostExecute/onCancelled).

Ответ 6

@Override
protected void onHandleIntent(Intent intent) {
    String action = intent.getAction();
    if (action.equals(Action_CANCEL)) {
        stopSelf();
    } else if (action.equals(Action_START)) {
        //handle
    }
}

Надеюсь, что это сработает.

Ответ 7

Как уже упоминалось в его комментарии @budius, вы должны установить boolean на Service, когда вы нажимаете эту кнопку:

// your Activity.java
public boolean onClick() {
   //...
   mService.performTasks = false;
   mService.stopSelf();
}

И в вашей обработке Intent перед тем, как выполнить важную задачу для передачи/отправки информации о намерениях, просто используйте это логическое значение:

// your Service.java
public boolean performTasks = true;

protected void onHandleIntent(Intent intent) {
   Bundle intentInfo = intent.getBundle();
   if (this.performTasks) {
      // Then handle the intent...
   }
}

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

Ответ 8

Вот пример кода для запуска/остановки службы

Чтобы начать,

Intent GPSService = new Intent(context, TrackGPS.class);
context.startService(GPSService);

Чтобы остановить,

context.stopService(GPSService);

Ответ 9

context.stopService(GPSService);