Mobile Web Wearable Web

Task: Download Manager

This task, based on the DownloadManager sample delivered with the Tizen SDK, demonstrates how you can use the Download API (in mobile and wearable applications) to asynchronously download URL content to the device storage. For more information on the sample functionality and creating the sample with the full source code, see DownloadManager.

This task consists of the following parts:

This sample is a fully functional application which allows the user to download any content by providing its URL. The user can control the download process.

Defining the Application Layout

The DownloadManager sample application layout contains only 1 screen: the main screen that displays the download items and progress. The application also has a template for displaying the download items.

The following figure shows the main screens of the application.

Figure: DownloadManager screens

DownloadManager screens

Defining the Main Screen

  1. index.html Source File

    The main screen of the application displays the URL input field, whose value is by default set to http://trailers.divx.com/divx_prod/profiles/WiegelesHeliSki_DivXPlus_19Mbps.mkv, and the OK button.

    <div id="main-header" data-role="header" data-position="fixed">
       <h1>Download manager</h1>
       <div id="main-url-div">
          <div id="main-input-div">
             <input type="text" id="main-url-text" placeholder="type URL" 
                    value="http://trailers.divx.com/divx_prod/profiles/WiegelesHeliSki_DivXPlus_19Mbps.mkv" />
          </div>
          <div id="main-button-div"><a data-role="button" id="main-url-ok">OK</a></div>
       </div>
    </div>
    
  2. js/app.ui.events.js Source File

    Clicking the OK button starts the download.

    $('#main-header').on('tap', '#main-url-ok', function onUrlOkTap() 
    {
       app.startDownloading($('#main-url-text').val());
    });        
    
  3. index.html Source File

    The download items are displayed on the main screen as a list, and the footer has the Refresh button.

    <div id="main-content" data-role="content">
       <ul data-role="listview"></ul>
    </div>
    
    <div id="main-footer" data-role="footer" data-position="fixed">
       <div data-role="button" data-inline="true" data-style="round" id="refresh-button">Refresh</div>
    </div>
    
  4. js/app.ui.events.js Source File

    Clicking the Refresh button refreshes the download item list.

    $('#refresh-button').on('tap', function onRefreshBtnTap(event) 
    {
       event.preventDefault();
       event.stopPropagation();
       app.refreshDownloadsList();
    });       
    

Defining the Template Mechanism

The Template Manager is used to follow the MVC architecture while generating a view item for the downloaded content. The whole process of generating the output HTML is divided into 3 parts:

  1. js/app.ui.templateManager.js Source File
    1. The Template Manager loads the template files to the cache.

      loadToCache: function TemplateManager_loadToCache(tplNames, onSuccess) 
      {
         var self = this,
             cachedTemplates = 0,
             tplName,
             tplPath;
      
         if ($.isArray(tplNames)) 
         {
            /* For each template */
            $.each(tplNames, function onTplIterate(index, fileName) 
            {
               /* Cache template html */
               if (self.cache[fileName] === undefined) 
               {
                  tplName = 
                  [
                     fileName,
                     app.config.get('templateExtension')
                  ].join('');
                  tplPath = 
                  [
                     app.config.get('templateDir'),
                     tplName
                  ].join('/');
      
                  $.ajax(
                  {
                     url: tplPath,
                     cache: true,
                     dataType: 'html',
                     async: true,
                     success: function onTplLoadSuccess(data) 
                     {
                        /* Increase counter */
                        cachedTemplates += 1;
      
                        /* Save to cache */
                        self.cache[fileName] = data;
      
                        /* If all templates are cached, launch callback */
                        if (cachedTemplates >= tplNames.length && typeof onSuccess === 'function') 
                        {
                           onSuccess();
                        }
                     },
                     error: function onTplLoadError(jqXHR, textStatus, errorThrown) 
                     {
                        /* Error handling */
                     }
                  });
               } 
               else 
               {
                  /* Template is already cached */
                  cachedTemplates += 1;
                  /* If all templates are cached, launch callback */
                  if (cachedTemplates >= tplNames.length && typeof onSuccess === 'function') 
                  {
                     onSuccess();
                  }
               }
            });
         }
      };
      
    2. The Template Manager returns the template HTML from the cache.

      get: function TemplateManager_get(tplName, tplParams) 
      {
         if (this.cache[tplName] !== undefined) 
         {
            return this.getCompleted(this.cache[tplName], tplParams);
         }
      
         return '';
      }
      
    3. The Template Manager returns the completed template where specified parameters have been inserted.

      getCompleted: function TemplateManager_getCompleted(tplHtml, tplParams) 
      {
         var tplParam;
      
         for (tplParam in tplParams) 
         {
            if (tplParams.hasOwnProperty(tplParam)) 
            {
               tplHtml = this.passThruModifiers(tplHtml, tplParam, tplParams[tplParam] );
            }
         }
      
         return tplHtml;
      }
      

Defining the Download Items

  1. templates/download-row.tpl Source File

    The download items are displayed in a list, where each item is its own row. The rows are placed in the list using the Template Manager.

    Every list element contains an icon suitable for the content type, the file name, some control buttons proper for the current download state, and a progress bar representing the download progress. The elements also have additional attributes used to recognize the download element recognition from the JavaScript code, for example while updating the progress bar value.

    <li class="downloadListElement" id="%downloadId%">
       <div class="download-item">
          <div class="download-desc" style="position: relative;">
             <img src="images/%fileIcon%" alt="icon" class="ui-li-bigicon"></img>
             <p class="download-name" id="name%downloadId%">%fileName%</p>
          </div>
          <div class="download-control">
             <div data-role="progressbar" id="progressbar%downloadId%"></div>
             <div class="download-buttons">
                <div data-role="button" class="download-button download-navigation-button" 
                     state="play" for-download="%downloadId%" for-url="%url%" 
                     id="button%downloadId%" listener-flag="1">
                   <img src="images/pause.png" class="download-navigation-button-image" 
                        id="buttonimg%downloadId%" />
                </div>
                <div data-role="button" class="download-button download-delete-button" 
                     state="play" for-download="%downloadId%" 
                     id="delete%downloadId%">
                   <img src="images/stop.png" class="download-navigation-button-image" 
                        id="deleteimg%downloadId%" />
                </div>
             </div>
          </div>
       <div>
    </li>
    

