Back to project page mezzofanti.
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.
/* * 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); } }