Skip to main content

schedule()

Schedules a task to run repeatedly based on a cron expression. Perfect for recurring automations like posting content, checking notifications, or performing maintenance.
task
string
required
JavaScript code to execute. Can be a single statement or a function call.
cronExpression
string
required
Cron expression defining when the task runs. Format: second minute hour day month dayOfWeek
return
void
The task is registered and will run according to the schedule.

Basic Usage

// Run every 5 minutes
Android.schedule(
  "Android.speakText('5 minute check')",
  "0 */5 * * * *"
);

// Run every hour
Android.schedule(
  "Android.speakText('Hourly update')",
  "0 0 * * * *"
);

// Run every day at 9 AM
Android.schedule(
  "Android.speakText('Good morning')",
  "0 0 9 * * *"
);

Cron Expression Format

Cron expressions use 6 fields:
┌───────────── second (0-59)
│ ┌───────────── minute (0-59)
│ │ ┌───────────── hour (0-23)
│ │ │ ┌───────────── day of month (1-31)
│ │ │ │ ┌───────────── month (1-12)
│ │ │ │ │ ┌───────────── day of week (0-7, 0=Sunday)
│ │ │ │ │ │
* * * * * *

Common Cron Patterns

// Every 1 minute
"0 */1 * * * *"

// Every 5 minutes
"0 */5 * * * *"

// Every 15 minutes
"0 */15 * * * *"

// Every 30 minutes
"0 */30 * * * *"
// Every hour
"0 0 * * * *"

// Every 2 hours
"0 0 */2 * * *"

// Every 6 hours
"0 0 */6 * * *"

// Every 12 hours
"0 0 */12 * * *"
// Every day at 9:00 AM
"0 0 9 * * *"

// Every day at 2:30 PM
"0 30 14 * * *"

// Weekdays at 8:00 AM
"0 0 8 * * 1-5"

// Weekends at 10:00 AM
"0 0 10 * * 0,6"
// Every 30 seconds
"*/30 * * * * *"

// First day of every month at midnight
"0 0 0 1 * *"

// Every Monday at 9:00 AM
"0 0 9 * * 1"

// Every weekday at 6:00 PM
"0 0 18 * * 1-5"

Practical Examples

// Post to Instagram every 2 hours
Android.schedule(
  "postToInstagram()",
  "0 0 */2 * * *"
);

function postToInstagram() {
  Android.speakText("Starting Instagram post");
  // ... posting logic ...
  Android.speakText("Post complete");
}

Implementation Details

Source Location

MainActivity.kt:5488
@JavascriptInterface
fun schedule(task: String, cronExpression: String) {
    try {
        val taskId = this@MainActivity.addCronTask(task, cronExpression)
        val interval = this@MainActivity.getIntervalFromCron(cronExpression)
        
        Log.d("AndroidJSInterface", "Scheduled task: $task with cron: $cronExpression (ID: $taskId), interval: ${interval}ms")
        
        if (interval != null) {
            val seconds = interval / 1000
            val minutes = seconds / 60
            val hours = minutes / 60
            
            val timeDescription = when {
                hours > 0 -> "$hours hours"
                minutes > 0 -> "$minutes minutes"
                else -> "$seconds seconds"
            }
            
            speakText("Scheduled task: $task to run every $timeDescription")
        } else {
            speakText("Scheduled task: $task with custom timing")
        }
        
        runOnUiThread { updateUI() }
    } catch (e: Exception) {
        Log.e("AndroidJSInterface", "Error scheduling task: ${e.message}")
        speakText("Error scheduling task")
    }
}

Task Storage

Scheduled tasks are:
  • Persisted to SharedPreferences
  • Survive app restarts
  • Checked by a background cron checker thread
  • Assigned unique IDs for management
Tasks execute on a scheduled executor service with 2 threads. Long-running tasks should be avoided.

clearSchedule()

Removes all scheduled tasks. Useful for resetting automation state or clearing old schedules.
return
void
All scheduled tasks are cleared and removed from storage.

Usage

// Clear all scheduled tasks
Android.clearSchedule();

Implementation

