Skip to content

Commit 6fbf61a

Browse files
Changed|Fixed(JobSchedulerAPI): Fix ResultReturner.returnData() being called multiple times for different printing since 51a02f4 and 61262f7 throwing Connection refused exceptions for calls after the first one instead of printing, and also refactor actions out to functions and change action output format
The `ResultReturner.returnData()` will be called once for each action. The schedule job action will not print all pending jobs at end and only the pending job that was scheduled if successful. Users should use `termux-job-scheduler -p` to get all pending jobs. The `termux-job-scheduler --p` action will print `No jobs found` instead of `No pending jobs` if no pending job exists. The `termux-job-scheduler --cancel-all` action will now print all jobs to be cancelled, or `No jobs found` found. The job description will use `4` spaces instead of a tab after the path. ``` Error in ResultReturner: java.io.IOException: Connection refused at android.net.LocalSocketImpl.connectLocal(Native Method) at android.net.LocalSocketImpl.connect(LocalSocketImpl.java:259) at android.net.LocalSocket.connect(LocalSocket.java:162) at com.termux.api.util.ResultReturner.lambda$returnData$0(ResultReturner.java:250) at com.termux.api.util.ResultReturner$$ExternalSyntheticLambda0.run(D8$$SyntheticClass:0) at java.lang.Thread.run(Thread.java:1119) Suppressed: java.lang.Exception: Called by: at com.termux.api.util.ResultReturner.returnData(ResultReturner.java:239) at com.termux.api.apis.JobSchedulerAPI.displayPendingJobs(JobSchedulerAPI.java:197) at com.termux.api.apis.JobSchedulerAPI.onReceive(JobSchedulerAPI.java:181) at com.termux.api.TermuxApiReceiver.doWork(TermuxApiReceiver.java:146) at com.termux.api.TermuxApiReceiver.onReceive(TermuxApiReceiver.java:65) at android.app.ActivityThread.handleReceiver(ActivityThread.java:5029) at android.app.ActivityThread.-$$Nest$mhandleReceiver(Unknown Source:0) at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2577) at android.os.Handler.dispatchMessage(Handler.java:110) at android.os.Looper.loopOnce(Looper.java:248) at android.os.Looper.loop(Looper.java:338) at android.app.ActivityThread.main(ActivityThread.java:9067) at java.lang.reflect.Method.invoke(Native Method) at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:593) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:932) ``` ```shell ~ $ termux-job-scheduler -s ~/test1.sh --period-ms 900000 --job-id 1 Scheduling Job 1: /data/data/com.termux/files/home/test1.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) - response 1 Pending Job 1: /data/data/com.termux/files/home/test1.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) ~ $ termux-job-scheduler -s ~/test2.sh --period-ms 900000 --job-id 2 Scheduling Job 2: /data/data/com.termux/files/home/test2.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) - response 1 Pending Job 2: /data/data/com.termux/files/home/test2.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) ~ $ termux-job-scheduler -s ~/test3.sh --period-ms 900000 --job-id 3 Scheduling Job 3: /data/data/com.termux/files/home/test3.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) - response 1 Pending Job 3: /data/data/com.termux/files/home/test3.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) ~ $ termux-job-scheduler -p Pending Job 3: /data/data/com.termux/files/home/test3.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) Pending Job 2: /data/data/com.termux/files/home/test2.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) Pending Job 1: /data/data/com.termux/files/home/test1.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) ~ $ termux-job-scheduler --cancel --job-id 2 Cancelling Job 2: /data/data/com.termux/files/home/test2.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) ~ $ termux-job-scheduler --cancel-all Cancelling Job 3: /data/data/com.termux/files/home/test3.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) Cancelling Job 1: /data/data/com.termux/files/home/test1.sh (periodic: 900000ms) (battery not low) (network: NetworkRequest [ NONE id=0, [ Capabilities: INTERNET&TRUSTED&VALIDATED&NOT_VCN_MANAGED&NOT_BANDWIDTH_CONSTRAINED Uid: 10215 UnderlyingNetworks: Null] ]) ~ $ termux-job-scheduler --cancel-all No jobs found ~ $ termux-job-scheduler -p No jobs found ~ $ termux-job-scheduler --cancel --job-id 2 No job 2 found ``` Closes #762, Closes #773
1 parent 9be2a6d commit 6fbf61a

