1package com.svox.pico.voice.spa.esp;
2
3import java.io.File;
4import java.io.FileOutputStream;
5import java.io.IOException;
6import java.io.InputStream;
7import java.util.zip.ZipEntry;
8import java.util.zip.ZipInputStream;
9
10import android.app.Activity;
11import android.content.Intent;
12import android.content.res.AssetFileDescriptor;
13import android.content.res.Resources;
14import android.os.Bundle;
15import android.speech.tts.TextToSpeech;
16import android.util.Log;
17import android.view.View;
18import android.view.View.OnClickListener;
19import android.widget.Button;
20
21public class InstallerActivity extends Activity {
22    private static final int DATA_ROOT_DIRECTORY_REQUEST_CODE = 42;
23    private String rootDirectory = "";
24    private InstallerActivity self;
25    private static boolean sInstallationSuccess = false;
26    private static boolean sIsInstalling = false;
27    private final static Object sInstallerStateLock = new Object();
28
29    /** Called when the activity is first created. */
30    @Override
31    public void onCreate(Bundle savedInstanceState) {
32        super.onCreate(savedInstanceState);
33        self = this;
34        Intent getRootDirectoryIntent = new Intent();
35        getRootDirectoryIntent.setClassName("com.svox.pico", "com.svox.pico.CheckVoiceData");
36        startActivityForResult(getRootDirectoryIntent, DATA_ROOT_DIRECTORY_REQUEST_CODE);
37    }
38
39    @Override
40    public void onActivityResult(int requestCode, int resultCode, Intent data){
41        super.onActivityResult(requestCode, resultCode, data);
42        if (requestCode == DATA_ROOT_DIRECTORY_REQUEST_CODE) {
43            rootDirectory = data.getStringExtra(TextToSpeech.Engine.EXTRA_VOICE_DATA_ROOT_DIRECTORY);
44            // only run the installer if there isn't another one running
45            synchronized (sInstallerStateLock) {
46                if (!sIsInstalling && !sInstallationSuccess) {
47                    sIsInstalling = true;
48                    runInstaller();
49                }
50            }
51        }
52    }
53
54    private void runInstaller(){
55        try {
56            Resources res = getResources();
57            AssetFileDescriptor langPackFd = res
58                    .openRawResourceFd(R.raw.svoxlangpack);
59            InputStream stream = langPackFd.createInputStream();
60
61            (new Thread(new unzipper(stream))).start();
62        } catch (IOException e) {
63            Log.e("PicoLangInstaller", "Unable to open langpack resource.");
64            e.printStackTrace();
65        }
66        setContentView(R.layout.installing);
67    }
68
69
70    private boolean unzipLangPack(InputStream stream) {
71        FileOutputStream out;
72        byte buf[] = new byte[16384];
73        try {
74            ZipInputStream zis = new ZipInputStream(stream);
75            ZipEntry entry = zis.getNextEntry();
76            while (entry != null) {
77                if (entry.isDirectory()) {
78                    File newDir = new File(rootDirectory + entry.getName());
79                    newDir.mkdir();
80                } else {
81                    String name = entry.getName();
82                    File outputFile = new File(rootDirectory + name);
83                    String outputPath = outputFile.getCanonicalPath();
84                    name = outputPath
85                            .substring(outputPath.lastIndexOf("/") + 1);
86                    outputPath = outputPath.substring(0, outputPath
87                            .lastIndexOf("/"));
88                    File outputDir = new File(outputPath);
89                    outputDir.mkdirs();
90                    outputFile = new File(outputPath, name);
91                    outputFile.createNewFile();
92                    out = new FileOutputStream(outputFile);
93
94                    int numread = 0;
95                    do {
96                        numread = zis.read(buf);
97                        if (numread <= 0) {
98                            break;
99                        } else {
100                            out.write(buf, 0, numread);
101                        }
102                    } while (true);
103                    out.close();
104                }
105                entry = zis.getNextEntry();
106            }
107            return true;
108        } catch (IOException e) {
109            e.printStackTrace();
110            return false;
111        }
112    }
113
114    private class unzipper implements Runnable {
115        public InputStream stream;
116
117        public unzipper(InputStream is) {
118            stream = is;
119        }
120
121        public void run() {
122            boolean result = unzipLangPack(stream);
123            synchronized (sInstallerStateLock) {
124                sInstallationSuccess = result;
125                sIsInstalling = false;
126            }
127            if (sInstallationSuccess) {
128                // installation completed: signal success (extra set to SUCCESS)
129                Intent installCompleteIntent =
130                        new Intent(TextToSpeech.Engine.ACTION_TTS_DATA_INSTALLED);
131                installCompleteIntent.putExtra(TextToSpeech.Engine.EXTRA_TTS_DATA_INSTALLED,
132                        TextToSpeech.SUCCESS);
133                self.sendBroadcast(installCompleteIntent);
134                finish();
135            } else {
136                // installation failed
137                // signal install error if the activity is finishing (can't ask the user to retry)
138                if (self.isFinishing()) {
139                    Intent installCompleteIntent =
140                        new Intent(TextToSpeech.Engine.ACTION_TTS_DATA_INSTALLED);
141                    installCompleteIntent.putExtra(TextToSpeech.Engine.EXTRA_TTS_DATA_INSTALLED,
142                            TextToSpeech.ERROR);
143                    self.sendBroadcast(installCompleteIntent);
144                } else {
145                    // the activity is still running, ask the user to retry.
146                    runOnUiThread(new retryDisplayer());
147                }
148            }
149        }
150    }
151
152
153    public class retryDisplayer implements Runnable {
154        public void run() {
155            setContentView(R.layout.retry);
156            Button retryButton = (Button) findViewById(R.id.retryButton);
157            retryButton.setOnClickListener(new OnClickListener() {
158                public void onClick(View arg0) {
159                    // only run the installer if there isn't another one running
160                    // (we only get here if the installer couldn't complete successfully before)
161                    synchronized (sInstallerStateLock) {
162                        if (!sIsInstalling) {
163                            sIsInstalling = true;
164                            runInstaller();
165                        }
166                    }
167                }
168            });
169        }
170    }
171
172}
173