MainActivity.kt:5525
@JavascriptInterface
fun clearSchedule() {
    try {
        val taskCount = this@MainActivity.cronTasks.size
        this@MainActivity.cronTasks.clear()
        this@MainActivity.saveCronTasks()
        speakText("Cleared $taskCount scheduled tasks")
        Log.d("AndroidJSInterface", "Cleared all scheduled tasks")
        runOnUiThread { updateUI() }
    } catch (e: Exception) {
        Log.e("AndroidJSInterface", "Error clearing schedule: ${e.message}")
        speakText("Error clearing scheduled tasks")
    }
}

Complete Examples

Instagram Posting Bot

// Schedule posts every 3 hours
Android.schedule(
  "autoPostInstagram()",
  "0 0 */3 * * *"
);

function autoPostInstagram() {
  Android.speakText("Starting Instagram automation");
  
  // Open Instagram
  Android.simulateClick(200, 1800);
  Android.delay(3000);
  
  // Click new post
  Android.simulateClick(400, 1800);
  Android.delay(2000);
  
  // Select media
  Android.simulateClick(200, 500);
  Android.delay(1000);
  
  // Next
  Android.clickNodesByContentDescription("Next");
  Android.delay(1500);
  
  // Next again
  Android.clickNodesByContentDescription("Next");
  Android.delay(1500);
  
  // Add caption
  Android.simulateTypeInFirstEditableField("Auto-posted content");
  Android.delay(1000);
  
  // Share
  Android.clickNodesByContentDescription("Share");
  Android.delay(3000);
  
  Android.speakText("Instagram post complete");
}

Email Digest

// Send daily summary at 6 PM
Android.schedule(
  "sendDailySummary()",
  "0 0 18 * * *"
);

function sendDailySummary() {
  const stats = {
    postsCreated: 5,
    messagesChecked: 23,
    tasksCompleted: 8
  };
  
  const message = `Daily Summary:
    Posts Created: ${stats.postsCreated}
    Messages Checked: ${stats.messagesChecked}
    Tasks Completed: ${stats.tasksCompleted}`;
  
  Android.sendAgentEmail(
    "user@example.com",
    "PhoneClaw Daily Summary",
    message
  );
  
  Android.speakText("Daily summary sent");
}

Status Checker

// Check app status every 30 minutes
Android.schedule(
  "checkAppStatus()",
  "0 */30 * * * *"
);

function checkAppStatus() {
  if (Android.isTextPresentOnScreen("Error")) {
    Android.speakText("Error detected, restarting app");
    // Restart logic
  } else if (Android.isTextPresentOnScreen("Login")) {
    Android.speakText("Logged out, logging back in");
    // Re-login logic
  } else {
    Android.speakText("App status normal");
  }
}

Best Practices

Scheduled tasks should call functions rather than containing complex inline code.
// Good
Android.schedule("performTask()", "0 */5 * * * *");

// Avoid
Android.schedule(
  "Android.speakText('test'); Android.delay(1000); Android.simulateClick(100, 200); ...",
  "0 */5 * * * *"
);
Errors in scheduled tasks should be caught and handled gracefully.
function scheduledTask() {
  try {
    // Task logic
  } catch (e) {
    Android.speakText("Scheduled task failed: " + e.message);
    Android.sendAgentEmail(
      "admin@example.com",
      "Task Failed",
      e.message
    );
  }
}
Very frequent tasks (every second) can drain battery and CPU.
// Avoid
"* * * * * *" // Every second

// Better
"0 */5 * * * *" // Every 5 minutes
Prevent duplicate tasks by clearing before scheduling.
Android.clearSchedule();
Android.schedule("myTask()", "0 */10 * * * *");

Viewing Scheduled Tasks

Scheduled tasks appear in the PhoneClaw UI:
  1. Open the PhoneClaw app
  2. Navigate to the Scheduled Tasks tab
  3. View all active tasks with their cron expressions
  4. See last execution time and next scheduled time

Limitations

  • Maximum of 100 concurrent scheduled tasks
  • Tasks must complete before the next scheduled execution
  • Long-running tasks (>5 minutes) may be terminated
  • Schedule persists but execution pauses if device is off
  • Requires app to remain running in background