Managing Downloads

This section builds upon the elements described in Managing Downloads.

The core functionalities regarding the control of the download request are implemented in the js/app.model.js file.

Starting the Download

  1. js/app.model.js Source File

    The download process starts when user clicks OK next to the URL input field on the main screen. The button click indirectly invokes the startDownloading() method, which is responsible for starting the download process. A new DownloadRequest object is created and the download process is started through the DownloadManager object.

    startDownloading: function Model_startDownloading(url, eventHandlers, onSuccess) 
    {
       console.log('Model_startDownloading: ' + url);
       var downloadRequest, downloadId;
    
       try 
       {
          downloadRequest = new tizen.DownloadRequest(url, 'downloads');
          downloadId = tizen.download.start(downloadRequest, eventHandlers);
          onSuccess(downloadId, url);
       } 
    }
    
  2. js/app.js Source File

    After the download process is started successfully, the download item information is added to the local storage and the application user interface is updated.

    onDownloadStarted: function App_onDownloadStarted(id, url) 
    {
       console.log('App_onDownloadStarted: ', id);
       var fileName = this.helpers.getSourceName(url);
       this.ui.onDownloadStarted(id, url, fileName,
                                 this.model.updateRecord.bind(this, id, 
                                 {
                                    'fileName': fileName,
                                    'url': url,
                                    'state': 0
                                 }));
    }
    
  3. js/app.ui.js Source File

    The user interface is updated using the download row template obtained through the templateManager object.

    addDownloadRecordToList: function Ui_addDownloadRecordToList(id, url, fileName, updateStorageCallback) 
    {
       var ul = $('#main-content ul.ui-listview'),
           fileIcon = app.helpers.resolveFileIcon(app.helpers.getFileExtension(fileName)),
           listElement = this.templateManager.get('download-row', 
           {
              downloadId: id,
              fileName: fileName,
              url: url,
              fileIcon: fileIcon
           });
    
          ul.append(listElement).listview('refresh');
          ul.find('#progressbar' + id).progressbar({value: 0});
          ul.find('#delete' + id).button();
          ul.find('#button' + id).button();
          updateStorageCallback($('#progressbar' + id).progressbar('option', 'value'));
    }
    

Pausing and Resuming the Download

  1. js/app.ui.events.js

    After the download item is created, the user can pause or resume operations through the applicable buttons in the download list element. To display the correct buttons, you must identify the current state of the download request.

    $('#main').on( 'tap', '.download-navigation-button', function onNavigationBtnTap(event) 
    {
       event.preventDefault();
       event.stopPropagation();
       var obj = $(this);
       if (obj.attr('state') === 'play') 
       {
          app.pauseDownloading(obj.attr('for-download'));
       } 
       else if (obj.attr('state') === 'pause') 
       {
          app.resumeDownloading(obj.attr('for-url'),
                                obj.attr('for-download'),
                                obj.attr('listener-flag'));
       } 
       else if (obj.attr('state') === 'finished') 
       {
          app.launchFile($('#name' + obj.attr('for-download')).text());
       } 
       else if (obj.attr('state') === 'canceled') 
       {
          app.startDownloading(obj.attr('for-url'),
                               obj.attr('for-download'));
       }
    });
    
  2. js/app.model.js Source File
    1. If the request is in the play state, and the user clicks the button, the download process is paused. The user interface is notified about the pause by the callback, provided while starting the download process.

      pauseDownloading: function Model_pauseDownloading(downloadId) 
      {
         console.log('Model_pauseDownloading', downloadId);
         try 
         {
            tizen.download.pause(downloadId);
         } 
      }
      
    2. If the request in the paused state, the download process is resumed.

      resumeDownloading: function Model_resumeDownloading(downloadId, eventHandlers, listenerCallback) 
      {
         console.log('Model_resumeDownloading: ', downloadId);
         tizen.download.resume(downloadId);
         if (eventHandlers !== null) 
         {
            tizen.download.setListener(downloadId, eventHandlers);
            listenerCallback(downloadId);
         }
      }
      

Stopping the Download

  1. js/app.ui.events.js Source File

    To stop the download process, you must first determine the download request status.

    $('#main').on('tap', '.download-delete-button', function onDeleteBtnTap(event) 
    {
       event.preventDefault();
       event.stopPropagation();
       var obj = $(this);
       if (obj.attr('state') === 'play') 
       {
          app.cancelDownloading(obj.attr('for-download'));
       } 
       else if (obj.attr('state') === 'pause' ||
                obj.attr('state') === 'finished' ||
                obj.attr('state') === 'canceled' ||
                obj.attr('state') === 'failed') 
       {
          app.deleteDownloading(obj.attr('for-download'));
       }
    });
  2. js/app.model.js

    If the download status is play, you can invoke the download cancellation function.

    cancelDownloading: function Model_cancelDownloading(downloadId) 
    {
       console.log('Model_cancelDownloading: ' + downloadId);
       try 
       {
          tizen.download.cancel(downloadId);
       } 
    }
    
  3. js/app.ui.js

    If the download request is not in the play state, the download is removed from the main screen list and local storage.

    deleteDownloading: function Ui_deleteDownloading(id) 
    {
       $('#' + id).remove();
    }
    
Go to top