Вызов метода через 60 секунд после того, как Activity / App перейдет в фоновый режим

Я хочу очистить буфер обмена через 60 секунд после помещения текста в буфер обмена Android.

Попробовал обработчик postDelayed ниже. Проблема в том, что когда действие прекращается или приложение переходит в фоновый режим (нажата кнопка «Домой»), эта функция не выполняется. Как я могу убедиться, что функция вызывается, когда приложение находится в фоновом режиме?

    final Handler handler = new Handler();
    handler.postDelayed(new Runnable() {
        @Override
        public void run() {
           //Clear clipboard
        }
    }, 60000);

@PacoAbato, спасибо, что указали в правильном направлении. Я обнаружил, что у Google есть служба диспетчера заданий firebase (github.com/firebase/firebase-jobdispatcher-android).

LAX_DEV 03.06.2018 10:52

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

GoRoS 03.06.2018 11:49
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
3
3
196
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поскольку ваша активность не сохраняется после того, как приложение было убито, вы должны выбрать класс Service. Есть некоторые обстоятельства, при которых он также может быть убит, но в нормальном режиме он будет сохраняться в большинстве случаев (в противном случае проверьте службы переднего плана).

Этот подход должен работать:

Ява

public class TestClipboardServiceActivity extends Activity {
    @Override protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        startService(new Intent(this, MyClipboardService.class));

        // Forced the app to be destroyed intentionally.
        finish();
    }
}

/**
 * Clipboard Service. It will clear the clipboard after 60 seconds.
 */
public class MyClipboardService extends Service {

    public class LocalBinder extends Binder {
        MyClipboardService getService() {
            return MyClipboardService.this;
        }
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        Log.i("MyClipboardService", "Received start id " + startId + ": " + intent);

        // Remember, this is executed in the main thread.
        new Handler().postDelayed(new Runnable() {
            @Override public void run() {
                clearClipboard();
            }
        }, 6000);

        return START_STICKY;
    }


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

    private final IBinder mBinder = new LocalBinder();

    /**
     * Clears the clipboard.
     */
    private void clearClipboard() {
        ClipboardManager myClipboard =
            (ClipboardManager) getSystemService(Context.CLIPBOARD_SERVICE);
        if (myClipboard != null) {
            myClipboard.setPrimaryClip(ClipData.newPlainText(null, "");
        }
    }
}

Котлин

class TestClipboardServiceActivity : Activity() {
  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    startService(Intent(this, MyClipboardService::class.java))

    // Forced the app to be destroyed intentionally.
    finish()
  }
}

/**
 * Clipboard Service. It will clear the clipboard after 60 seconds.
 */
class MyClipboardService : Service() {

  private val mBinder = LocalBinder()

  inner class LocalBinder : Binder() {
    internal val service: MyClipboardService
      get() = this@MyClipboardService
  }

  override fun onStartCommand(intent: Intent, flags: Int, startId: Int): Int {
    Log.i("MyClipboardService", "Received start id $startId: $intent")

    // Remember, this is executed in the main thread.
    Handler().postDelayed(this::clearClipboard, 60000)

    return START_STICKY
  }

  override fun onBind(intent: Intent) = mBinder

  /**
   * Clears the clipboard.
   */
  private fun clearClipboard() {
    val myClipboard = getSystemService(Context.CLIPBOARD_SERVICE) as ClipboardManager
    myClipboard.primaryClip = ClipData.newPlainText(null, "")
  }
}

С другой стороны, если вы предпочитаете использовать пользовательскую библиотеку для обработки заданий, я настоятельно рекомендую Android-работа от Evernote. Внутри он даже использует недавний класс WorkManager, а библиотека содержит несколько вариантов планирования, помимо совместимости со многими Android API и отсутствия библиотеки сервисов Google Play. В вашем случае вы можете взглянуть на метод setExact (длинные точные дюймы в миллиметрах), предоставляющий смещение, когда задание должно запускаться с того момента, когда задание было запланировано.

Вопрос специально помечен как Java. Почему ответ - использование котлина?

ישו אוהב אותך 03.06.2018 12:29

@ ישו אוהב אות окей, ты прав, я сначала обновил ответ версией Java, спасибо!

GoRoS 03.06.2018 12:45

Большой! Спасибо за попытку!

ישו אוהב אותך 03.06.2018 12:49

Другие вопросы по теме