Auto download offline speech recognition language

2019-04-18 22:23发布

Is there any way in Java to detect if an Android device has an offline speech recognition language installed, and if it does not prompt the user to download it?

I know you can ask to speech to text to prefer offline speech to text, but how do you know if the device has the language installed?

This question is not on how to use offline speech, this works. The question is "how to detect and download/install offline speech languages" from Java app code. i.e. have the app detect if they have offline German language installed, and if not prompt the user to download/install it.

3条回答
贪生不怕死
2楼-- · 2019-04-18 22:59

This is not the answer you are hoping for, as at the time of writing, I don't believe there is a straight forward solution to this. I very much hope to be proved wrong.

I requested an enhancement to provide this information programmatically a long time ago - here

The enhancement suggested an additional parameter RecognizerIntent.EXTRA_SUPPORTED_OFFLINE_LANGUAGES:

It would surely be trivial for this to be added and used in the following way:

final Intent vrIntent = new Intent(RecognizerIntent.ACTION_GET_LANGUAGE_DETAILS);
getContext().sendOrderedBroadcast(vrIntent, null, new BroadcastReceiver() {

    @Override
    public void onReceive(final Context context, final Intent intent) {

        final ArrayList<String> vrStringLocales = intent.getExtras().getStringArrayList(
                RecognizerIntent.EXTRA_SUPPORTED_LANGUAGES);

        // This would be nice
        final ArrayList<String> vrStringOfflineLocales = intent.getExtras().getStringArrayList(
                RecognizerIntent.EXTRA_SUPPORTED_OFFLINE_LANGUAGES);
    }

}, null, 1234, null, null);

Alas, it has never happened.

You do have two other options to attempt to handle this gracefully.

In the unlikely event you application runs with root permissions, you can check the location of /data/data/com.google.android.googlequicksearchbox/app_g3_models/ which contains the offline files, labelled quite handily by their locale.

The second involves knowing when the user needs a prompt to install the missing offline files.

From my experience, the recognition error of SpeechRecognizer.ERROR_SERVER most often denotes this, but it is not foolproof.

@Override
public void onError(final int error) {

    switch (error) {

        case SpeechRecognizer.ERROR_SERVER:
            // TODO - prompt to install offline files
            break;
    }
}

When detected, you can guide the user to the correct installation screen.

public static final String PACKAGE_NAME_GOOGLE_NOW = "com.google.android.googlequicksearchbox";
public static final String ACTIVITY_INSTALL_OFFLINE_FILES = "com.google.android.voicesearch.greco3.languagepack.InstallActivity";

public static boolean showInstallOfflineVoiceFiles(@NonNull final Context ctx) {

    final Intent intent = new Intent();
    intent.setComponent(new ComponentName(PACKAGE_NAME_GOOGLE_NOW, ACTIVITY_INSTALL_OFFLINE_FILES));

    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_CLEAR_TOP);

    try {
        ctx.startActivity(intent);
        return true;
    } catch (final ActivityNotFoundException e) {

    } catch (final Exception e) {

    }

    return false;
}

Using hard-coded values such as this, is of course not ideal, but neither is this situation!

Once you've messed around with all of the above and think you have a good interim solution - think again! Regardless of whether the user has correctly installed the missing offline files, it is highly likely it still won't work.....

My answer here describes the process I still have to guide my user's with. It's very frustrating.

Finally one more bug to throw into the mix - RecognitionListener.onError(int) can be thrown when there isn't an error. Check my gist from the answer here to use a BugRecognitionListener so you can check the callbacks are being sent in the correct order and ignore those that aren't. This remains a problem, despite my answer suggesting a fix in a previous release.

The above should keep you busy! Good luck....

查看更多
神经病院院长
3楼-- · 2019-04-18 23:07

To detect whether needed Language(German) is available, please follow below :

  • Iterate the Locale list and check whether Locale available for German language.

  • If you didn't get any Locale object in return, you can conclude that German language is not available offline. Then you can write code to download and do other stuff.

  • I did below implementation for my project. Hope below code helps you !!!

    private TextToSpeech t1;
    
    private void setForOtherLangAudio() {
    Locale[] locales = Locale.getAvailableLocales();
    Locale loc = null;
    for (Locale locale : locales) {
      // Replace XXX with your German codes
      if (locale.getDisplayCountry().equals("XXX") &&   locale.getDisplayLanguage().equals("XXX")) {
        loc = locale ;
        break;
    }
    }
    final Locale germanLocale = loc;
    t1 = new TextToSpeech(getContext(), new TextToSpeech.OnInitListener() {
        @Override
        public void onInit(int status) {
            if (status != TextToSpeech.ERROR) {
                t1.setLanguage(germanLocale);
            }
        }
    });
    

    }

查看更多
登录 后发表回答