Android Open Source - mezzofanti Download Manager






From Project

Back to project page mezzofanti.

License

The source code is released under:

Apache License

If you think the Android project mezzofanti listed in this page is inappropriate, such as containing malicious code/tools or violating the copyright, please email info at java2s dot com, thanks.

Java Source Code

/*
 * Copyright (C) 2009 IT Wizard./*from   ww  w.  j  a  v  a2s .  co m*/
 * http://www.itwizard.ro
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */

package com.itwizard.mezzofanti;

import java.io.DataOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.Enumeration;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;

import android.app.ProgressDialog;
import android.os.Handler;
import android.util.Log;

/**
 * This object wraps the download functionality. The OCR engine needs different language-files that are large in
 * size and will not be kept in the package. Any additional language that will be installed by the client will be
 * downloaded from the Internet (in a zip file), unziped in a temporary directory, and finally saved in the language directory.     
 */
public class DownloadManager implements Runnable
{
  private static final String TAG = "MLOG: Download.java: ";
  
  private int m_iLangIndex;      // the lang index to be downloaded
  private boolean m_bProcessing;    // will not allow to start another download thread if one already running
  private boolean m_bCancelDownload;  // variable used to cancel the current download
  private long m_lCurrentDownloadSz;  // bytes downloaded
  private long m_lMaxDownloadSz;    // total download size in bytes
  private Handler m_ParentMessageHandler = null;  // the parent message handler
  private ProgressDialog m_ParentProgressDialog;  // progress dialog of the parent, to display the status
  private final int PROGRESS_STEP = 100;      // the progress step
  private boolean m_bSdcardError = false;
  
  /**
   * this class holds the info about each language stored on the server
   */
  public class ServerLang
  {
    // ex: lang=English,eng,26
    String sFullName;  //English
    String sExtName;  //eng
    long lDownloadSz;  //26MB - ignored at this point (because we can get this via the protocol)

    /**
     * constructor
     * @param sLanguageInfo a line containing all language info - to be parsed in the constructor
     */
    ServerLang(String sLanguageInfo)
    {
      String [] s = sLanguageInfo.split(",");
      if (s.length == 3)
      {
        try{
          sExtName = s[0];
          lDownloadSz = Long.parseLong(s[1]);
          sFullName = s[2].replace("[\r\n\0]+", "");
          Log.v(TAG, "created SL :"+" "+sExtName+" "+lDownloadSz+" "+sFullName);
        }
        catch (Exception ex)
        {
          Log.v(TAG, "Exception: " + ex.toString());
        }
      }
    }
  }
  
  public ServerLang [] m_ServerLanguages = null;  // vector holding the languages available on the server
  
  
  
  
  /**
   * constructor
   */
  DownloadManager()
  {
    m_ParentMessageHandler = null;
  }
  
  /**
   * set the parent message handler
   * @param mh the parent message handler
   */
  public void SetMessageHandler(Handler mh)
  {
    m_ParentMessageHandler = mh;
  }
  
  /**
   * set the parent progress dialog
   * @param pd the parent progress dialog
   */
  public void SetProgressDialog(ProgressDialog pd)
  {
    m_ParentProgressDialog = pd;
  }
  
  /** 
   * this will return the languages available online in a string
   * and will set the local variables accordingly
   * @param url the server URL
   * @param filename the brief-language filename 
   */  
  public boolean DownloadLanguageBrief(String url, String filename)
  {
    Log.v(TAG, "DownloadLanguageBrief (" + url + filename + ")");
    String ret = "";

    // create url connector
      URL u;
      byte[] buffer = new byte[1024];
    try {
      u = new URL(url + filename);
        HttpURLConnection c = (HttpURLConnection) u.openConnection();
        c.setRequestMethod("GET");
        c.setDoOutput(true);
        c.connect();
        InputStream in = c.getInputStream();
      Log.v(TAG, "DownloadFile opened connection");
        
        FileOutputStream f = new FileOutputStream(new File(Mezzofanti.TEMP_PATH, filename));
    
        int len = 0;
        int total_len = 0;
        while ( (len = in.read(buffer, 0, 1024)) > 0 ) 
        {
             f.write(buffer, 0, len);
             total_len += len;
             if (len > 0)
             {
               String s = new String(buffer, 0, len);
               ret += s;
             }
        }
        
        // create serverLanguages vector
        if (ret.length() > 0)
        {
          String [] lines = ret.split("\n");
          m_ServerLanguages = new ServerLang[lines.length];
          for (int i=0; i<lines.length; i++)
            m_ServerLanguages[i] = new ServerLang(lines[i]);
        }
        
        Log.v(TAG, "total len=" + total_len);
        f.close();
        c.disconnect();
        
    } catch (Exception e) 
    {
      Log.v(TAG, e.toString());
      return false;
    }
      
    Log.v(TAG, "returning: " + ret);
      return true;
  }
    