File tree

1 file changed

+111
-55
lines changed

1 file changed

+111
-55
lines changed

app/src/main/java/com/termux/api/apis/JobSchedulerAPI.java

Lines changed: 111 additions & 55 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@
2121
import com.termux.shared.termux.TermuxConstants.TERMUX_APP.TERMUX_SERVICE;
2222

2323
import java.io.File;
24+
import java.io.PrintWriter;
2425
import java.util.ArrayList;
2526
import java.util.List;
2627
import java.util.Locale;
@@ -56,29 +57,52 @@ private static String formatJobInfo(JobInfo jobInfo) {
5657
description.add(String.format(Locale.ENGLISH, "(network: %s)", jobInfo.getRequiredNetwork().toString()));
5758
}
5859

59-
return String.format(Locale.ENGLISH, "Job %d: %s\t%s", jobInfo.getId(), path,
60+
return String.format(Locale.ENGLISH, "Job %d: %s %s", jobInfo.getId(), path,
6061
TextUtils.join(" ", description));
6162
}
6263

6364
public static void onReceive(TermuxApiReceiver apiReceiver, Context context, Intent intent) {
6465
Logger.logDebug(LOG_TAG, "onReceive");
6566

66-
final String scriptPath = intent.getStringExtra("script");
67-
68-
final int jobId = intent.getIntExtra("job_id", 0);
69-
7067
final boolean pending = intent.getBooleanExtra("pending", false);
71-
7268
final boolean cancel = intent.getBooleanExtra("cancel", false);
7369
final boolean cancelAll = intent.getBooleanExtra("cancel_all", false);
7470

75-
final int periodicMillis = intent.getIntExtra("period_ms", 0);
71+
if (pending) {
72+
ResultReturner.returnData(apiReceiver, intent, out -> {
73+
runDisplayPendingJobsAction(context, out);
74+
});
75+
} else if (cancelAll) {
76+
ResultReturner.returnData(apiReceiver, intent, out -> {
77+
runCancelAllJobsAction(context, out);
78+
});
79+
} else if (cancel) {
80+
ResultReturner.returnData(apiReceiver, intent, out -> {
81+
runCancelJobAction(context, intent, out);
82+
});
83+
} else {
84+
ResultReturner.returnData(apiReceiver, intent, out -> {
85+
runScheduleJobAction(context, intent, out);
86+
});
87+
}
88+
}
89+
90+
private static void runScheduleJobAction(Context context, Intent intent, PrintWriter out) {
91+
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
92+
93+
int jobId = intent.getIntExtra("job_id", 0);
94+
95+
Logger.logVerbose(LOG_TAG, "schedule_job: Running action for job " + jobId);
96+
97+
String scriptPath = intent.getStringExtra("script");
7698
String networkType = intent.getStringExtra("network");
77-
final boolean batteryNotLow = intent.getBooleanExtra("battery_not_low", true);
78-
final boolean charging = intent.getBooleanExtra("charging", false);
79-
final boolean persisted = intent.getBooleanExtra("persisted", false);
80-
final boolean idle = intent.getBooleanExtra("idle", false);
81-
final boolean storageNotLow = intent.getBooleanExtra("storage_not_low", false);
99+
int periodicMillis = intent.getIntExtra("period_ms", 0);
100+
boolean batteryNotLow = intent.getBooleanExtra("battery_not_low", true);
101+
boolean charging = intent.getBooleanExtra("charging", false);
102+
boolean persisted = intent.getBooleanExtra("persisted", false);
103+
boolean idle = intent.getBooleanExtra("idle", false);
104+
boolean storageNotLow = intent.getBooleanExtra("storage_not_low", false);
105+
82106

83107
int networkTypeCode;
84108
if (networkType != null) {
@@ -108,29 +132,14 @@ public static void onReceive(TermuxApiReceiver apiReceiver, Context context, Int
108132
}
109133

110134

111-
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
112-
113-
if (pending) {
114-
displayPendingJobs(apiReceiver, intent, jobScheduler);
115-
return;
116-
}
117-
if (cancelAll) {
118-
displayPendingJobs(apiReceiver, intent, jobScheduler);
119-
ResultReturner.returnData(apiReceiver, intent, out -> out.println("Cancelling all jobs"));
120-
jobScheduler.cancelAll();
121-
return;
122-
} else if (cancel) {
123-
cancelJob(apiReceiver, intent, jobScheduler, jobId);
124-
return;
125-
}
126-
127-
// Schedule new job
128135
if (scriptPath == null) {
129-
ResultReturner.returnData(apiReceiver, intent, out -> out.println("No script path given"));
136+
Logger.logErrorPrivate(LOG_TAG, "schedule_job: " + "Script path not passed");
137+
out.println("No script path given");
130138
return;
131139
}
132-
final File file = new File(scriptPath);
133-
final String fileCheckMsg;
140+
141+
File file = new File(scriptPath);
142+
String fileCheckMsg;
134143
if (!file.isFile()) {
135144
fileCheckMsg = "No such file: %s";
136145
} else if (!file.canRead()) {
@@ -142,10 +151,12 @@ public static void onReceive(TermuxApiReceiver apiReceiver, Context context, Int
142151
}
143152

144153
if (!fileCheckMsg.isEmpty()) {
145-
ResultReturner.returnData(apiReceiver, intent, out -> out.println(String.format(fileCheckMsg, scriptPath)));
154+
Logger.logErrorPrivate(LOG_TAG, "schedule_job: " + String.format(fileCheckMsg, scriptPath));
155+
out.println(String.format(fileCheckMsg, scriptPath));
146156
return;
147157
}
148158

159+
149160
PersistableBundle extras = new PersistableBundle();
150161
extras.putString(JobSchedulerService.SCRIPT_FILE_PATH, file.getAbsolutePath());
151162

@@ -169,44 +180,89 @@ public static void onReceive(TermuxApiReceiver apiReceiver, Context context, Int
169180
builder = builder.setPeriodic(periodicMillis);
170181
}
171182

172-
JobInfo job = builder.build();
183+
JobInfo jobInfo = builder.build();
184+
final int scheduleResponse = jobScheduler.schedule(jobInfo);
185+
String message = String.format(Locale.ENGLISH, "Scheduling %s - response %d", formatJobInfo(jobInfo), scheduleResponse);
186+
printMessage(out, "schedule_job", message);
187+
188+
displayPendingJob(out, jobScheduler, "schedule_job", "Pending", jobId);
189+
}
190+
191+
private static void runDisplayPendingJobsAction(Context context, PrintWriter out) {
192+
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
193+
194+
Logger.logVerbose(LOG_TAG, "display_pending_jobs: Running action");
195+
displayPendingJobs(out, jobScheduler, "display_pending_jobs", "Pending");
196+
}
197+
198+
private static void runCancelAllJobsAction(Context context, PrintWriter out) {
199+
Logger.logVerbose(LOG_TAG, "cancel_all_jobs: Running action");
200+
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
201+
int jobsCount = displayPendingJobs(out, jobScheduler, "cancel_all_jobs", "Cancelling");
202+
if (jobsCount >= 0) {
203+
Logger.logVerbose(LOG_TAG, "cancel_all_jobs: Cancelling " + jobsCount + " jobs");
204+
jobScheduler.cancelAll();
205+
}
206+
}
207+
208+
@RequiresApi(api = Build.VERSION_CODES.N)
209+
private static void runCancelJobAction(Context context, Intent intent, PrintWriter out) {
210+
JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
173211

174-
final int scheduleResponse = jobScheduler.schedule(job);
212+
if (!intent.hasExtra("job_id")) {
213+
Logger.logErrorPrivate(LOG_TAG, "cancel_job: Job id not passed");
214+
out.println("Job id not passed");
215+
return;
216+
}
175217

176-
final String message = String.format(Locale.ENGLISH, "Scheduling %s - response %d", formatJobInfo(job), scheduleResponse);
177-
Logger.logInfo(LOG_TAG, message);
178-
ResultReturner.returnData(apiReceiver, intent, out -> out.println(message));
218+
int jobId = intent.getIntExtra("job_id", 0);
219+
Logger.logVerbose(LOG_TAG, "cancel_job: Running action for job " + jobId);
220+
221+
if (displayPendingJob(out, jobScheduler, "cancel_job", "Cancelling", jobId)) {
222+
Logger.logVerbose(LOG_TAG, "cancel_job: Cancelling job " + jobId);
223+
jobScheduler.cancel(jobId);
224+
}
225+
}
179226

180227

181-
displayPendingJobs(apiReceiver, intent, jobScheduler);
182228

229+
private static boolean displayPendingJob(PrintWriter out, JobScheduler jobScheduler,
230+
String actionTag, String actionLabel, int jobId) {
231+
JobInfo jobInfo = jobScheduler.getPendingJob(jobId);
232+
if (jobInfo == null) {
233+
printMessage(out, actionTag, String.format(Locale.ENGLISH, "No job %d found", jobId));
234+
return false;
235+
}
236+
237+
printMessage(out, actionTag, String.format(Locale.ENGLISH, actionLabel + " %s", formatJobInfo(jobInfo)));
238+
return true;
183239
}
184240

185-
private static void displayPendingJobs(TermuxApiReceiver apiReceiver, Intent intent, JobScheduler jobScheduler) {
186-
// Display pending jobs
187-
final List<JobInfo> jobs = jobScheduler.getAllPendingJobs();
241+
242+
private static int displayPendingJobs(PrintWriter out, JobScheduler jobScheduler, String actionTag, String actionLabel) {
243+
List<JobInfo> jobs = jobScheduler.getAllPendingJobs();
188244
if (jobs.isEmpty()) {
189-
ResultReturner.returnData(apiReceiver, intent, out -> out.println("No pending jobs"));
190-
return;
245+
printMessage(out, actionTag, "No jobs found");
246+
return 0;
191247
}
192248

193249
StringBuilder stringBuilder = new StringBuilder();
250+
boolean jobAdded = false;
194251
for (JobInfo job : jobs) {
195-
stringBuilder.append(String.format(Locale.ENGLISH, "Pending %s\n", formatJobInfo(job)));
252+
if (jobAdded) stringBuilder.append("\n");
253+
stringBuilder.append(String.format(Locale.ENGLISH, actionLabel + " %s", formatJobInfo(job)));
254+
jobAdded = true;
196255
}
197-
ResultReturner.returnData(apiReceiver, intent, out -> out.println(stringBuilder.toString()));
256+
printMessage(out, actionTag, stringBuilder.toString());
257+
258+
return jobs.size();
198259
}
199260

200-
@RequiresApi(api = Build.VERSION_CODES.N)
201-
private static void cancelJob(TermuxApiReceiver apiReceiver, Intent intent, JobScheduler jobScheduler, int jobId) {
202-
final JobInfo jobInfo = jobScheduler.getPendingJob(jobId);
203-
if (jobInfo == null) {
204-
ResultReturner.returnData(apiReceiver, intent, out -> out.println(String.format(Locale.ENGLISH, "No job %d found", jobId)));
205-
return;
206-
}
207-
ResultReturner.returnData(apiReceiver, intent, out -> out.println(String.format(Locale.ENGLISH, "Cancelling %s", formatJobInfo(jobInfo))));
208-
jobScheduler.cancel(jobId);
209261

262+
263+
private static void printMessage(PrintWriter out, String actionTag, String message) {
264+
Logger.logVerbose(LOG_TAG, actionTag + ": " + message);
265+
out.println(message);
210266
}
211267

212268

0 commit comments

Comments
 (0)