Page Example

Call Log Sample Overview

The Call Log sample application demonstrates how you can view the detailed call history from the device or from a specific caller.

The following figure illustrates the main screens of the Call Log.

Figure: Call Log screens

Call Log screens

The application opens with the main screen that shows the recent call history. On the History for caller screen, click:

  • Call to make a call.
  • Message to send an SMS.
  • DELETE to delete call history items.

Prerequisites

  • An active SIM card
  • If the call history is empty, the application cannot be used.
  • The application does not work on the Emulator.
  • To ensure proper application execution, the following privileges must be set:

    • http://tizen.org/privilege/application.launch
    • http://tizen.org/privilege/callhistory.read
    • http://tizen.org/privilege/callhistory.write
    • http://tizen.org/privilege/contact.read

Source Files

You can create and view the sample application project including the source files in the IDE.

File name Description
config.xml This file contains the application information for the platform to install and launch the application, including the view mode and the icon to be used in the device menu.
index.html This is a starting file from which the application starts loading. It contains the layout of the application screens.
js/app.config.js This file allows storing the configuration values.
js/app.helpers.js This file contains the helper functions used by the application.
js/app.js This file defines the main application class.
js/app.model.js This file handles the data used by the common part of the application.
js/app.ui.js This file handles the application UI.
js/app.ui.templateManager.js This file contains the TemplateManager class that manages, caches, and provides HTML templates.
js/app.ui.templateManager.modifiers.js This file contains the filters used in the templates.
js/main.js This file starts the application.
images/ This directory contains the images used to create the user interface.
templates/ This directory contains the layout for the application screens, and templates for smaller UI components.
lib/tau/ This directory contains the external libraries (TAU library).

Implementation

On initialization of the application layout, the Contact API is used to get phone contacts.

/* app.ui.js */
init: function Ui_init() 
{
   /* Load contacts */
   this.loadContacts();
   this.templateManager = new TemplateManager();
   this.helpers = new Helpers();
   $(document).ready(this.domInit.bind(this));
   $.mobile.tizen.disableSelection(document);
},

On successfully getting contacts, they are assigned to UI class variable contactsLoaded.

/* app.ui.js */
loadContacts: function Ui_loadContacts(callback) 
{
   var contactsFoundCB, errorCB;

   this.contactsLoaded = null;

   contactsFoundCB = function onContactsFindSuccess(contacts) 
   {
      this.contactsLoaded = contacts;
      if (callback instanceof Function) 
      {
         callback();
      }
   };

   errorCB = function onContactFindError(error) 
   {
   console.error('Model_loadContacts, problem with find() method: ' + error.message);
   };

/* Load contacts */
this.addressBook.find(contactsFoundCB.bind(this), errorCB);
},

The application main page uses the Callhistory API to display a list of made and received calls. The following method initializes the UI pages. The Callhistory API is used in the app.showCallHistory() method to get the call history.

/* app.ui.js */
initPages: function Ui_initPages() 
{
   var pages = [], body = $('body');

   body
   .append(this.templateManager.get('messageWindow'))
   .append(this.templateManager.get('errorWindow'))
   .trigger('create');
   .append($(this.templateManager.get('callView')).children())
   .trigger('pagecreate')
   .trigger('pageshow');
   pages.push(this.templateManager.get('callerHistory'));
   body.append(pages.join(''));
   this.removeSearchBarToHeader();

   this.addEvents();

   /* Show call history */
   app.showCallHistory();

   this.photoURIdefault = $('#header .photo').css('background-image');
},

The following method calls the model method. The success function this.ui.showCallHistory.bind(this.ui) is rendering the call history list method (js/app.ui.js showCallHistory shown lower).

/* app.js */
showCallHistory: function App_showCallHistory() 
{
   this.model.getCallHistory(this.ui.showCallHistory.bind(this.ui));
},    

The method sorts the list of connections by start time, where each element is a collection of data, such as a remote phone number, call start time, or call duration (see interface of CallHistoryEntry).

/* app.model.js */
getCallHistory: function Model_getCallHistory(onSuccess, onError) 
{
   if (typeof onError !== 'function') 
   {
      onError = function onCallHistoryFindError(e) 
      {
         console.error('Model_getCallHistory error', e);
      };
   }

   tizen.callhistory.find(onSuccess, onError, null,
      new tizen.SortMode('startTime', 'DESC'));
},

The following method call is the onSuccess function using callEntries to fill the call list. Callers are grouped by phone numbers.

/* app.ui.js */
showCallHistory: function Ui_showCallHistory(callEntries) 
{
   var self = this,

   /* Return duplicated entries */
   function filterForSameEntry(element) 
   {
      return self.getNumber(current) === self.getNumber(element) 
             && current.direction === element.direction;
   }

    for (i = 0; i < len; i = i + 1) 
   {
      current = callEntries[i];
      date = this.helpers.toNativeDate(current.startTime);

      /* If the date is changed, create a new dayLog */

      /* Group the entries by remote party */
      filterResult = dayLog.entries.filter(filterForSameEntry);
   }
   /* Create UL list with dividers */
   calllogListContentPos = this.helpers.getScrollPosition(calllogListContent);
   calllogList.empty().append(elements);
   /* Searching phrase */

   setTimeout(this.helpers.scrollTo.bind(this, calllogListContent, calllogListContentPos), 10);
},

By tapping on a list element on the main page, the page changes to the Caller details view with a list of connections. You can use a filter in the find() method to reduce the search result by a specified phone number.