  // this will download the language, based on the index in the m_ServerLanguages vector
  /**
   * download a specific language from the server.
   * @param langIndex the index of the language from the m_ServerLanguages 
   */
  public void DownloadLanguageJob(int langIndex)
  {  
    if (m_bProcessing)
    {
      // already in a download (to cancel the download call the appropriate method)
      Log.v(TAG, "DownloadLanguageJob: already processing a job, please cancel the prev job before another restart");
      return;
    }
        
    if (m_ServerLanguages == null)
      return;
    if (langIndex > m_ServerLanguages.length)
      return;

    m_bProcessing = true;
    m_bCancelDownload = false;
    m_iLangIndex = langIndex;
    
    // Note: moved these to DownloadFile
    //m_lCurrentDownloadSz = 0;  
    //m_lMaxDownloadSz = m_ServerLanguages[langIndex].lDownloadSz;
    
      Thread theDownloadThread = new Thread(this);
      theDownloadThread.start();
  }
    
  /**
   * smooth cancel of the download
   */
  public void CancelDownload()
  {
    Log.v(TAG, "Force CANCEL Download [" + GetDownloadStatus() + "%]");
    m_bCancelDownload = true;
  }

  /**
   * @return the download status [0-100] %
   */
  public int GetDownloadStatus()
  {
    if (m_bProcessing == false)
      return 0;
    
    long proc_down = 0; // [0-100]
    if (m_lMaxDownloadSz != 0)
      proc_down = m_lCurrentDownloadSz * 100/m_lMaxDownloadSz;
    //Log.v(TAG, "GetDownloadStatus(): downloaded "+m_lCurrentDownloadSz +"B ["+proc_down+"%]");
    
    return (int) proc_down;
  }
  
  
  /**
   * the download job
   */
  public void run() 
  {
    int downloadsz = 0;
    
    // download the file
    String file_name = m_ServerLanguages[m_iLangIndex].sExtName + ".zip";
    Log.v(TAG, "Downloading file: " + file_name);
    boolean download_ok = DownloadFile(Mezzofanti.DOWNLOAD_URL, file_name);
    int ret = R.id.downloadmanager_downloadFinishedError;
    
    //!! if zip is already downloaded in the temp dir, it should be not downloaded again
    
    m_lCurrentDownloadSz += downloadsz;
    Log.v(TAG, "Download ended: " + file_name + " [" +GetDownloadStatus()+"%]");      

    if (download_ok)
    {
      Log.v(TAG, "Download succesfully finished");
      String zipname = Mezzofanti.TEMP_PATH + file_name;
      
            
      m_ParentMessageHandler.sendEmptyMessage(R.id.downloadmanager_unziping);
      if (UnzipLangArchive(zipname))
      {
        Log.v(TAG, "Unzipped ok");
        if (RenameTempFiles())
        {
          Log.v(TAG, "Renamed ok");
          ret = R.id.downloadmanager_downloadFinishedOK;
        }
        else
          Log.v(TAG, "Renamed error");
      }
      else
      {
        Log.v(TAG, "Unzip returned false");        
      }
    }
    else
    {
      Log.v(TAG, "Download UNSUCCESFULLY finished");
    }
    
    m_bProcessing = false;
    if (m_bSdcardError)
      ret = R.id.downloadmanager_downloadFinishedErrorSdcard;
    m_ParentMessageHandler.sendEmptyMessage(ret);
  }  


