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