/* app.model.js */
getCallHistoryForCaller: function Model_getCallHistoryForCaller(phoneNumber, onSuccess) 
{
   var filter = null, success;
   if (phoneNumber) 
   {
      filter = new tizen.AttributeFilter('remoteParties.remoteParty', 'EXACTLY', phoneNumber);
      success = onSuccess;
   } 
   else 
   {
      success = function onCallHistoryFindSuccess(calls) 
      {
         onSuccess(calls.filter(function onIterate(element) 
         {
            if (!element.remoteParties[0].remoteParty) 
            {
               return element;
            }
         }));
      };
   }

    tizen.callhistory.find(success, function onCallHistoryFindError(e) 
   {
      console.error(e);
   },
   filter,
   new tizen.SortMode('startTime', 'DESC'));
},

On the Caller details view the following actions can be made:

  • Calling by clicking the Call button. The Application API is used to make a call. The ApplicationControl interface is used to launch other applications. To respond to the call log by calling, specify the http://tizen.org/appcontrol/operation/dial operation and the contact number as parameters.

    /* app.uj.js */
    $('#callActionBtn').on('click', function onCallBtnClick() 
    {
       self.lockButtons('#callActionBtn, #smsActionBtn');
       self.hideCheckboxes();
       self.lockButtons('#deleteActionBtn');
       app.makeCall($('#forCallerList').data('remoteParty'));
    });
    
    /* app.js */
    makeCall: function App_makeCall(phoneNumber) 
    {
       var self = this,
           appControl = new tizen.ApplicationControl('http://tizen.org/appcontrol/operation/call', 'tel:' + phoneNumber);
       tizen.application.launchAppControl(appControl, null, function onCallSuccess() 
       {
          setTimeout(function unlockButtons() 
          {
             self.ui.unlockButtons();
          },
          1500);
       },
       function onCallError(e) 
       {
       console.error('Call to ' + phoneNumber + ' failed. Call service is unavailable.', e);
       self.ui.showErrorPopup('Call failed. ' + 'Call service is unavailable.');  self.ui.unlockButtons();
       },
       {
          onsuccess: function onCallSuccess() 
          {
             self.ui.unlockButtons();
          },
          onfailure: function onCallError(e) 
          {
             console.log('App_makeCall: Call to ' + phoneNumber + ' failed. Call service was busy.', e);
             .ui.unlockButtons();
          }
       });
       },
    
  • Sending a message by clicking the Message button.

    /* app.ui.js */
       $('#smsActionBtn').on('click', function onSmsBtnClick(event) 
    {
       event.stopPropagation();
       event.preventDefault();
       self.lockButtons('#smsActionBtn, #callActionBtn');
       self.hideCheckboxes();
       self.lockButtons('#deleteActionBtn');
       /* Send SMS */
       app.sendSms($('#forCallerList').data('remoteParty'));
    });
    

    To respond to the call log by sending a message, specify the http://tizen.org/appcontrol/operation/compose operation and the contact number as parameters.

    /* app.js */
    sendSms: function App_sendSms(phoneNumber) 
    {
       var self = this,
           appControl = new tizen.ApplicationControl('http://tizen.org/appcontrol/operation/compose', 'sms:' + phoneNumber);
    
       tizen.application.launchAppControl(appControl, null, null, function onSendMessageError(e) 
       {
          console.error('Message launch error: ', e);
          self.ui.showErrorPopup('Message service is unavailable');
          app.ui.unlockOptionButtons();
       },
       {
          onfailure: function onSendMessageError(er) 
          {
             console.error('Message service launch error: ', er);
             self.ui.showErrorPopup('Message service is unavailable');
             app.ui.unlockOptionButtons();
          }
       });
    },
    
  • Deleting the log entries by clicking the DELETE button on the bottom of the screen.

    To remove an entry from the call history, use the tizen.callhistory.remove method with CallHistoryEntry argument. Removing is realized in a loop that depends on the checked call logs to delete the checked call log entries.

    First, there is a call to an app.js method with the specified entry.

    /* app.ui.js */
    deleteCheckedLogs: function Ui_deleteCheckedLogs(e) 
    {
       /* If there is popup open, close it */
       this.closePopup();
    
       /* Uncheck SelectAll checkbox */
       this.selectCheckbox($('#selectAllDetails'), false);
    
       /* Iterate through all entries */
       $('#forCallerList li.call').each(function onCallEntryIterate() 
       {
          /* If entry contains selected checkbox */
          if ($(this).find('form label').hasClass('ui-checkbox-on')) 
          {
             /* Remove that entry */
             app.deleteLog($(this).data('entries')[0]);
             /* Remove connected HTML element */
             $(this).remove();
          }
       });
    }
    

    Then, the following method calls for the model method.

    /* app.js */
    deleteLog: function App_deleteLogs(entry) 
    {
       this.model.deleteLog(entry);
    },
    

    The following model method uses the API to delete a given entry from the call history.

    /* app.model.js */
    deleteLog: function Model_deleteLog(entry) 
    {
       try 
       {
          tizen.callhistory.remove(entry);
       } 
       catch (e) 
       {
          console.error('Error on entry delete: ' + e.message);
       }
    },
    

    The Application API is used to exit the application in the exit method of the app module.

    /* app.js */
    exit: function App_exit(event) 
    {
       if (event instanceof Event) 
       {
          event.preventDefault();
          event.stopPropagation();
       }
       tizen.application.getCurrentApplication().exit();
    }