Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit a6cc9b85 authored by Niels Egberts's avatar Niels Egberts
Browse files

Markup support for framework

Change-Id: Ia5ad6cff7593c295944a90775a1b061c95f5cc3f
parent 55cef957
Loading
Loading
Loading
Loading
+105 −1
Original line number Original line Diff line number Diff line
@@ -26581,6 +26581,28 @@ package android.speech {
package android.speech.tts {
package android.speech.tts {
  public final class Markup implements android.os.Parcelable {
    ctor public Markup();
    ctor public Markup(java.lang.String);
    ctor public Markup(android.speech.tts.Markup);
    method public android.speech.tts.Markup addNestedMarkup(android.speech.tts.Markup);
    method public int describeContents();
    method public android.speech.tts.Markup getNestedMarkup(int);
    method public java.util.List<android.speech.tts.Markup> getNestedMarkups();
    method public java.lang.String getParameter(java.lang.String);
    method public java.lang.String getPlainText();
    method public java.lang.String getType();
    method public static android.speech.tts.Markup markupFromString(java.lang.String) throws java.lang.IllegalArgumentException;
    method public int nestedMarkupSize();
    method public int parametersSize();
    method public boolean removeNestedMarkup(android.speech.tts.Markup);
    method public void removeParameter(java.lang.String);
    method public android.speech.tts.Markup setParameter(java.lang.String, java.lang.String);
    method public void setPlainText(java.lang.String);
    method public void setType(java.lang.String);
    method public void writeToParcel(android.os.Parcel, int);
  }
  public final class RequestConfig {
  public final class RequestConfig {
    method public android.os.Bundle getAudioParams();
    method public android.os.Bundle getAudioParams();
    method public android.speech.tts.VoiceInfo getVoice();
    method public android.speech.tts.VoiceInfo getVoice();
@@ -26643,9 +26665,10 @@ package android.speech.tts {
  }
  }
  public final class SynthesisRequestV2 implements android.os.Parcelable {
  public final class SynthesisRequestV2 implements android.os.Parcelable {
    ctor public SynthesisRequestV2(java.lang.String, java.lang.String, java.lang.String, android.os.Bundle, android.os.Bundle);
    ctor public SynthesisRequestV2(android.speech.tts.Markup, java.lang.String, java.lang.String, android.os.Bundle, android.os.Bundle);
    method public int describeContents();
    method public int describeContents();
    method public android.os.Bundle getAudioParams();
    method public android.os.Bundle getAudioParams();
    method public android.speech.tts.Markup getMarkup();
    method public java.lang.String getText();
    method public java.lang.String getText();
    method public java.lang.String getUtteranceId();
    method public java.lang.String getUtteranceId();
    method public java.lang.String getVoiceName();
    method public java.lang.String getVoiceName();
@@ -26748,7 +26771,9 @@ package android.speech.tts {
    method public void queueAudio(android.net.Uri, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueAudio(android.net.Uri, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSilence(long, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSilence(long, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSpeak(java.lang.String, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSpeak(java.lang.String, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSpeak(android.speech.tts.Markup, android.speech.tts.TextToSpeechClient.UtteranceId, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSynthesizeToFile(java.lang.String, android.speech.tts.TextToSpeechClient.UtteranceId, java.io.File, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSynthesizeToFile(java.lang.String, android.speech.tts.TextToSpeechClient.UtteranceId, java.io.File, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void queueSynthesizeToFile(android.speech.tts.Markup, android.speech.tts.TextToSpeechClient.UtteranceId, java.io.File, android.speech.tts.RequestConfig, android.speech.tts.TextToSpeechClient.RequestCallbacks);
    method public void stop();
    method public void stop();
  }
  }
@@ -26822,6 +26847,85 @@ package android.speech.tts {
    method protected void onVoicesInfoChange();
    method protected void onVoicesInfoChange();
  }
  }
  public class Utterance {
    ctor public Utterance();
    method public android.speech.tts.Utterance append(android.speech.tts.Utterance.AbstractTts<? extends android.speech.tts.Utterance.AbstractTts<?>>);
    method public android.speech.tts.Utterance append(java.lang.String);
    method public android.speech.tts.Utterance append(int);
    method public android.speech.tts.Markup createMarkup();
    method public android.speech.tts.Utterance.AbstractTts<? extends android.speech.tts.Utterance.AbstractTts<?>> get(int);
    method public android.speech.tts.Utterance setNoWarningOnFallback(boolean);
    method public int size();
    method public static android.speech.tts.Utterance utteranceFromString(java.lang.String) throws java.lang.IllegalArgumentException;
    field public static final int ANIMACY_ANIMATE = 1; // 0x1
    field public static final int ANIMACY_INANIMATE = 2; // 0x2
    field public static final int ANIMACY_UNKNOWN = 0; // 0x0
    field public static final int CASE_ABLATIVE = 4; // 0x4
    field public static final int CASE_ACCUSATIVE = 2; // 0x2
    field public static final int CASE_DATIVE = 3; // 0x3
    field public static final int CASE_GENITIVE = 5; // 0x5
    field public static final int CASE_INSTRUMENTAL = 8; // 0x8
    field public static final int CASE_LOCATIVE = 7; // 0x7
    field public static final int CASE_NOMINATIVE = 1; // 0x1
    field public static final int CASE_UNKNOWN = 0; // 0x0
    field public static final int CASE_VOCATIVE = 6; // 0x6
    field public static final int GENDER_FEMALE = 3; // 0x3
    field public static final int GENDER_MALE = 2; // 0x2
    field public static final int GENDER_NEUTRAL = 1; // 0x1
    field public static final int GENDER_UNKNOWN = 0; // 0x0
    field public static final java.lang.String KEY_NO_WARNING_ON_FALLBACK = "no_warning_on_fallback";
    field public static final int MULTIPLICITY_DUAL = 2; // 0x2
    field public static final int MULTIPLICITY_PLURAL = 3; // 0x3
    field public static final int MULTIPLICITY_SINGLE = 1; // 0x1
    field public static final int MULTIPLICITY_UNKNOWN = 0; // 0x0
    field public static final java.lang.String TYPE_UTTERANCE = "utterance";
  }
  public static abstract class Utterance.AbstractTts {
    ctor protected Utterance.AbstractTts();
    ctor protected Utterance.AbstractTts(android.speech.tts.Markup);
    method public java.lang.String generatePlainText();
    method public android.speech.tts.Markup getMarkup();
    method protected java.lang.String getParameter(java.lang.String);
    method public java.lang.String getPlainText();
    method public java.lang.String getType();
    method protected C removeParameter(java.lang.String);
    method protected C setParameter(java.lang.String, java.lang.String);
    method public C setPlainText(java.lang.String);
    field protected android.speech.tts.Markup mMarkup;
  }
  public static abstract class Utterance.AbstractTtsSemioticClass extends android.speech.tts.Utterance.AbstractTts {
    ctor protected Utterance.AbstractTtsSemioticClass();
    ctor protected Utterance.AbstractTtsSemioticClass(android.speech.tts.Markup);
    method public int getAnimacy();
    method public int getCase();
    method public int getGender();
    method public int getMultiplicity();
    method public C setAnimacy(int);
    method public C setCase(int);
    method public C setGender(int);
    method public C setMultiplicity(int);
  }
  public static class Utterance.TtsCardinal extends android.speech.tts.Utterance.AbstractTtsSemioticClass {
    ctor public Utterance.TtsCardinal();
    ctor public Utterance.TtsCardinal(int);
    ctor public Utterance.TtsCardinal(java.lang.String);
    method public java.lang.String getInteger();
    method public android.speech.tts.Utterance.TtsCardinal setInteger(int);
    method public android.speech.tts.Utterance.TtsCardinal setInteger(java.lang.String);
    field protected static final java.lang.String TYPE_CARDINAL = "cardinal";
  }
  public static class Utterance.TtsText extends android.speech.tts.Utterance.AbstractTtsSemioticClass {
    ctor public Utterance.TtsText();
    ctor public Utterance.TtsText(java.lang.String);
    method public java.lang.String getText();
    method public android.speech.tts.Utterance.TtsText setText(java.lang.String);
    field protected static final java.lang.String TYPE_TEXT = "text";
  }
  public abstract class UtteranceProgressListener {
  public abstract class UtteranceProgressListener {
    ctor public UtteranceProgressListener();
    ctor public UtteranceProgressListener();
    method public abstract void onDone(java.lang.String);
    method public abstract void onDone(java.lang.String);
+537 −0

File added.

Preview size limit exceeded, changes collapsed.

+28 −10
Original line number Original line Diff line number Diff line
@@ -4,11 +4,12 @@ import android.os.Bundle;
import android.os.Parcel;
import android.os.Parcel;
import android.os.Parcelable;
import android.os.Parcelable;
import android.speech.tts.TextToSpeechClient.UtteranceId;
import android.speech.tts.TextToSpeechClient.UtteranceId;
import android.util.Log;


/**
/**
 * Service-side representation of a synthesis request from a V2 API client. Contains:
 * Service-side representation of a synthesis request from a V2 API client. Contains:
 * <ul>
 * <ul>
 *   <li>The utterance to synthesize</li>
 *   <li>The markup object to synthesize containing the utterance.</li>
 *   <li>The id of the utterance (String, result of {@link UtteranceId#toUniqueString()}</li>
 *   <li>The id of the utterance (String, result of {@link UtteranceId#toUniqueString()}</li>
 *   <li>The synthesis voice name (String, result of {@link VoiceInfo#getName()})</li>
 *   <li>The synthesis voice name (String, result of {@link VoiceInfo#getName()})</li>
 *   <li>Voice parameters (Bundle of parameters)</li>
 *   <li>Voice parameters (Bundle of parameters)</li>
@@ -16,8 +17,11 @@ import android.speech.tts.TextToSpeechClient.UtteranceId;
 * </ul>
 * </ul>
 */
 */
public final class SynthesisRequestV2 implements Parcelable {
public final class SynthesisRequestV2 implements Parcelable {
    /** Synthesis utterance. */

    private final String mText;
    private static final String TAG = "SynthesisRequestV2";

    /** Synthesis markup */
    private final Markup mMarkup;


    /** Synthesis id. */
    /** Synthesis id. */
    private final String mUtteranceId;
    private final String mUtteranceId;
@@ -34,9 +38,9 @@ public final class SynthesisRequestV2 implements Parcelable {
    /**
    /**
     * Constructor for test purposes.
     * Constructor for test purposes.
     */
     */
    public SynthesisRequestV2(String text, String utteranceId, String voiceName,
    public SynthesisRequestV2(Markup markup, String utteranceId, String voiceName,
            Bundle voiceParams, Bundle audioParams) {
            Bundle voiceParams, Bundle audioParams) {
        this.mText = text;
        this.mMarkup = markup;
        this.mUtteranceId = utteranceId;
        this.mUtteranceId = utteranceId;
        this.mVoiceName = voiceName;
        this.mVoiceName = voiceName;
        this.mVoiceParams = voiceParams;
        this.mVoiceParams = voiceParams;
@@ -49,15 +53,18 @@ public final class SynthesisRequestV2 implements Parcelable {
     * @hide
     * @hide
     */
     */
    public SynthesisRequestV2(Parcel in) {
    public SynthesisRequestV2(Parcel in) {
        this.mText = in.readString();
        this.mMarkup = (Markup) in.readValue(Markup.class.getClassLoader());
        this.mUtteranceId = in.readString();
        this.mUtteranceId = in.readString();
        this.mVoiceName = in.readString();
        this.mVoiceName = in.readString();
        this.mVoiceParams = in.readBundle();
        this.mVoiceParams = in.readBundle();
        this.mAudioParams = in.readBundle();
        this.mAudioParams = in.readBundle();
    }
    }


    SynthesisRequestV2(String text, String utteranceId, RequestConfig rconfig) {
    /**
        this.mText = text;
     * Constructor to request the synthesis of a sentence.
     */
    SynthesisRequestV2(Markup markup, String utteranceId, RequestConfig rconfig) {
        this.mMarkup = markup;
        this.mUtteranceId = utteranceId;
        this.mUtteranceId = utteranceId;
        this.mVoiceName = rconfig.getVoice().getName();
        this.mVoiceName = rconfig.getVoice().getName();
        this.mVoiceParams = rconfig.getVoiceParams();
        this.mVoiceParams = rconfig.getVoiceParams();
@@ -71,7 +78,7 @@ public final class SynthesisRequestV2 implements Parcelable {
     */
     */
    @Override
    @Override
    public void writeToParcel(Parcel dest, int flags) {
    public void writeToParcel(Parcel dest, int flags) {
        dest.writeString(mText);
        dest.writeValue(mMarkup);
        dest.writeString(mUtteranceId);
        dest.writeString(mUtteranceId);
        dest.writeString(mVoiceName);
        dest.writeString(mVoiceName);
        dest.writeBundle(mVoiceParams);
        dest.writeBundle(mVoiceParams);
@@ -82,7 +89,18 @@ public final class SynthesisRequestV2 implements Parcelable {
     * @return the text which should be synthesized.
     * @return the text which should be synthesized.
     */
     */
    public String getText() {
    public String getText() {
        return mText;
        if (mMarkup.getPlainText() == null) {
            Log.e(TAG, "Plaintext of markup is null.");
            return "";
        }
        return mMarkup.getPlainText();
    }

    /**
     * @return the markup which should be synthesized.
     */
    public Markup getMarkup() {
        return mMarkup;
    }
    }


    /**
    /**
+60 −7
Original line number Original line Diff line number Diff line
@@ -512,7 +512,6 @@ public class TextToSpeechClient {
        }
        }
    }
    }



    /**
    /**
     * Connects the client to TTS service. This method returns immediately, and connects to the
     * Connects the client to TTS service. This method returns immediately, and connects to the
     * service in the background.
     * service in the background.
@@ -876,7 +875,7 @@ public class TextToSpeechClient {
    private static final String ACTION_QUEUE_SPEAK_NAME = "queueSpeak";
    private static final String ACTION_QUEUE_SPEAK_NAME = "queueSpeak";


    /**
    /**
     * Speaks the string using the specified queuing strategy using current
     * Speaks the string using the specified queuing strategy and the current
     * voice. This method is asynchronous, i.e. the method just adds the request
     * voice. This method is asynchronous, i.e. the method just adds the request
     * to the queue of TTS requests and then returns. The synthesis might not
     * to the queue of TTS requests and then returns. The synthesis might not
     * have finished (or even started!) at the time when this method returns.
     * have finished (or even started!) at the time when this method returns.
@@ -887,12 +886,35 @@ public class TextToSpeechClient {
     *            in {@link RequestCallbacks}.
     *            in {@link RequestCallbacks}.
     * @param config Synthesis request configuration. Can't be null. Has to contain a
     * @param config Synthesis request configuration. Can't be null. Has to contain a
     *            voice.
     *            voice.
     * @param callbacks Synthesis request callbacks. If null, default request
     * @param callbacks Synthesis request callbacks. If null, the default request
     *            callbacks object will be used.
     *            callbacks object will be used.
     */
     */
    public void queueSpeak(final String utterance, final UtteranceId utteranceId,
    public void queueSpeak(final String utterance, final UtteranceId utteranceId,
            final RequestConfig config,
            final RequestConfig config,
            final RequestCallbacks callbacks) {
            final RequestCallbacks callbacks) {
        queueSpeak(createMarkupFromString(utterance), utteranceId, config, callbacks);
    }

    /**
     * Speaks the {@link Markup} (which can be constructed with {@link Utterance}) using
     * the specified queuing strategy and the current voice. This method is
     * asynchronous, i.e. the method just adds the request to the queue of TTS
     * requests and then returns. The synthesis might not have finished (or even
     * started!) at the time when this method returns.
     *
     * @param markup The Markup to be spoken. The written equivalent of the spoken
     *            text should be no longer than 1000 characters.
     * @param utteranceId Unique identificator used to track the synthesis progress
     *            in {@link RequestCallbacks}.
     * @param config Synthesis request configuration. Can't be null. Has to contain a
     *            voice.
     * @param callbacks Synthesis request callbacks. If null, the default request
     *            callbacks object will be used.
     */
    public void queueSpeak(final Markup markup,
            final UtteranceId utteranceId,
            final RequestConfig config,
            final RequestCallbacks callbacks) {
        runAction(new Action(ACTION_QUEUE_SPEAK_NAME) {
        runAction(new Action(ACTION_QUEUE_SPEAK_NAME) {
            @Override
            @Override
            public void run(ITextToSpeechService service) throws RemoteException {
            public void run(ITextToSpeechService service) throws RemoteException {
@@ -908,7 +930,7 @@ public class TextToSpeechClient {


                int queueResult = service.speakV2(
                int queueResult = service.speakV2(
                        getCallerIdentity(),
                        getCallerIdentity(),
                        new SynthesisRequestV2(utterance, utteranceId.toUniqueString(), config));
                        new SynthesisRequestV2(markup, utteranceId.toUniqueString(), config));
                if (queueResult != Status.SUCCESS) {
                if (queueResult != Status.SUCCESS) {
                    removeCallbackAndErr(utteranceId.toUniqueString(), queueResult);
                    removeCallbackAndErr(utteranceId.toUniqueString(), queueResult);
                }
                }
@@ -931,12 +953,37 @@ public class TextToSpeechClient {
     * @param outputFile File to write the generated audio data to.
     * @param outputFile File to write the generated audio data to.
     * @param config Synthesis request configuration. Can't be null. Have to contain a
     * @param config Synthesis request configuration. Can't be null. Have to contain a
     *            voice.
     *            voice.
     * @param callbacks Synthesis request callbacks. If null, default request
     * @param callbacks Synthesis request callbacks. If null, the default request
     *            callbacks object will be used.
     *            callbacks object will be used.
     */
     */
    public void queueSynthesizeToFile(final String utterance, final UtteranceId utteranceId,
    public void queueSynthesizeToFile(final String utterance, final UtteranceId utteranceId,
            final File outputFile, final RequestConfig config,
            final File outputFile, final RequestConfig config,
            final RequestCallbacks callbacks) {
            final RequestCallbacks callbacks) {
        queueSynthesizeToFile(createMarkupFromString(utterance), utteranceId, outputFile, config, callbacks);
    }

    /**
     * Synthesizes the given {@link Markup} (can be constructed with {@link Utterance})
     * to a file using the specified parameters. This method is asynchronous, i.e. the
     * method just adds the request to the queue of TTS requests and then returns. The
     * synthesis might not have finished (or even started!) at the time when this method
     * returns.
     *
     * @param markup The Markup that should be synthesized. The written equivalent of
     *            the spoken text should be no longer than 1000 characters.
     * @param utteranceId Unique identificator used to track the synthesis progress
     *            in {@link RequestCallbacks}.
     * @param outputFile File to write the generated audio data to.
     * @param config Synthesis request configuration. Can't be null. Have to contain a
     *            voice.
     * @param callbacks Synthesis request callbacks. If null, the default request
     *            callbacks object will be used.
     */
    public void queueSynthesizeToFile(
            final Markup markup,
            final UtteranceId utteranceId,
            final File outputFile, final RequestConfig config,
            final RequestCallbacks callbacks) {
        runAction(new Action(ACTION_QUEUE_SYNTHESIZE_TO_FILE) {
        runAction(new Action(ACTION_QUEUE_SYNTHESIZE_TO_FILE) {
            @Override
            @Override
            public void run(ITextToSpeechService service) throws RemoteException {
            public void run(ITextToSpeechService service) throws RemoteException {
@@ -964,8 +1011,7 @@ public class TextToSpeechClient {


                    int queueResult = service.synthesizeToFileDescriptorV2(getCallerIdentity(),
                    int queueResult = service.synthesizeToFileDescriptorV2(getCallerIdentity(),
                            fileDescriptor,
                            fileDescriptor,
                            new SynthesisRequestV2(utterance, utteranceId.toUniqueString(),
                            new SynthesisRequestV2(markup, utteranceId.toUniqueString(), config));
                                    config));
                    fileDescriptor.close();
                    fileDescriptor.close();
                    if (queueResult != Status.SUCCESS) {
                    if (queueResult != Status.SUCCESS) {
                        removeCallbackAndErr(utteranceId.toUniqueString(), queueResult);
                        removeCallbackAndErr(utteranceId.toUniqueString(), queueResult);
@@ -981,6 +1027,13 @@ public class TextToSpeechClient {
        });
        });
    }
    }


    private static Markup createMarkupFromString(String str) {
        return new Utterance()
            .append(new Utterance.TtsText(str))
            .setNoWarningOnFallback(true)
            .createMarkup();
    }

    private static final String ACTION_QUEUE_SILENCE_NAME = "queueSilence";
    private static final String ACTION_QUEUE_SILENCE_NAME = "queueSilence";


    /**
    /**
+49 −4
Original line number Original line Diff line number Diff line
@@ -352,6 +352,12 @@ public abstract class TextToSpeechService extends Service {
            params.putString(TextToSpeech.Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS, "true");
            params.putString(TextToSpeech.Engine.KEY_FEATURE_EMBEDDED_SYNTHESIS, "true");
        }
        }


        String noWarning = request.getMarkup().getParameter(Utterance.KEY_NO_WARNING_ON_FALLBACK);
        if (noWarning == null || noWarning.equals("false")) {
            Log.w("TextToSpeechService", "The synthesis engine does not support Markup, falling " +
                                         "back to the given plain text.");
        }

        // Build V1 request
        // Build V1 request
        SynthesisRequest requestV1 = new SynthesisRequest(request.getText(), params);
        SynthesisRequest requestV1 = new SynthesisRequest(request.getText(), params);
        Locale locale = selectedVoice.getLocale();
        Locale locale = selectedVoice.getLocale();
@@ -856,14 +862,53 @@ public abstract class TextToSpeechService extends Service {
            }
            }
        }
        }


        /**
         * Estimate of the character count equivalent of a Markup instance. Calculated
         * by summing the characters of all Markups of type "text". Each other node
         * is counted as a single character, as the character count of other nodes
         * is non-trivial to calculate and we don't want to accept arbitrarily large
         * requests.
         */
        private int estimateSynthesisLengthFromMarkup(Markup m) {
            int size = 0;
            if (m.getType() != null &&
                m.getType().equals("text") &&
                m.getParameter("text") != null) {
                size += m.getParameter("text").length();
            } else if (m.getType() == null ||
                       !m.getType().equals("utterance")) {
                size += 1;
            }
            for (Markup nested : m.getNestedMarkups()) {
                size += estimateSynthesisLengthFromMarkup(nested);
            }
            return size;
        }

        @Override
        @Override
        public boolean isValid() {
        public boolean isValid() {
            if (mSynthesisRequest.getText() == null) {
            if (mSynthesisRequest.getMarkup() == null) {
                Log.e(TAG, "null synthesis text");
                Log.e(TAG, "No markup in request.");
                return false;
                return false;
            }
            }
            if (mSynthesisRequest.getText().length() >= TextToSpeech.getMaxSpeechInputLength()) {
            String type = mSynthesisRequest.getMarkup().getType();
                Log.w(TAG, "Text too long: " + mSynthesisRequest.getText().length() + " chars");
            if (type == null) {
                Log.w(TAG, "Top level markup node should have type \"utterance\", not null");
                return false;
            } else if (!type.equals("utterance")) {
                Log.w(TAG, "Top level markup node should have type \"utterance\" instead of " +
                            "\"" + type + "\"");
                return false;
            }

            int estimate = estimateSynthesisLengthFromMarkup(mSynthesisRequest.getMarkup());
            if (estimate >= TextToSpeech.getMaxSpeechInputLength()) {
                Log.w(TAG, "Text too long: estimated size of text was " + estimate + " chars.");
                return false;
            }

            if (estimate <= 0) {
                Log.e(TAG, "null synthesis text");
                return false;
                return false;
            }
            }


Loading