我们正在通过JobScheduler实施一项工作,用于后台加载数据。这项工作每天会开一次。我们可以使用哪些工具来测试此功能(可能是ADB)?
用例应能够模拟作业运行所需的条件,或者只是说“运行此作业”作为我们自动化测试套件的一部分。
答案 0 :(得分:87)
右。
Henning和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)
提示:使用
adb shell dumpsys jobscheduler | grep com.foo.bar.application
快速过滤列表。
现在,您可以轻松识别您的工作是否已使用正确的标准进行注册。
如果您使用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
选项,因为这会强制作业运行,即使设置的限制未得到满足。
最后但并非最不重要
请使用the wonderful library from Evernote。
根据您的API级别,它允许使用JobScheduler
,JobScheduler
或GcmNetworkManager
在较低的API级别轻松向后移植AlarmManager
。
更好地使用firebase作业调度程序库。
Firebase JobDispatcher是一个用于在Android应用中安排后台作业的库。它提供了与JobScheduler兼容的API,适用于安装了Google Play服务的所有最新版本的Android(API级别9+)。
我希望这有帮助。
由于
Evernote Android-Job和Firebase JobDispatcher现在都处于仅维护模式,他们都建议使用jetpack WorkManager来完成这些工作。
答案 1 :(得分:16)
使用命令adb shell dumpsys jobscheduler
,您可以获得有关当前计划和活动作业的信息。
我注意到Android 6和7之间命令的输出差别很大。使用 Android 5 设备,输出很短,有时很神秘。注册作业的有趣部分是构建here并在下面重复以方便起见,这应该有助于解密:
@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 设备具有非常长的输出,具有更详细和更好的可读信息。还有更多的功能,如历史。缺点是你必须先找到有趣的部分。
我还没有办法强迫一份工作继续,there is a feature request for it. 请参阅p4u144的答案。
答案 2 :(得分:14)
从Android 7.0开始,adb shell有一个新的cmd
。在7.1中(仅在预览中),adb shell cmd jobscheduler
已添加as you can see here以强制运行JobScheduler。
帮助说:
作业调度程序(jobscheduler)命令:help 打印此帮助文本。
运行[-f | --force] [-u | --user USER_ID] PACKAGE JOB_ID 触发立即执行特定的预定作业。 选项: -f或--force:即使是技术限制,也可以运行作业 目前尚未达到连接 -u或--user:指定要运行哪个用户的作业;默认是 主要用户或系统用户
答案 3 :(得分:-1)
这对我有用,无需使用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;
}
}