Developing Programs with Task Scheduling Capabilities

Symbian Developers and device creators can use the task scheduler APIs to develop programs with scheduling capabilities. Programs may need task scheduling capabilities to support scheduling options that may be required for a phone user, another program or a system server.

For example, a phone user can use the alarm option of a clock application to schedule an alarm to be triggered every day at 5:00 A.M.

Steps

  1. Connect the client to the task scheduler server using RScheduler::Connect().
    RScheduler iScheduler;
    User::LeaveIfError(iScheduler.Connect());
  2. Register the client with the task scheduler server using RScheduler::Register() by passing the following parameters:
    1. Name and full path of the executable to be used to execute the scheduled task. For more information about creating this executable, see the taskexecutor.cpp topic in theTaskSchedulerExample: Using Task Scheduler for Creating and Executing Tasks section.
    2. Priority of the task to be executed, relative to other clients. If two clients have tasks to execute at the same time, the one with the higher priority is executed first.
    The following code snippet illustrates how to register a client with the task scheduler server:
    RScheduler iScheduler;
    TFileName fileName;
    ...
    
    //A priority value
    const TInt priority = 3;
    
    ...
    
    User::LeaveIfError(iScheduler.Register(filename, priority));

    Note: Task scheduler supports only the execution of Symbian platform executables. The

    aFileName parameter can include a path but must not include a file extension.
    For example, a fileName can be minimalTaskHandler. Note that in the presence of platform security all EXEs are located in the \sys\bin folder and as a consequence of this, the path of an EXE (only the drive letter) is not needed.
  3. Create the support for different types of schedules that you want to provide using the following functions of RScheduler:
    1. IMPORT_C TInt CreatePersistentSchedule(TSchedulerItemRef& aRef, const CArrayFixFlat<TScheduleEntryInfo2>& aEntryList):Creates a persistent time-based schedule without tasks. The following code snippet illustrates how to create a persistent time-based schedule scheduled to start on January 1st, 2010 at 08:00 A.M., runs every one hour and is valid for eight hours.
      ...
      
      TSchedulerItemRef& aRef;
      
      //Array to hold the schedule entries
      CArrayFixFlat<TScheduleEntryInfo2>* cSchEntryInfoArray;    
      cSchEntryInfoArray = new CArrayFixFlat<TScheduleEntryInfo2>(1);
      
      CleanupStack::PushL(cSchEntryInfoArray);
      
      // Create an hourly schedule
      TScheduleEntryInfo2 entry1;
      
      //Sets the date and time for the schedule as Jan 1st, 2010, 08:00 am
      TDateTime datetime2(2010, EJanuary, 1, 8, 0, 0, 0); 
      TTsTime time2(datetime2, ETrue);
      
      //Set the first instance when the entry will cause the execution of tasks. 
      entry1.SetStartTime(time2);
      
      // Set the interval between execution of tasks
      // Here the interval is 2 hours because the interval type is hourly.
      const TInt interval = 2;
      entry1.SetInterval(interval);
      
      // Set the type of interval used between due times for the scheduled entry
      entry1.SetIntervalType(TIntervalType(EHourly));
          
      // Set the period for which the entry is valid. After 8 hours the 
      // tasks associated with the entry will not be eligible for execution.
      const TInt eightHours = 480; // in minutes 
      entry1.SetValidityPeriod(TTimeIntervalMinutes(eightHours));
          
      cSchEntryInfoArray->AppendL(entry1);
      
      //create the time-based persistent schedule
      User::LeaveIfError(iScheduler.CreatePersistentSchedule(aRef, *cSchEntryInfoArray));
      
      CleanupStack::PopAndDestroy(cSchEntryInfoArray);
      ...
    2. IMPORT_C TInt CreatePersistentSchedule(TSchedulerItemRef& aRef, const CArrayFixFlat<TTaskSchedulerCondition>& aConditions, const TTsTime& aDefaultRunTime): Creates a persistent condition-based schedule without tasks. The following code snippet illustrates how to create a persistent condition-based schedule that is triggered when both condtion1 and condtion2 are satisfied. By default, the schedule is set to start on December 10th, 2009 at 09:00 A.M., if the condition set is not met.
      ...
      
      TSchedulerItemRef& aRef;
      
      //Array to hold the schedule conditions
      CArrayFixFlat<TTaskSchedulerCondition>* cTaskScheCondArray;
      
      //Condition list to hold a set of conditions
      CSchConditionArray conditionList = new (ELeave) CSchConditionArray(2);
      CleanupStack::PushL(conditionList);
      
      //set the first condition
      TTaskSchedulerCondition condition1;
      
      //UID of the publish and subscribe category for condition1
      const TUid KPubSubsPersistCondCategUid1 = TUid::Uid(0x102F7784);
      
      //Key of the publish and subscribe category for condition2
      const TInt KPubSubsPersistCondKey1 = 1;
      
      condition1.iCategory = KPubSubsPersistCondCategUid1;
      condition1.iKey        = KPubSubsPersistCondKey1;
      condition1.iState    = 10;
      condition1.iType    = TTaskSchedulerCondition::EEquals;
      conditionList->AppendL(condition1);
      
      //set the second condition
      TTaskSchedulerCondition condition2;
      
      //UID of the publish and subscribe category for condition2
      const TUid KPubSubsPersistCondCategUid2 = TUid::Uid(0x103F7784);
      
      //Key of the publish and subscribe category for condition2
      const TInt KPubSubsPersistCondKey2 = 1;
      
      condition2.iCategory = KPubSubsPersistCondCategUid2;
      condition2.iKey        = KPubSubsPersistCondKey2;
      condition2.iState    = 20;
      condition2.iType    = TTaskSchedulerCondition::ENotEquals;
      conditionList->AppendL(condition2);
      
      //Set the date and time for the schedule as Dec 10th, 2009, 09:00 am
      TDateTime datetime2(2009, EDecember, 10, 9, 0, 0, 0); 
      TTsTime time2(datetime2, EFalse);
      
      //create the condition-based persistent schedule
      iScheduler.CreatePersistentSchedule(aRef, *conditionList, time2);
      
      CleanupStack::PopAndDestroy(); // conditionList
    3. IMPORT_C TInt ScheduleTask(TTaskInfo& aTaskInfo, HBufC& aTaskData, TSchedulerItemRef& aRef, const CArrayFixFlat<TScheduleEntryInfo2>& aEntryList):Creates a transient time-based schedule and adds a task to it. The following code snippet illustrates how to create a transient time-based schedule and associate a task to it. It starts at a specific time, runs every one hour and is valid for two hours.
      ...
      
      TSchedulerItemRef ref;
      
      // Array that holds the schedule entries
      CArrayFixFlat<TScheduleEntryInfo2>* cSchEntryInfoArray;
      cSchEntryInfoArray = new CArrayFixFlat<TScheduleEntryInfo2>(1);
      
      CleanupStack::PushL(cSchEntryInfoArray);
      
      // Create a schedule entry
      TScheduleEntryInfo2 entry;
      
      TTime now;
      
      //    Set the date and time of this TTime to the universal time.
      now.UniversalTime();
          
      // Assign an offset of 15 seconds. 
      TInt offset = 15;
      now += TTimeIntervalSeconds(offset);
      
      // Constructs a TTsTime with a TTime object.
      // ETrue indicates that TTsTime is UTC based time
      TTsTime time(now, ETrue);
          
      // Set the above time as the first time at which
      // the entry will cause execution of tasks. 
      entry.SetStartTime(time);
          
      // Set the type of interval used between due times for scheduled entry
      entry.SetIntervalType(TIntervalType(EHourly));
          
      // Set the period for which the entry is valid. 
      // After 2 hours the tasks associated with the entry will not be eligible for execution 
      TInt validity = 120;
      entry.SetValidityPeriod(TTimeIntervalMinutes(validity));
          
      // Set the interval between execution of tasks
      // Here the interval is 1 hour because the interval type is hourly.
      entry.SetInterval(1);
      
      //Add the schedule entry to the array
      cSchEntryInfoArray->AppendL(entry);
          
      // Create a transient task to be scheduled
      TTaskInfo taskInfo;
      
      // Task id
      const TInt tId = 0;
      taskInfo.iTaskId = tId;
          
      // The task repeats just once
      const TInt numberOfRepeats = 1;
      taskInfo.iRepeat = numberOfRepeats;
          
      // Task priority set by the client. 
      // Where a client has two tasks with different priorities, 
      // the task with the higher priority will be executed first.
      const TInt priority = 2; 
      taskInfo.iPriority = priority;
          
      _LIT(KScheduleType," transient schedule");
      const TDesC* transient = &KScheduleType;
      HBufC* data = transient->AllocLC();
              
      // Create the transient time-based schedule 
      User::LeaveIfError(iScheduler.ScheduleTask(taskInfo, *data, ref, *cSchEntryInfoArray));
      
      ...
      Important: The task scheduler does not notify a client if a scheduled task fails to execute successfully. Clients can however use the notification mechanism of the Log Engine to get some notification and information of the error condition that caused the task to fail.
      • Errors can occur when the task scheduler prepares to create and run a task process. The most likely error is an out of memory error. The task scheduler logs the error to the system log with type KLogTaskSchedulerEventTypeUid. The task or schedule is not retried.

      • If the task process is created successfully, but it exits with an error, the task scheduler logs the process exit reason to the system log, also with type KLogTaskSchedulerEventTypeUid.

    4. IMPORT_C TInt ScheduleTask(TTaskInfo& aTaskInfo, HBufC& aTaskData, TSchedulerItemRef& aRef, const CArrayFixFlat<TTaskSchedulerCondition>& aConditions, const TTsTime& aDefaultRunTime): Creates a transient condition-based schedule and adds a task to it. The following code snippet illustrates how to create a transient condition-based schedule and associate a task to it. The schedule is triggered when condition1 is met. By default, the schedule is set to start on December 10th, 2009 at 09:00 A.M., if the condition set is not met.
      ...
      
      TSchedulerItemRef ref2;
      
      //Array that holds the conditions
      CArrayFixFlat<TTaskSchedulerCondition>* CSchConditionArray;
      CSchConditionArray conditionList = new (ELeave) CSchConditionArray(1);
      
      CleanupStack::PushL(conditionList);
      
      //set the condition
      TTaskSchedulerCondition condition1;
      
      //UID of the publish and subscribe category for condition1
      const TUid KPubSubsTransCondCategUid1 = TUid::Uid(0x102F7785);
      
      //Key of the publish and subscribe category for condition1
      const TInt KPubSubsTransCondKey1 = 1;
      
      condition1.iCategory = KPubSubsTransCondCategUid1;
      condition1.iKey        = KPubSubsTransCondKey1;
      condition1.iState    = 10;
      condition1.iType    = TTaskSchedulerCondition::EEquals;
      conditionList->AppendL(condition1);
      
      // Associate a task with the condition-based schedule
      TTaskInfo taskInfo2;
      
      _LIT(KTransSchedTaskName, "Transient - Condition-Based");
      _LIT(KTransSchedTaskData2, "Task data for transient schedule");
      
      taskInfo2.iName = KTransSchedTaskName;
      taskInfo2.iPriority = 2;
      taskInfo2.iRepeat = 0;
      
      // Create some data associated with this task
      HBufC* taskTransSchedData = KTransSchedTaskData2().AllocLC();
      
      //set the default time at which you want the transient condition-based
      //schedule to start, if no conditions are met
      // sets the date and time as Jan 1st, 2010, 10:01 am
      TDateTime datetime2(2010, EJanuary, 1, 10, 1, 0, 0); 
      TTsTime defaultRuntime(datetime2, ETrue); // 10:01 am
      
      // Create the transient condition-based schedule
      User::LeaveIfError(iScheduler.ScheduleTask(taskInfo2, *taskTransSchedData, ref2, *conditionList, defaultRuntime));
      
      CleanupStack::PopAndDestroy(2); // taskTransSchedData, conditionList
      
      ...

    Note: Schedules can be either persistent or transient. Persistent schedules have schedule information and any corresponding task data persisted to the disk.

    The task scheduler server reads this data back into memory when the phone is restarted. But, transient schedules do not have their data persisted and are deleted automatically once any associated tasks have finished running.
  4. Create the support for adding tasks to a persistent schedule by passing the handle of the persistent schedule to ScheduleTask(TTaskInfo& aTaskInfo, HBufC& aTaskData, const TInt aScheduleHandle). Notes:

    The following code snippet illustrates how to create a task and associate it with an existing persistent schedule.
    ...
    
    //Contains the handle to the persistent schedule
    TInt aScheduleId;
    ...
    
    
    TInt& aNewId;
    
    //Create the task that you want to add the persistent schedule
    TTaskInfo taskInfo;
    taskInfo.iTaskId = aNewId;
    
    _LIT(aName, "Task for Persistent Schedule");
    
    taskInfo.iName = aName;
    taskInfo.iPriority = 2;
    taskInfo.iRepeat = 0;
    
    HBufC* taskdata = _L("the data").AllocLC();
    
    iScheduler.ScheduleTask(taskInfo, *taskdata, aScheduleId);
    
    //Update aNewId with the task ID set by the task scheduler
    aNewId = taskInfo.iTaskId;
    ...
    
    CleanupStack::PopAndDestroy(); // taskdata
    
    ...
    Notes:
    • The HBufC* taskdata parameter is used by clients who want to send data to the executable that is launched when the task becomes due. When the executable is launched, this data is stored in a temporary task file and the filename is passed on the command line to the newly created process. That executable can then open the file and stream in the contents.

    • If multiple tasks are assigned to a schedule that has become due, the data for each schedule is concatenated into the same file. The tasks are stored in the file as CScheduledTask instances. The first item in the file is an integer describing how many tasks there are in the file. Subsequently the file just contains tasks which can be streamed in using the CScheduledTask::NewLC() method.

  5. Create the support for viewing schedules. This involves two steps:
    1. Get the name and ID (schedule handle) of schedules using RScheduler::GetScheduleRefsL().
      //Array that holds schedule entries
      CArrayFixFlat<TSchedulerItemRef>* CSchItemRefArray;
      CSchItemRefArray = new CArrayFixFlat<TSchedulerItemRef>(3);
      
      CleanupStack::PushL(CSchItemRefArray);
      
      //Get the list of all schedules
      User::LeaveIfError(iScheduler.GetScheduleRefsL(*CSchItemRefArray, EAllSchedules));
      
      ...
      
      //Gets the schedule handle and assigns it to schedHandle
      TInt schedHandle = *CSchItemRefArray)[1].iHandle;
      
      ...
    2. Get schedule details by passing the schedule handle to RScheduler::GetScheduleL() or RScheduler::GetScheduleTypeL().
      • Viewing details of time-based schedules:

        ...
        
        CArrayFixFlat<TTaskInfo> CTaskInfoArray;
        CTaskInfoArray* tasks = new (ELeave) CTaskInfoArray(3);
        
        TTsTime nextTimeScheduleIsDue;
        TScheduleState2 stateTimebasedSched;
        
        CArrayFixFlat<TScheduleEntryInfo2> CScheduleEntryInfoArray;
        CScheduleEntryInfoArray* entries = new (ELeave) CScheduleEntryInfoArray(3);
        
        CleanupStack::PushL(entries);
        
        iScheduler.GetScheduleL(schedHandle, stateTimebasedSched, *entries, tasks, nextTimeScheduleIsDue);
        CleanupStack::PopAndDestroy(entries);
      • Viewing details of condition-based schedules:

        ...
        
        TTsTime defaultTime;
        TScheduleState2 state;
        
        CArrayFixFlat<TTaskInfo> CTaskInfoArray;
        CTaskInfoArray* tasks = new (ELeave) CTaskInfoArray(3);
        
        CArrayFixFlat<TTaskSchedulerCondition> CSchConditionArray;
        CSchConditionArray* conditionList = new (ELeave) CSchConditionArray(3);
        CleanupStack::PushL(conditionList);
        
        iScheduler.GetScheduleL(schedHandle, state, *conditionList, defaultTime, tasks);
        
        CleanupStack::PopAndDestroy(conditionList);
      • Viewing the schedule type associated with a schedule: Identifies whether the schedule is a condition or time-based.

        ...
        
        TScheduleType &type;
        
        iScheduler.GetScheduleTypeL(schedHandle, type);
  6. Create the support for editing, enabling and disabling schedules. Schedules can be edited using RScheduler::EditSchedule() when a change is required to be done to a schedule. Before making changes to a schedule, you can use RScheduler::DisableSchedule() to disable a schedule, so that it is not triggered and later use RScheduler::EnableSchedule() to enable it, once the changes are done to the schedule. The following code snippet illustrates how to disable a time-based schedule, edit it to make changes to the schedule and later enable the schedule.
    //Editing time-based schedules
                      
    ...
    
    TInt schedHandle;
    
    ...
    
    //Disables the schedule referenced by "schedHandle"
    User::LeaveIfError(iScheduler.DisableSchedule(schedHandle);
    ...
    
    //Array to hold the schedule entries
    CArrayFixFlat<TScheduleEntryInfo2> CSchEntryInfoArray;
    CSchEntryInfoArray* entryList = new (ELeave) CSchEntryInfoArray(3);
    
    CleanupStack::PushL(entryList);
    
    //Change the start date and time as Jan 10th, 2010, 11:00 am
    TDateTime datetime2(2010, EJanuary, 10, 11, 0, 0, 0);
    TTsTime defaultRuntime(datetime2, ETrue);
    
    //create the schedule entry with the updated time
    TScheduleEntryInfo2 entry1 (defaultRuntime, EDaily, 1, 20); // 20m from "now"
    entryList->AppendL(entry1);
    
    //Enables the schedule referenced by "schedHandle"
    User::LeaveIfError(iScheduler.EnableSchedule(schedHandle);
    
    //edit the schedule
    User::LeaveIfError(iScheduler.EditSchedule(schedHandle, entryList));
            
    CleanupStack::PopAndDestroy(entryList);
    The following code snippet illustrates how to edit a condition-based schedule by passing the schedule handle of the schedule to be edited and the updated schedule condition details to RScheduler::EditSchedule().
    //Editing condition-based schedules
    ...
    
    TInt schedHandle;
    
    ...
    
    CArrayFixFlat<TTaskSchedulerCondition>* CSchConditionArray;
    
    
    CSchConditionArray conditionList = new (ELeave) CSchConditionArray(2);
    CleanupStack::PushL(conditionList);
    
    //update the condition
    TTaskSchedulerCondition condition1;
    
    //UID of the publish and subscribe category for condition1
    const TUid KPubSubsTransCondCategUid1 = TUid::Uid(0x102F7785);
    
    //Key of the publish and subscribe category for condition1
    const TInt KPubSubsTransCondKey1 = 1;
    
    condition1.iCategory = KPubSubsTransCondCategUid1;
    condition1.iKey        = KPubSubsTransCondKey1;
    condition1.iState    = 10;
    condition1.iType    = TTaskSchedulerCondition::EEquals;
    conditionList->AppendL(condition1);
    
    // sets the date and time as Jan 10th, 2010, 10:00 am
    TDateTime datetime2(2010, EJanuary, 10, 10, 0, 0, 0);
    TTsTime defaultRuntime(datetime2, ETrue);
    
    iScheduler.EditSchedule(schedHandle, *conditionList, defaultRuntime);
    
    ...
  7. Create the support for deleting schedules using RScheduler::DeleteSchedule().
    ...
    
    //Deletes the schedule referenced by "schedHandle"
    iScheduler.DeleteSchedule(schedHandle);
  8. Create the support for viewing task information associated with a schedule. This involves two steps:
    1. Get a list of all tasks or a subset of tasks using RScheduler::GetTaskRefsL().
      //Array to hold the list of tasks
      CArrayFixFlat<TSchedulerItemRef> CSchItemRefArray;
      CSchItemRefArray* refs = new (ELeave) CSchItemRefArray(3);
      
      //Gets the list of tasks
      iScheduler.GetTaskRefsL(*refs, EAllSchedules, EAllTasks);
      
      CleanupStack::PopAndDestroy(refs);
    2. Get details associated with a specific task using RScheduler::GetTaskInfoL().
      ...
      
      //Handle to the task
      TInt aTaskHandle;
      
      ...
      
      TInt taskSize = 0;
      
      //Gets the size of the data to be passed to the task's program.
      taskSize = iScheduler.GetTaskDataSize(aTaskHandle, taskSize);
      HBufC* taskData = HBufC::NewLC(taskSize);
      
      TPtr pTaskData = taskData->Des();
      
      TTsime scheduleNextDueTime;
      TTaskInfo taskFromServer;
      TSchedulerItemRef scheduleReference;
      
      //Gets task details
      iScheduler.GetTaskInfoL(aTaskHandle, taskFromServer, pTaskData, scheduleReference, scheduleNextDueTime);
      
      CleanupStack::PopAndDestroy(taskData);
  9. Create the support for deleting tasks associated with a schedule using RScheduler::DeleteTask().
    TInt taskId;
    
    ...
    
    iScheduler.DeleteTask(taskId);

Related concepts