1

I've written a simple text-to-speech app. But in some mobile with more than one tts engine, Even though the choice of the tts engine within my code, the tts engine selection popup opens again!!

How can I avoid it from opening?

my code is here:

onCreate():

String GOOGLE_TTS_PACKAGE = "com.google.android.tts";

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    // Fire off an intent to check if a TTS engine is installed
    Intent intent = new Intent();
    intent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
    startActivityForResult(intent, MY_TTS_DATA_CHECK_CODE);

    mButtonSpeak.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {
            speak();
        }
    });
}

onActivityResult():

 @Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
    if (requestCode == MY_TTS_DATA_CHECK_CODE) {
        if (resultCode == TextToSpeech.Engine.CHECK_VOICE_DATA_PASS) {
            // success, create the TTS instance
            Log.e(TTS_TAG,"Already VOICE_DATA Installed, create the TTS instance");

            mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {
                @Override
                public void onInit(int status) {
                    if (status == TextToSpeech.ERROR) {
                        Log.e(TTS_TAG, "Initialize failed");
                    } else {
                        int result = mTTS.setLanguage(Locale.US);

                        if (result == TextToSpeech.LANG_NOT_SUPPORTED
                                || result == TextToSpeech.LANG_MISSING_DATA) {
                            Log.e(TTS_TAG, "Language not supported");
                        } else {
                            mButtonSpeak.setEnabled(true);
                        }
                    }
                }
            }, GOOGLE_TTS_PACKAGE);
        } else {
            // missing data, install it
            Log.e(TTS_TAG,"missing data, install it");
            Intent installIntent = new Intent();
            installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
            try {
                Log.e(TTS_TAG, "Installing voice data: " + installIntent.toUri(0));
                startActivity(installIntent);
            } catch (ActivityNotFoundException ex) {
                Log.e(TTS_TAG, "Failed to install TTS data, no activity found for " + installIntent + ")");
            }
        }
    }
}

onDestroy():

@Override
protected void onDestroy() {
    super.onDestroy();

    if (mTTS != null) {
        mTTS.stop();
        mTTS.shutdown();
    }
}

As you can see, inside the TExtToSpeech constructor, the package name is specified.

please help me

UPDATE 1: In this app, in any case, Google TTS will work in the app, even if the user chooses any other engine!

UPDATE 2: I understand that this happens because I've used the startActivityForResult() and onActivityResult(). Does anyone have a solution to solve this problem?

UPDATE 3: When using the Google TTS in the app, and When a specific language is needed (e.g turkish), the files of this language will be downloaded automatically. But if the device is not connected to the Internet, it will remain in download mode. How and under what condition can I control this problem and give the user a message to turn on the Internet?

roghayeh hosseini
  • 676
  • 1
  • 8
  • 21

2 Answers2

0

You should not need to use startActivityForResult.

If you only want to use the Google TTS, then just check for it specifically, and prompt an install if it is absent.

Also... if certain languages are missing, you can have an alert dialog which sends the user to the general TTS settings where they can install the missing language.

These three methods should help you:

private boolean isGoogleTTSInstalled() {

        Intent ttsIntent = new Intent();
        ttsIntent.setAction(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
        PackageManager pm = this.getPackageManager();
        List<ResolveInfo> listOfInstalledTTSInfo = pm.queryIntentActivities(ttsIntent, PackageManager.GET_META_DATA);
        for (ResolveInfo r : listOfInstalledTTSInfo) {
            String engineName = r.activityInfo.applicationInfo.packageName;
            if (engineName.equals(GOOGLE_TTS_PACKAGE)) {
                return true;
            }
        }
        return false;

    }

private void installGoogleTTS() {

        Intent goToMarket = new Intent(Intent.ACTION_VIEW)
                .setData(Uri.parse("market://details?id=com.google.android.tts"));
        startActivity(goToMarket);

    }

private void openTTSSettingsToInstallUnsupportedLanguage() {

        Intent intent = new Intent();
        intent.setAction("com.android.settings.TTS_SETTINGS");
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);

    }
Nerdy Bunz
  • 6,040
  • 10
  • 41
  • 100
  • tnx. Can I use listOfInstalledTTSInfo for check if any TTS engine is installed on device? (by if(listOfInstalledTTSInfo==null)) – roghayeh hosseini Dec 09 '18 at 12:41
  • I don't know -- you would have to test it on a device with no tts installed. It might not be null, but I think the size would be zero. It's confusing to me why you would ask that question when you specifically said you were only interested in positively identifying the Google engine. – Nerdy Bunz Dec 09 '18 at 20:39
  • When using the Google TTS in the app, and When a specific language is needed (e.g turkish), the files of this language will be downloaded automatically. But if the device is not connected to the Internet, it will remain in download mode. How and under what condition can I control this problem and give the user a message to turn on the Internet? – roghayeh hosseini Dec 10 '18 at 07:31
  • I asked the same question: https://stackoverflow.com/questions/50962724/how-to-predict-failure-of-google-text-to-speech – Nerdy Bunz Dec 10 '18 at 08:21
0

As far as I've tested in different modes, whenever no TTS engine is installed or disabled, the status==TextToSpeech.ERROR will occur.

So you do not need to check this before onInit().

String GOOGLE_TTS_PACKAGE = "com.google.android.tts"

mTTS = new TextToSpeech(this, new TextToSpeech.OnInitListener() {

            @Override
            public void onInit(int status) {
                if (status == TextToSpeech.ERROR) {
                    Log.e(TTS_TAG, "TTS initialize failed");
                    // Open play store if user have'nt installed or disable google TTS
                    installGoogleTTS();
                } else {
                    // Set engine for tts
                    if (isPackageInstalled(getPackageManager(), GOOGLE_TTS_PACKAGE)) {
                        mTTS.setEngineByPackageName(GOOGLE_TTS_PACKAGE);
                    }

                    int result = mTTS.setLanguage(Locale.US);

                    if (result == TextToSpeech.LANG_NOT_SUPPORTED
                            || result == TextToSpeech.LANG_MISSING_DATA) {
                        Log.e(TTS_TAG, "Language not supported");
                    } else {
                        mButtonSpeak.setEnabled(true);
                    }
                }
            }
        });

I also used this function to control the Google service being installed, before set engine for mTTS:

public static boolean isPackageInstalled(PackageManager pm, String packageName) {
    try {
        pm.getPackageInfo(packageName, 0);
    } catch (PackageManager.NameNotFoundException e) {
        return false;
    }
    return true;
}

and this for install Google TTS:

private void installGoogleTTS() {
    try {
        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("market://details?id=" + GOOGLE_TTS_PACKAGE)));
    } catch (android.content.ActivityNotFoundException anfe) {
        startActivity(new Intent(Intent.ACTION_VIEW, Uri.parse("https://play.google.com/store/apps/details?id=" + GOOGLE_TTS_PACKAGE)));
    }
}

also You can display the dialog before install the Google TTS.

roghayeh hosseini
  • 676
  • 1
  • 8
  • 21