Я считаю, что наиболее полезно использовать Runnable для всех упомянутых причин, но иногда мне нравится продлить Thread, поэтому я могу создать свой собственный метод остановки потока и вызвать его непосредственно на созданном мной потоке.
Верно. Хеннинг и P4u144 поставили меня на правильный путь, чтобы ответить на это более подробно.
Определить свою задачу командой adb shell dumpsys jobscheduler
. Это даст вам огромный результат в следующих категориях:
Вы, скорее всего, заинтересованы в категории Зарегистрировано XX Задания . Это говорит о том, сколько заданий запланировано на устройстве. Например, ваше имя_файла com.foo.bar.application
должно выглядеть как:
JOB #u0a93/17: eec3709 com.foo.bar.application/com.evernote.android.job.v21.PlatformJobService
u0a93 tag=*job*/com.foo.bar.application/com.evernote.android.job.v21.PlatformJobService
Source: uid=u0a93 user=0 pkg=com.foo.bar.application
JobInfo:
Service: com.foo.bar.application/com.evernote.android.job.v21.PlatformJobService
PERIODIC: interval=+15m0s0ms flex=+5m0s0ms
PERSISTED
Requires: charging=false deviceIdle=false
Network type: 2
Backoff: policy=1 initial=+30s0ms
Has early constraint
Has late constraint
Required constraints: TIMING_DELAY DEADLINE UNMETERED
Satisfied constraints: CONNECTIVITY NOT_ROAMING APP_NOT_IDLE DEVICE_NOT_DOZING
Unsatisfied constraints: TIMING_DELAY DEADLINE UNMETERED
Earliest run time: 07:23
Latest run time: 12:23
Ready: false (job=false pending=false active=false user=true)
Совет. Используйте
blockquote>adb shell dumpsys jobscheduler | grep com.foo.bar.application
, чтобы быстро отфильтровать список.Теперь вы можете легко определить, была ли зарегистрирована ваша работа с правильными критериями.
FireBaseJobdispatcher
Если вы используете
FirebaseJobDispatcher
lib, вы можете использоватьadb shell dumpsys activity service GcmService | grep com.foo.bar.debug com.foo.bar.debug:0 v853 u0|com.foo.bar.debug: 3 (scheduled) com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="com.foo.bar.debug.job.FetchArticlesJob" trigger=window{start=10800s,end=11700s,earliest=10448s,latest=11348s} requirements=[NET_UNMETERED,DEVICE_IDLE] attributes=[PERSISTED,RECURRING] scheduled=-351s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1} (scheduled) com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="com.foo.bar.debug.job.FetchNotificationGroupsJob" trigger=window{start=86400s,end=129600s,earliest=86048s,latest=129248s} requirements=[NET_CONNECTED,CHARGING] attributes=[PERSISTED,RECURRING] scheduled=-351s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1} (scheduled) com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver{u=0 tag="com.foo.bar.debug.job.RemoveUnusedRealmArticlesJob" trigger=window{start=577980s,end=608400s,earliest=521961s,latest=552381s} requirements=[NET_ANY] attributes=[PERSISTED,RECURRING] scheduled=-56018s last_run=N/A jid=N/A status=PENDING retries=0 client_lib=FIREBASE_JOB_DISPATCHER-1} (finished) [com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver:com.foo.bar.debug.job.UpdateNotificationGroupJob,u0] (finished) [com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver:com.foo.bar.debug.job.UpdatePushTokenJob,u0] (finished) [com.foo.bar.debug/com.firebase.jobdispatcher.GooglePlayReceiver:com.foo.bar.debug.job.FetchArticlesJob,u0]
, чтобы проверить, была ли ваша служба запланирована или запущена.
Заставить свою задачу запускать
При создании
Job
вы получаете возвращенныйJOB_ID
. ИспользуйтеJOB_ID
, чтобы заставить задание работать. Вы можете сделать это, используя командуadb shell cmd jobscheduler run
(требуется Android 7.1 или более поздняя).Например, ваше имя_пакета является
com.foo.bar.application
, аJOB_ID
равно 1. Теперь вы можете выполнить свою задачу черезadb
adb shell cmd jobscheduler run -f com.foo.bar.application 1
Не забывайте параметр
-f
, поскольку это заставляет работу запускаться, даже если установленные ограничения не выполняются.Evernote Android Job Lib
Последнее, но не менее важное. Используйте замечательную библиотеку из Evernote для этого. Это позволяет легко осуществлять резервное копирование
JobScheduler
на более низких уровнях API с использованиемJobScheduler
,GcmNetworkManager
илиAlarmManager
в зависимости от вашего уровня API.Редактировать 24/08
Еще лучше использовать библиотеку диспетчера заданий для firebase.
Firebase JobDispatcher - это библиотека для планирования фоновых заданий в приложении для Android. Он предоставляет API, совместимый с JobScheduler, который работает во всех последних версиях Android (API уровня 9+), в которых установлены сервисы Google Play.
blockquote>Надеюсь, это помогло.
Спасибо
С помощью команды adb shell dumpsys jobscheduler
вы получаете информацию о текущих запланированных и активных заданиях.
Я заметил, что выход из команды сильно отличается между Android 6 и 7. С устройством Android 5 выход очень короткий и иногда загадочный. Интересная часть с зарегистрированными заданиями построена здесь здесь и повторена ниже для удобства, что должно помочь в расшифровке:
@Override
public String toString() {
return String.valueOf(hashCode()).substring(0, 3) + ".."
+ ":[" + job.getService()
+ ",jId=" + job.getId()
+ ",u" + getUserId()
+ ",R=(" + formatRunTime(earliestRunTimeElapsedMillis, NO_EARLIEST_RUNTIME)
+ "," + formatRunTime(latestRunTimeElapsedMillis, NO_LATEST_RUNTIME) + ")"
+ ",N=" + job.getNetworkType() + ",C=" + job.isRequireCharging()
+ ",I=" + job.isRequireDeviceIdle() + ",F=" + numFailures
+ ",P=" + job.isPersisted()
+ (isReady() ? "(READY)" : "")
+ "]";
}
Устройства Android 7, с другой стороны, имеют очень длинный выход с более подробной и более читаемой информацией. Также есть больше возможностей, таких как история. Недостатком является то, что сначала вам нужно найти интересные детали.
Я не нашел способ заставить работу работать, но есть запрос функции для нее. См. ответ от p4u144.
Это работает для меня, без необходимости использовать команды adb. Для этого требуется minSdk 21
@RunWith(AndroidJUnit4.class)
@TargetApi(VERSION_CODES.LOLLIPOP)
public abstract class BaseJobServiceTest {
protected final Context context() {
return InstrumentationRegistry.getTargetContext();
}
protected final void launchJobAndWait(JobInfo jobInfo) throws InterruptedException {
JobScheduler scheduler = (JobScheduler) context().getSystemService(Context.JOB_SCHEDULER_SERVICE);
scheduler.schedule(jobInfo);
while (jobExecutionPending(scheduler, jobInfo)) {
Thread.sleep(50);
}
}
private boolean jobExecutionPending(JobScheduler scheduler, JobInfo jobInfo) {
if (VERSION.SDK_INT >= VERSION_CODES.N) {
return scheduler.getPendingJob(jobInfo.getId()) != null;
}
List<JobInfo> scheduledJobs = scheduler.getAllPendingJobs();
for (int i = 0, size = scheduledJobs.size(); i < size; i++) {
if (scheduledJobs.get(i).getId() == jobInfo.getId()) {
return true;
}
}
return false;
}
}
Начиная с Android 7.0, есть новая cmd
для оболочки adb. И в 7.1 (только в предварительном просмотре прямо сейчас) adb shell cmd jobscheduler
был добавлен , как вы можете видеть здесь , чтобы заставить запустить JobScheduler. Помогает говорит:
Команды планировщика заданий (jobscheduler): help Распечатайте этот текст справки.
запустите [-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID Запустить немедленное выполнение определенного запланированного задания. Параметры: -f или --force: запуск задания, даже если технические ограничения, такие как подключение, в настоящее время не выполняются -u или --user: укажите, какое задание пользователя должно быть запущено; по умолчанию используется основной или системный пользователь
blockquote>
Running job [FORCED]
, но задание не выполняется. Протестировано на эмуляторе с Android O. – Muhammad Babar 26 September 2017 в 10:21