  /**
   * get the total unpacked size of the contents of the zip 
   * @param zipname the zip filename
   * @return the total unpacked size
   */
  private long GetZipSize(String zipname)
  {
        ZipFile zipFile;
        long ret = 0;
        
      try 
      {
        zipFile = new ZipFile(zipname);
  
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) 
        {
          ZipEntry entry = (ZipEntry)entries.nextElement();
  
          ret += entry.getSize();
        }
  
        zipFile.close();
      } 
      catch (IOException ioe) 
      {
        Log.v(TAG, "exception:" + ioe.toString());
        return 0;
      }
      return ret;
  }
  
  /**
   * Unzip an archive
   * @param zipname the archive name, stored in the temp directory
   * @return boolean state indicating the unzip success
   */
    private boolean UnzipLangArchive(String zipname)
    {
        ZipFile zipFile;
        
        // reset the statuses, thus we will be able to get the progress[%] status 
        m_lMaxDownloadSz = GetZipSize(zipname);
        m_lCurrentDownloadSz = 0;

        try 
      {
        zipFile = new ZipFile(zipname);
  
        Enumeration<? extends ZipEntry> entries = zipFile.entries();
        while (entries.hasMoreElements()) 
        {
          ZipEntry entry = (ZipEntry)entries.nextElement();
  
          String filename = entry.getName();
          Log.v(TAG, "Extracting file: " + filename);
            
          if (!CopyInputStream(zipFile.getInputStream(entry), entry.getSize(), entry.getName()))
            return false;
       m_ParentProgressDialog.setProgress(GetDownloadStatus());
        }
  
        zipFile.close();
      } 
      catch (IOException ioe) 
      {
        Log.v(TAG, "exception:" + ioe.toString());
        return false;
      }
      
      return true;
  }  
  
    /**
     * Copy a file from zip on the disk.
     * @param in InputStream of the zip file.
     * @param in_size the size of the input stream
     * @param outname the name of the output file
     * @return a boolean indicating the success of the copy procedure
     * @throws IOException
     */
  private final boolean CopyInputStream(InputStream in, long in_size, String outname)
    throws IOException
    {
      byte[] buffer = new byte[1024];
      int len;
      DataOutputStream out = null;
      int kont = 0;
      
      try
      {
      File f = new File(Mezzofanti.TEMP_PATH + outname);      
      long fsz = f.length();

      //!! consider to remove this for clean reinstall at upload
      if (f!=null && f.isFile() && fsz == in_size)
      {
        Log.v(TAG, "File " + outname + " already installed disksz="+fsz +" zipsz="+in_size);
        return true;
      }
      else
      {
        Log.v(TAG, "File " + outname + " NOT installed disksz="+fsz +" zipsz="+in_size);
      }
        
      if (in_size > AssetsManager.GetFreeSpaceB())
      {
          Log.v(TAG, "Warning: not enough disk space");
          m_bSdcardError = true;
          return false;
      }
      
        //BufferedOutputStream out = new BufferedOutputStream(new FileOutputStream(Mezzofanti.DATA_PATH + outname));
      out = new DataOutputStream(new FileOutputStream(Mezzofanti.TEMP_PATH + outname));
        
        while((len = in.read(buffer)) >= 0)
        {
         if (m_bCancelDownload)
           return false; 
         kont++;
         if (kont >= PROGRESS_STEP)
         {
           m_ParentProgressDialog.setProgress(GetDownloadStatus());
           kont = 0;
         }
         out.write(buffer, 0, len);
         m_lCurrentDownloadSz += len;
        } 
        
        in.close();
        out.close();
      }
      catch (Exception ex)
      {
        m_bSdcardError = true;
        Log.v(TAG, "Exception: " + ex.toString());
        return false;
      }
      
    return true;
  }
    
    
    /**
     * rename/moves the temporary unziped files in the resources directory. 
     * @return status of the procedure
     */
  private boolean RenameTempFiles()
  {
    Log.v(TAG, "RenameTempFiles(): STARTED");
    String lang = m_ServerLanguages[m_iLangIndex].sExtName;
    
    // rename/move the files to the final directory
    for (int i=0; i<Mezzofanti.svLangExtNames.length; i++)
    {
      String filename = lang + Mezzofanti.svLangExtNames[i];
      if (!RenameFileOrDir(Mezzofanti.TEMP_PATH + filename, Mezzofanti.DATA_PATH + filename))
      {
        Log.v(TAG, "FAILED to rename " + Mezzofanti.TEMP_PATH + filename);
        return false;
      }
      else
        Log.v(TAG, "Renamed " + Mezzofanti.TEMP_PATH + filename);
        
    }
    Log.v(TAG, "RenameTempFiles(): Finished");
    return true;
  }
  
  /**
   * rename a file or a directory
   * @param initialName input name & path 
   * @param finalName output name & path
   * @return state of the process
   */
  public boolean RenameFileOrDir(String initialName, String finalName)
  {
    boolean ret = false;
    try
    {
        File file = new File(initialName);
        File file2 = new File(finalName);
        
        ret = file.renameTo(file2);
    }
    catch (Exception ex)
    {
      Log.v(TAG, "Exception: "+ex.toString());
      ret = false;
    }
    
    return ret;
  }
  
  
  /**
   * Download a file from the server.
   * @param url the server URL
   * @param filename the name of the file to be downloaded
   * @return true on procedure success 
   */
  public boolean DownloadFile(String url, String filename)
  {
    Log.v(TAG, "DownloadFile (" + url + filename + ")");
      int len = 0;
      m_lCurrentDownloadSz = 0;
      m_lMaxDownloadSz = -1;
      int kont = 0;

    // create url connector
      URL u;
      byte[] buffer = new byte[1024];
    try {
      u = new URL(url + filename);
      
        HttpURLConnection c = (HttpURLConnection) u.openConnection();
        c.setRequestMethod("GET");
        c.setDoOutput(true);
        c.setUseCaches(true);
        c.connect();
        InputStream in = c.getInputStream();
      Log.v(TAG, "DownloadFile opened connection");
        m_lMaxDownloadSz = c.getContentLength();
        
        if (m_lMaxDownloadSz > AssetsManager.GetFreeSpaceB())
        {
          Log.v(TAG, "Warning: not enough disk space");
          m_bSdcardError = true;
          return false;
        }
        
        File ft = new File(Mezzofanti.TEMP_PATH, filename);
        if (ft!=null && ft.isFile() && ft.length() == m_lMaxDownloadSz)
        {
          Log.v(TAG, "Download has the same size as the temp file - do not download");
          return true;
        }
        
        FileOutputStream f = new FileOutputStream(new File(Mezzofanti.TEMP_PATH, filename)); 
        Log.v(TAG, "contentlen=" + c.getContentLength());
        
        while ( (len = in.read(buffer, 0, 1024)) > 0 ) 
        {
        if (m_bCancelDownload)
        {
          f.close();
          c.disconnect();
          return false;
        }
        
         kont++;
         if (kont >= PROGRESS_STEP)
         {
           m_ParentProgressDialog.setProgress(GetDownloadStatus());
           kont = 0;
         }
             f.write(buffer, 0, len);
             m_lCurrentDownloadSz += len;
        }
        Log.v(TAG, "total len=" + m_lCurrentDownloadSz);
        f.close();
        c.disconnect();
        
      if (c.getContentLength() != m_lCurrentDownloadSz)
      {
        Log.v(TAG, "------------ NOT ALL FILE DOWNLOADED -------------------");
      }
    } catch (Exception e) 
    {
      Log.v(TAG, e.toString());
      return false;
    }

      return (m_lCurrentDownloadSz == m_lMaxDownloadSz);
  }   
}




Java Source Code List

com.itwizard.mezzofanti.AssetsManager.java
com.itwizard.mezzofanti.CameraManager.java
com.itwizard.mezzofanti.CaptureLayout.java
com.itwizard.mezzofanti.CustomImageButton.java
com.itwizard.mezzofanti.DownloadManager.java
com.itwizard.mezzofanti.InstallActivity.java
com.itwizard.mezzofanti.LanguageDialog.java
com.itwizard.mezzofanti.Languages.java
com.itwizard.mezzofanti.Maps.java
com.itwizard.mezzofanti.Mezzofanti.java
com.itwizard.mezzofanti.OCR.java
com.itwizard.mezzofanti.OnScreenHint.java
com.itwizard.mezzofanti.PreferencesActivity.java
com.itwizard.mezzofanti.ResultsActivity.java
com.itwizard.mezzofanti.TranslateActivity.java
com.itwizard.mezzofanti.Translate.java