这是indexloc提供的服务,不要输入任何密码
Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -86,6 +86,9 @@
<action android:name="android.service.notification.NotificationListenerService" />
</intent-filter>
</service>
<service
android:name=".SchedulerJobService"
android:permission="android.permission.BIND_JOB_SERVICE" />
</application>

</manifest>
137 changes: 137 additions & 0 deletions app/src/main/java/com/termux/api/JobSchedulerAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
package com.termux.api;

import android.app.job.JobInfo;
import android.app.job.JobScheduler;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.media.AudioManager;
import android.os.PersistableBundle;
import android.os.Vibrator;
import android.util.Log;

import com.termux.api.util.ResultReturner;

import java.io.File;
import java.io.PrintWriter;

public class JobSchedulerAPI {

private static final String LOG_TAG = "JobSchedulerAPI";


static void onReceive(TermuxApiReceiver apiReceiver, Context context, Intent intent) {

final String scriptPath = intent.getStringExtra("script");

final int periodicMillis = intent.getIntExtra("period_ms", 0);
final int jobId = intent.getIntExtra("job_id", 0);
final String networkType = intent.getStringExtra("network");
final boolean batteryNotLow = intent.getBooleanExtra("battery_not_low", true);
final boolean charging = intent.getBooleanExtra("charging", false);
final boolean idle = intent.getBooleanExtra("idle", false);
final boolean storageNotLow = intent.getBooleanExtra("storage_not_low", false);

int networkTypeCode = JobInfo.NETWORK_TYPE_NONE;
if (networkType != null) {
switch (networkType) {
case "any":
networkTypeCode = JobInfo.NETWORK_TYPE_ANY;
break;
case "unmetered":
networkTypeCode = JobInfo.NETWORK_TYPE_UNMETERED;
break;
case "cellular":
networkTypeCode = JobInfo.NETWORK_TYPE_CELLULAR;
break;
case "not_roaming":
networkTypeCode = JobInfo.NETWORK_TYPE_NOT_ROAMING;
break;
default:
case "none":
networkTypeCode = JobInfo.NETWORK_TYPE_NONE;
break;
}
}
if (scriptPath == null) {
ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultWriter() {
@Override
public void writeResult(PrintWriter out) {
out.println("No script path given");
}
});
return;
}
final File file = new File(scriptPath);
final String fileCheckMsg;
if (!file.isFile()) {
fileCheckMsg = "No such file: %s";
} else if (!file.canRead()) {
fileCheckMsg = "Cannot read file: %s";
} else if (!file.canExecute()) {
fileCheckMsg = "Cannot execute file: %s";
} else {
fileCheckMsg = "";
}

if (!fileCheckMsg.isEmpty()) {
ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultWriter() {
@Override
public void writeResult(PrintWriter out) {
out.println(String.format(fileCheckMsg, scriptPath));
}
});
return;
}

PersistableBundle extras = new PersistableBundle();
extras.putString(SchedulerJobService.SCRIPT_FILE_PATH, file.getAbsolutePath());


JobScheduler jobScheduler = (JobScheduler) context.getSystemService(Context.JOB_SCHEDULER_SERVICE);
// Display pending jobs
for (JobInfo job : jobScheduler.getAllPendingJobs()) {
final JobInfo j = job;
ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultWriter() {
@Override
public void writeResult(PrintWriter out) {
out.println(String.format("Pending job %d %s", j.getId(), j.toString()));
}
});
}

ComponentName serviceComponent = new ComponentName(context, SchedulerJobService.class);
JobInfo.Builder builder = null;
;
builder = new JobInfo.Builder(jobId, serviceComponent)
.setExtras(extras)
.setRequiredNetworkType(networkTypeCode)
.setRequiresCharging(charging)
.setRequiresDeviceIdle(idle);

if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.O) {
builder = builder.setRequiresBatteryNotLow(batteryNotLow);
builder = builder.setRequiresStorageNotLow(storageNotLow);
}

if (periodicMillis > 0) {
builder = builder.setPeriodic(periodicMillis);
}

JobInfo job = builder.build();

final int scheduleResponse = jobScheduler.schedule(job);

Log.i(LOG_TAG, String.format("Scheduled job %d to call %s every %d ms - response %d",
jobId, scriptPath, periodicMillis, scheduleResponse));
ResultReturner.returnData(apiReceiver, intent, new ResultReturner.ResultWriter() {
@Override
public void writeResult(PrintWriter out) {
out.println(String.format("Scheduled job %d to call %s every %d ms - response %d",
jobId, scriptPath, periodicMillis, scheduleResponse));
}
});

}

}
50 changes: 50 additions & 0 deletions app/src/main/java/com/termux/api/SchedulerJobService.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,50 @@
package com.termux.api;
import android.app.job.JobParameters;
import android.app.job.JobService;
import android.content.Context;
import android.content.Intent;
import android.net.Uri;
import android.os.Build;
import android.os.PersistableBundle;
import android.util.Log;

public class SchedulerJobService extends JobService {

private static final String LOG_TAG = "TermuxAPISchedulerJob";
public static final String SCRIPT_FILE_PATH = "com.termux.api.jobscheduler_script_path";

// Constants from TermuxService.
private static final String TERMUX_SERVICE = "com.termux.app.TermuxService";
private static final String ACTION_EXECUTE = "com.termux.service_execute";
private static final String EXTRA_EXECUTE_IN_BACKGROUND = "com.termux.execute.background";

@Override
public boolean onStartJob(JobParameters params) {

Log.i(LOG_TAG, "Starting job " + params.toString());
PersistableBundle extras = params.getExtras();
String filePath = extras.getString(SCRIPT_FILE_PATH);

Uri scriptUri = new Uri.Builder().scheme("com.termux.file").path(filePath).build();
Intent executeIntent = new Intent(ACTION_EXECUTE, scriptUri);
executeIntent.setClassName("com.termux", TERMUX_SERVICE);
executeIntent.putExtra(EXTRA_EXECUTE_IN_BACKGROUND, true);

Context context = getApplicationContext();
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
// https://developer.android.com/about/versions/oreo/background.html
context.startForegroundService(executeIntent);
} else {
context.startService(executeIntent);
}

Log.i(LOG_TAG, "Started job " + params.toString());
return false;
}

@Override
public boolean onStopJob(JobParameters params) {
Log.i(LOG_TAG, "Stopped job " + params.toString());
return false;
}
}
3 changes: 3 additions & 0 deletions app/src/main/java/com/termux/api/TermuxApiReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -83,6 +83,9 @@ public void onReceive(Context context, Intent intent) {
InfraredAPI.onReceiveTransmit(this, context, intent);
}
break;
case "JobScheduler":
JobSchedulerAPI.onReceive(this, context, intent);
break;
case "Keystore":
KeystoreAPI.onReceive(this, intent);
break;
Expand Down