1/*
2 * Copyright (C) 2011 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16package com.example.android.ttsengine;
17
18import android.app.Activity;
19import android.content.Intent;
20import android.os.Bundle;
21import android.speech.tts.TextToSpeech;
22import android.text.TextUtils;
23import android.util.Log;
24
25import java.io.IOException;
26import java.io.InputStream;
27import java.util.ArrayList;
28import java.util.Arrays;
29import java.util.List;
30
31/*
32 * Checks if the voice data is present.
33 */
34public class CheckVoiceData extends Activity {
35    private static final String TAG = "CheckVoiceData";
36
37    private static final String[] SUPPORTED_LANGUAGES = { "eng-GBR", "eng-USA" };
38
39    @Override
40    protected void onCreate(Bundle savedInstanceState) {
41        super.onCreate(savedInstanceState);
42
43        Intent intent = getIntent();
44        List<String> checkLanguages = getCheckVoiceDataFor(intent);
45
46        // If the call didn't specify which languages to check, check
47        // for all the supported ones.
48        if (checkLanguages.isEmpty()) {
49            checkLanguages = Arrays.asList(SUPPORTED_LANGUAGES);
50        }
51
52        ArrayList<String> available = new ArrayList<String>();
53        ArrayList<String> unavailable = new ArrayList<String>();
54
55        for (String lang : checkLanguages) {
56            // This check is required because checkLanguages might contain
57            // an arbitrary list of languages if the intent specified them
58            // {@link #getCheckVoiceDataFor}.
59            if (isLanguageSupported(lang)) {
60                if (isDataInstalled(lang)) {
61                    available.add(lang);
62                } else {
63                    unavailable.add(lang);
64                }
65            }
66        }
67
68        int result;
69        if (!checkLanguages.isEmpty() && available.isEmpty()) {
70            // No voices available at all.
71            result = TextToSpeech.Engine.CHECK_VOICE_DATA_FAIL;
72        } else if (!unavailable.isEmpty()) {
73            // Some voices are available, but some have missing
74            // data.
75            result = TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA;
76        } else {
77            // All voices are available.
78            result = TextToSpeech.Engine.CHECK_VOICE_DATA_PASS;
79        }
80
81        // We now return the list of available and unavailable voices
82        // as well as the return code.
83        Intent returnData = new Intent();
84        returnData.putStringArrayListExtra(
85                TextToSpeech.Engine.EXTRA_AVAILABLE_VOICES, available);
86        returnData.putStringArrayListExtra(
87                TextToSpeech.Engine.EXTRA_UNAVAILABLE_VOICES, unavailable);
88        setResult(result, returnData);
89        finish();
90    }
91
92    /**
93     * The intent that launches this activity can contain an intent extra
94     * {@link TextToSpeech.Engine.EXTRA_CHECK_VOICE_DATA_FOR} that might specify
95     * a given language to check voice data for. If the intent does not contain
96     * this extra, we assume that a voice check for all supported languages
97     * was requested.
98     */
99    private List<String> getCheckVoiceDataFor(Intent intent) {
100        ArrayList<String> list = intent.getStringArrayListExtra(
101                TextToSpeech.Engine.EXTRA_CHECK_VOICE_DATA_FOR);
102        ArrayList<String> ret = new ArrayList<String>();
103        if (list != null) {
104            for (String lang : list) {
105                if (!TextUtils.isEmpty(lang)) {
106                    ret.add(lang);
107                }
108            }
109        }
110        return ret;
111    }
112
113    /**
114     * Checks whether a given language is in the list of supported languages.
115     */
116    private boolean isLanguageSupported(String input) {
117        for (String lang : SUPPORTED_LANGUAGES) {
118            if (lang.equals(input)) {
119                return true;
120            }
121        }
122
123        return false;
124    }
125
126    /*
127     * Note that in our example, all data is packaged in our APK as
128     * assets (it could be a raw resource as well). This check is unnecessary
129     * because it will always succeed.
130     *
131     * If for example, engine data was downloaded or installed on external storage,
132     * this check would make much more sense.
133     */
134    private boolean isDataInstalled(String lang) {
135        try {
136            InputStream is = getAssets().open(lang + ".freq");
137
138            if (is != null) {
139                is.close();
140            } else {
141                return false;
142            }
143        } catch (IOException e) {
144            Log.w(TAG, "Unable to find data for: " + lang + ", exception: " + e);
145            return false;
146        }
147
148        // The asset InputStream was non null, and therefore this
149        // data file is available.
150        return true;
151    }
152}
153