1package com.svox.langpack.installer;
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.net.Uri;
15import android.os.Bundle;
16import android.speech.tts.TextToSpeech;
17import android.util.Log;
18import android.view.View;
19import android.view.View.OnClickListener;
20import android.widget.Button;
21
22public class InstallerActivity extends Activity {
23    private static final int DATA_ROOT_DIRECTORY_REQUEST_CODE = 42;
24    private String rootDirectory = "";
25    private InstallerActivity self;
26    private static boolean sInstallationSuccess = false;
27    private static boolean sIsInstalling = false;
28    private final static Object sInstallerStateLock = new Object();
29
30    /** Called when the activity is first created. */
31    @Override
32    public void onCreate(Bundle savedInstanceState) {
33        super.onCreate(savedInstanceState);
34        self = this;
35        Intent getRootDirectoryIntent = new Intent();
36        getRootDirectoryIntent.setClassName("com.svox.pico", "com.svox.pico.CheckVoiceData");
37        startActivityForResult(getRootDirectoryIntent, DATA_ROOT_DIRECTORY_REQUEST_CODE);
38    }
39
40    @Override
41    public void onActivityResult(int requestCode, int resultCode, Intent data){
42        super.onActivityResult(requestCode, resultCode, data);
43        if (requestCode == DATA_ROOT_DIRECTORY_REQUEST_CODE) {
44            rootDirectory = data.getStringExtra(TextToSpeech.Engine.EXTRA_VOICE_DATA_ROOT_DIRECTORY);
45            // only run the installer if there isn't another one running
46            synchronized (sInstallerStateLock) {
47                if (!sIsInstalling && !sInstallationSuccess) {
48                    sIsInstalling = true;
49                    runInstaller();
50                }
51            }
52        }
53    }
54
55    private void runInstaller(){
56        try {
57            Resources res = getResources();
58            AssetFileDescriptor langPackFd = res
59                    .openRawResourceFd(R.raw.svoxlangpack);
60            InputStream stream = langPackFd.createInputStream();
61
62            (new Thread(new unzipper(stream))).start();
63        } catch (IOException e) {
64            Log.e("PicoLangInstaller", "Unable to open langpack resource.");
65            e.printStackTrace();
66        }
67        setContentView(R.layout.installing);
68    }
69
70
71    private boolean unzipLangPack(InputStream stream) {
72        FileOutputStream out;
73        byte buf[] = new byte[16384];
74        try {
75            ZipInputStream zis = new ZipInputStream(stream);
76            ZipEntry entry = zis.getNextEntry();
77            while (entry != null) {
78                if (entry.isDirectory()) {
79                    File newDir = new File(rootDirectory + entry.getName());
80                    newDir.mkdir();
81                } else {
82                    String name = entry.getName();
83                    File outputFile = new File(rootDirectory + name);
84                    String outputPath = outputFile.getCanonicalPath();
85                    name = outputPath
86                            .substring(outputPath.lastIndexOf("/") + 1);
87                    outputPath = outputPath.substring(0, outputPath
88                            .lastIndexOf("/"));
89                    File outputDir = new File(outputPath);
90                    outputDir.mkdirs();
91                    outputFile = new File(outputPath, name);
92                    outputFile.createNewFile();
93                    out = new FileOutputStream(outputFile);
94
95                    int numread = 0;
96                    do {
97                        numread = zis.read(buf);
98                        if (numread <= 0) {
99                            break;
100                        } else {
101                            out.write(buf, 0, numread);
102                        }
103                    } while (true);
104                    out.close();
105                }
106                entry = zis.getNextEntry();
107            }
108            return true;
109        } catch (IOException e) {
110            e.printStackTrace();
111            return false;
112        }
113    }
114
115    private class unzipper implements Runnable {
116        public InputStream stream;
117
118        public unzipper(InputStream is) {
119            stream = is;
120        }
121
122        public void run() {
123            boolean result = unzipLangPack(stream);
124            synchronized (sInstallerStateLock) {
125                sInstallationSuccess = result;
126                sIsInstalling = false;
127            }
128            if (sInstallationSuccess) {
129                // installation completed: signal success (extra set to SUCCESS)
130                Intent installCompleteIntent =
131                        new Intent(TextToSpeech.Engine.ACTION_TTS_DATA_INSTALLED);
132                installCompleteIntent.putExtra(TextToSpeech.Engine.EXTRA_TTS_DATA_INSTALLED,
133                        TextToSpeech.SUCCESS);
134                self.sendBroadcast(installCompleteIntent);
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