146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenpackage com.svox.pico.voice.fra.fra; 246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport java.io.File; 446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport java.io.FileOutputStream; 546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport java.io.IOException; 646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport java.io.InputStream; 746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport java.util.zip.ZipEntry; 846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport java.util.zip.ZipInputStream; 946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 1046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.app.Activity; 1146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.content.Intent; 1246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.content.res.AssetFileDescriptor; 1346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.content.res.Resources; 1446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.os.Bundle; 1546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.speech.tts.TextToSpeech; 1646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.util.Log; 1746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.view.View; 1846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.view.View.OnClickListener; 1946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenimport android.widget.Button; 2046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 2146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chenpublic class InstallerActivity extends Activity { 2246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private static final int DATA_ROOT_DIRECTORY_REQUEST_CODE = 42; 2346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private String rootDirectory = ""; 2446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private InstallerActivity self; 2546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private static boolean sInstallationSuccess = false; 2646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private static boolean sIsInstalling = false; 2746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private final static Object sInstallerStateLock = new Object(); 2846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 2946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen /** Called when the activity is first created. */ 3046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen @Override 3146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public void onCreate(Bundle savedInstanceState) { 3246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen super.onCreate(savedInstanceState); 3346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen self = this; 3446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen Intent getRootDirectoryIntent = new Intent(); 3546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen getRootDirectoryIntent.setClassName("com.svox.pico", "com.svox.pico.CheckVoiceData"); 3646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen startActivityForResult(getRootDirectoryIntent, DATA_ROOT_DIRECTORY_REQUEST_CODE); 3746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 3846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 3946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen @Override 4046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public void onActivityResult(int requestCode, int resultCode, Intent data){ 4146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen super.onActivityResult(requestCode, resultCode, data); 4246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen if (requestCode == DATA_ROOT_DIRECTORY_REQUEST_CODE) { 4346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen rootDirectory = data.getStringExtra(TextToSpeech.Engine.EXTRA_VOICE_DATA_ROOT_DIRECTORY); 4446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen // only run the installer if there isn't another one running 4546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen synchronized (sInstallerStateLock) { 4646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen if (!sIsInstalling && !sInstallationSuccess) { 4746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen sIsInstalling = true; 4846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen runInstaller(); 4946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 5046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 5146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 5246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 5346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 5446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private void runInstaller(){ 5546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen try { 5646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen Resources res = getResources(); 5746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen AssetFileDescriptor langPackFd = res 5846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen .openRawResourceFd(R.raw.svoxlangpack); 5946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen InputStream stream = langPackFd.createInputStream(); 6046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 6146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen (new Thread(new unzipper(stream))).start(); 6246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } catch (IOException e) { 6346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen Log.e("PicoLangInstaller", "Unable to open langpack resource."); 6446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen e.printStackTrace(); 6546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 6646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen setContentView(R.layout.installing); 6746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 6846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 6946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 7046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private boolean unzipLangPack(InputStream stream) { 7146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen FileOutputStream out; 7246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen byte buf[] = new byte[16384]; 7346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen try { 7446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen ZipInputStream zis = new ZipInputStream(stream); 7546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen ZipEntry entry = zis.getNextEntry(); 7646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen while (entry != null) { 7746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen if (entry.isDirectory()) { 7846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen File newDir = new File(rootDirectory + entry.getName()); 7946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen newDir.mkdir(); 8046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } else { 8146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen String name = entry.getName(); 8246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen File outputFile = new File(rootDirectory + name); 8346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen String outputPath = outputFile.getCanonicalPath(); 8446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen name = outputPath 8546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen .substring(outputPath.lastIndexOf("/") + 1); 8646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen outputPath = outputPath.substring(0, outputPath 8746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen .lastIndexOf("/")); 8846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen File outputDir = new File(outputPath); 8946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen outputDir.mkdirs(); 9046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen outputFile = new File(outputPath, name); 9146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen outputFile.createNewFile(); 9246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen out = new FileOutputStream(outputFile); 9346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 9446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen int numread = 0; 9546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen do { 9646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen numread = zis.read(buf); 9746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen if (numread <= 0) { 9846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen break; 9946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } else { 10046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen out.write(buf, 0, numread); 10146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 10246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } while (true); 10346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen out.close(); 10446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 10546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen entry = zis.getNextEntry(); 10646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 10746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen return true; 10846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } catch (IOException e) { 10946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen e.printStackTrace(); 11046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen return false; 11146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 11246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 11346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 11446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen private class unzipper implements Runnable { 11546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public InputStream stream; 11646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 11746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public unzipper(InputStream is) { 11846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen stream = is; 11946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 12046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 12146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public void run() { 12246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen boolean result = unzipLangPack(stream); 12346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen synchronized (sInstallerStateLock) { 12446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen sInstallationSuccess = result; 12546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen sIsInstalling = false; 12646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 12746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen if (sInstallationSuccess) { 12846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen // installation completed: signal success (extra set to SUCCESS) 12946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen Intent installCompleteIntent = 13046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen new Intent(TextToSpeech.Engine.ACTION_TTS_DATA_INSTALLED); 13146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen installCompleteIntent.putExtra(TextToSpeech.Engine.EXTRA_TTS_DATA_INSTALLED, 13246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen TextToSpeech.SUCCESS); 13346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen self.sendBroadcast(installCompleteIntent); 13446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen finish(); 13546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } else { 13646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen // installation failed 13746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen // signal install error if the activity is finishing (can't ask the user to retry) 13846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen if (self.isFinishing()) { 13946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen Intent installCompleteIntent = 14046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen new Intent(TextToSpeech.Engine.ACTION_TTS_DATA_INSTALLED); 14146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen installCompleteIntent.putExtra(TextToSpeech.Engine.EXTRA_TTS_DATA_INSTALLED, 14246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen TextToSpeech.ERROR); 14346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen self.sendBroadcast(installCompleteIntent); 14446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } else { 14546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen // the activity is still running, ask the user to retry. 14646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen runOnUiThread(new retryDisplayer()); 14746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 14846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 14946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 15046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 15146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 15246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 15346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public class retryDisplayer implements Runnable { 15446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public void run() { 15546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen setContentView(R.layout.retry); 15646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen Button retryButton = (Button) findViewById(R.id.retryButton); 15746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen retryButton.setOnClickListener(new OnClickListener() { 15846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen public void onClick(View arg0) { 15946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen // only run the installer if there isn't another one running 16046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen // (we only get here if the installer couldn't complete successfully before) 16146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen synchronized (sInstallerStateLock) { 16246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen if (!sIsInstalling) { 16346960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen sIsInstalling = true; 16446960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen runInstaller(); 16546960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 16646960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 16746960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 16846960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen }); 16946960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 17046960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen } 17146960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen 17246960c7fc30735201659b4f8d81cc3ed5c75e54cCharles Chen} 173