Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add CronAPI #657

Open
wants to merge 12 commits into
base: master
Choose a base branch
from
10 changes: 10 additions & 0 deletions app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,8 @@ android {
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8

coreLibraryDesugaringEnabled true
}

applicationVariants.all { variant ->
Expand All @@ -64,9 +66,17 @@ android {
}

dependencies {
coreLibraryDesugaring 'com.android.tools:desugar_jdk_libs:1.2.3'

implementation 'com.google.android.material:material:1.4.0'
implementation 'androidx.biometric:biometric:1.2.0-alpha03'
implementation "androidx.work:work-runtime:2.6.0"
implementation "androidx.concurrent:concurrent-futures:1.1.0"
implementation 'androidx.media:media:1.4.3'
implementation 'com.cronutils:cron-utils:9.2.0'
implementation 'com.google.code.gson:gson:2.10.1'
implementation "com.google.guava:guava:24.1-android"
implementation 'com.google.guava:listenablefuture:9999.0-empty-to-avoid-conflict-with-guava'

implementation 'com.termux.termux-app:termux-shared:8c1749ef96'
// Use if below libraries are published locally by termux-app with `./gradlew publishReleasePublicationToMavenLocal` and used with `mavenLocal()`.
Expand Down
23 changes: 22 additions & 1 deletion app/src/main/AndroidManifest.xml
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,28 @@
android:grantUriPermissions="true"
android:exported="true" />


<provider
android:name="androidx.startup.InitializationProvider"
android:authorities="${applicationId}.androidx-startup"
android:exported="false"
tools:node="merge">
<meta-data
android:name="androidx.work.WorkManagerInitializer"
android:value="androidx.startup"
tools:node="remove" />
</provider>


<receiver android:name=".cron.CronReceiver"
android:exported="false">
</receiver>

<receiver android:name=".cron.CronBootReceiver"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>

<receiver android:name=".TermuxApiReceiver"
android:exported="false" />
Expand Down
17 changes: 14 additions & 3 deletions app/src/main/java/com/termux/api/TermuxAPIApplication.java
Original file line number Diff line number Diff line change
Expand Up @@ -2,16 +2,19 @@

import android.app.Application;
import android.content.Context;

import android.util.Log;
import androidx.annotation.NonNull;
import androidx.work.Configuration;
import com.termux.api.util.ResultReturner;
import com.termux.shared.logger.Logger;
import com.termux.shared.termux.TermuxConstants;
import com.termux.shared.termux.crash.TermuxCrashUtils;
import com.termux.shared.termux.settings.preferences.TermuxAPIAppSharedPreferences;


public class TermuxAPIApplication extends Application {
public class TermuxAPIApplication extends Application implements Configuration.Provider {

@Override
public void onCreate() {
super.onCreate();

Expand All @@ -28,12 +31,20 @@ public void onCreate() {
}

public static void setLogConfig(Context context, boolean commitToFile) {
Logger.setDefaultLogTag(TermuxConstants.TERMUX_API_APP_NAME.replaceAll(":", ""));
Logger.setDefaultLogTag(TermuxConstants.TERMUX_API_APP_NAME.replace(":", ""));

// Load the log level from shared preferences and set it to the {@link Logger.CURRENT_LOG_LEVEL}
TermuxAPIAppSharedPreferences preferences = TermuxAPIAppSharedPreferences.build(context);
if (preferences == null) return;
preferences.setLogLevel(null, preferences.getLogLevel(true), commitToFile);
}

@NonNull
@Override
public Configuration getWorkManagerConfiguration() {
return new Configuration.Builder()
.setJobSchedulerJobIdRange(10_000, 11_000)
.setMinimumLoggingLevel(Log.INFO)
.build();
}
}
6 changes: 5 additions & 1 deletion app/src/main/java/com/termux/api/TermuxAPIConstants.java
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
package com.termux.api;

import com.termux.shared.termux.TermuxConstants;
import static com.termux.shared.termux.TermuxConstants.TERMUX_API_PACKAGE_NAME;
import static com.termux.shared.termux.TermuxConstants.TERMUX_PACKAGE_NAME;

Expand All @@ -14,4 +13,9 @@ public class TermuxAPIConstants {
/** The Uri authority for Termux:API app file shares */
public static final String TERMUX_API_FILE_SHARE_URI_AUTHORITY = TERMUX_PACKAGE_NAME + ".sharedfiles"; // Default: "com.termux.sharedfiles"

public static final String TERMUX_API_CRON_ALARM_SCHEME = "com.termux.api.cron.alarm";

public static final String TERMUX_API_CRON_CONSTRAINT_SCHEME = "com.termux.api.cron.constraint";

public static final String TERMUX_API_CRON_EXECUTION_RESULT_SCHEME = "com.termux.api.cron.exec";
}
4 changes: 4 additions & 0 deletions app/src/main/java/com/termux/api/TermuxApiReceiver.java
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
import android.provider.Settings;
import android.widget.Toast;

import com.termux.api.apis.CronAPI;
import com.termux.api.apis.AudioAPI;
import com.termux.api.apis.BatteryStatusAPI;
import com.termux.api.apis.BrightnessAPI;
Expand Down Expand Up @@ -84,6 +85,9 @@ private void doWork(Context context, Intent intent) {
}

switch (apiMethod) {
case "Cron":
CronAPI.onReceive(this, context, intent);
break;
case "AudioInfo":
AudioAPI.onReceive(this, context, intent);
break;
Expand Down
103 changes: 103 additions & 0 deletions app/src/main/java/com/termux/api/apis/CronAPI.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,103 @@
package com.termux.api.apis;

import android.content.Context;
import android.content.Intent;
import com.termux.api.TermuxApiReceiver;
import com.termux.api.cron.CronTab;
import com.termux.api.cron.CronEntry;
import com.termux.api.cron.CronScheduler;
import com.termux.api.util.ResultReturner;
import com.termux.shared.logger.Logger;

import java.util.List;
import java.util.Locale;

public class CronAPI {

public static final String LOG_TAG = "CronAPI";

private CronAPI() {
/* static class */
}

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

if (intent.getBooleanExtra("list", false)) {
handleList(apiReceiver, intent);
} else if (intent.getIntExtra("info", -1) != -1) {
handleInfo(apiReceiver, intent, intent.getIntExtra("info", -1));
} else if (intent.getBooleanExtra("reschedule", false)) {
handleRescheduleAll(apiReceiver, context, intent);
} else if (intent.getBooleanExtra("delete_all", false)) {
handleDeleteAll(apiReceiver, context, intent);
} else if (intent.getIntExtra("delete", -1) != -1) {
handleDelete(apiReceiver, context, intent, intent.getIntExtra("delete", -1));
} else {
handleAddJob(apiReceiver, context, intent);
}
}

private static void handleAddJob(TermuxApiReceiver apiReceiver, Context context, Intent intent) {
try {
CronEntry entry = CronTab.add(intent);
CronScheduler.scheduleAlarmForJob(context, entry);
ResultReturner.returnData(apiReceiver, intent, out -> out.println(entry.describe()));
} catch (Exception e) {
String message = getExceptionMessage(e);
Logger.logError(LOG_TAG, message);
Logger.logStackTrace(LOG_TAG, e);
ResultReturner.returnData(apiReceiver, intent, out -> out.println(message));
}
}

private static void handleList(TermuxApiReceiver apiReceiver, Intent intent) {
ResultReturner.returnData(apiReceiver, intent, out -> out.println(CronTab.print()));
}

private static void handleInfo(TermuxApiReceiver apiReceiver, Intent intent, int id) {
CronEntry entry = CronTab.getById(id);
if (entry != null) {
ResultReturner.returnData(apiReceiver, intent, out -> out.println(entry.describe()));
} else {
ResultReturner.returnData(apiReceiver, intent, out ->
out.println(String.format(Locale.getDefault(), "Cron job with id %d not found", id)));
}
}

private static void handleRescheduleAll(TermuxApiReceiver apiReceiver, Context context, Intent intent) {
for (CronEntry entry : CronTab.getAll()) {
CronScheduler.scheduleAlarmForJob(context, entry);
}
ResultReturner.returnData(apiReceiver, intent, out -> out.println("All cron jobs have been rescheduled"));
}

private static void handleDeleteAll(TermuxApiReceiver apiReceiver, Context context, Intent intent) {
List<CronEntry> entries = CronTab.clear();
for (CronEntry entry : entries) {
CronScheduler.cancelAlarmForJob(context, entry);
}
ResultReturner.returnData(apiReceiver, intent, out -> out.println("All cron jobs deleted"));
}

private static void handleDelete(TermuxApiReceiver apiReceiver, Context context, Intent intent, int id) {
CronEntry entry = CronTab.delete(id);
if (entry != null) {
CronScheduler.cancelAlarmForJob(context, entry);
ResultReturner.returnData(apiReceiver, intent, out ->
out.println(String.format(Locale.getDefault(), "Deleted cron job with id %d", id)));
} else {
ResultReturner.returnData(apiReceiver, intent, out ->
out.println(String.format(Locale.getDefault(), "Cron job with id %d not found?", id)));
}
}

private static String getExceptionMessage(Exception e) {
String message = e.getMessage();
if (message != null) {
return message;
} else {
return String.format(Locale.getDefault(), "%s without message", e.getClass().getSimpleName());
}
}
}
2 changes: 2 additions & 0 deletions app/src/main/java/com/termux/api/apis/JobSchedulerAPI.java
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
package com.termux.api.apis;

import android.annotation.SuppressLint;
import android.app.job.JobInfo;
import android.app.job.JobParameters;
import android.app.job.JobScheduler;
Expand Down Expand Up @@ -208,6 +209,7 @@ private static void cancelJob(TermuxApiReceiver apiReceiver, Intent intent, JobS



@SuppressLint("SpecifyJobSchedulerIdRange")
public static class JobSchedulerService extends JobService {

public static final String SCRIPT_FILE_PATH = TermuxConstants.TERMUX_API_PACKAGE_NAME + ".jobscheduler_script_path";
Expand Down
24 changes: 24 additions & 0 deletions app/src/main/java/com/termux/api/cron/CronBootReceiver.java
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
package com.termux.api.cron;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import com.termux.shared.data.IntentUtils;
import com.termux.shared.logger.Logger;

public class CronBootReceiver extends BroadcastReceiver {

private static final String LOG_TAG = "CronBootReceiver";

@Override
public void onReceive(Context context, Intent intent) {
if (!intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {
Logger.logDebug(LOG_TAG, "Unknown intent Received:\n" + IntentUtils.getIntentString(intent));
return;
}

for (CronEntry entry : CronTab.getAll()) {
CronScheduler.scheduleAlarmForJob(context, entry);
}
}
}
Loading