Android Question How to run JavaObject for "public class xxx implements xxx"?

watesoft

Active Member
Licensed User
Longtime User
I have an aar file that can convert text into multiple dialects, I tested it in Android Studio and it works fine, but when I run in B4A with JavaObject, there is no error, but there is no sound.
The entry class is not an ordinary class, it implements SynthesisCallback (import android.speech.tts.SynthesisCallback, I think the problem should be here, I want to use JavaObject, but don't know how to do it,my code is as follows:

In Java:
Entry class:
import android.annotation.SuppressLint;
import android.content.Context;
import android.media.AudioFormat;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.SystemClock;
import android.speech.tts.SynthesisCallback;
import android.util.Log;

import com.iflytek.business.SpeechConfig;
import com.iflytek.speechcloud.TtsService;

import java.util.Queue;
import java.util.concurrent.ConcurrentLinkedQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class TTS implements SynthesisCallback {
    private ExecutorService executorService;
    private AudioTrack audioTrack;
    private TtsService ttsService;
    @SuppressLint("StaticFieldLeak")
    private static volatile TTS singleton;
    private volatile int rate = 100;
    private volatile int tone = 8000;
    private Context context;
    private volatile boolean loop = true;
    private Queue<String> textQueue;
    private volatile String text = null;
    private volatile boolean isFlush = false;

    public static TTS getInstance() {
        if (singleton == null) {
            synchronized (TTS.class) {
                if (singleton == null) {
                    singleton = new TTS();
                }
            }
        }
        return singleton;
    }

    public TTS() {
        if (textQueue == null)
            textQueue = new ConcurrentLinkedQueue<>();
        if (executorService == null)
            executorService = Executors.newFixedThreadPool(2);
        if (audioTrack == null) {
            audioTrack = new AudioTrack(AudioManager.STREAM_MUSIC,
                    16000,
                    AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT,
                    AudioTrack.getMinBufferSize(16000, AudioFormat.CHANNEL_OUT_STEREO, AudioFormat.ENCODING_PCM_16BIT)
                    , AudioTrack.MODE_STREAM);
            audioTrack.play();
        }
        executorService.execute(() -> {
            while (loop) {
                text = textQueue.poll();
                if (text != null) {
                    ttsService.onSynthesizeText(text, rate, this);
                }
                SystemClock.sleep(50L);
            }
        });
    }

    public void init(Context context, String speaker, int rate, int tone) {
        setRate(rate);
        setTone(tone);
        init(context, speaker);
    }

    public void init(Context context, String speaker) {
        this.context = context.getApplicationContext();
        SpeechConfig.putString(this.context, SpeechConfig.KEY_SPEAKER_SETTING, speaker);
        if (ttsService == null) {
            ttsService = new TtsService();
            ttsService.onCreate(this.context);
        }

    }

    public void init(Context context) {
        init(context,TTSConstants.TTS_XIAOFENG);
    }

    public void speakText(String text) {
       textQueue.offer(text);
       audioTrack.play();

    }
  
  
    @Override
    public int getMaxBufferSize() {
        return 0;
    }

    @Override
    public int start(int sampleRateInHz, int audioFormat, int channelCount) {
        return 0;
    }

    @Override
    public int audioAvailable(byte[] buffer, int offset, int length) {
        audioTrack.setPlaybackRate(tone);
        audioTrack.write(buffer, offset, length);
        return 0;
    }

    @Override
    public int done() {
        return 0;
    }


    @Override
    public boolean hasStarted() {
        return false;
    }

    @Override
    public boolean hasFinished() {
        return false;
    }

    public int getRate() {
        return rate;
    }

    public void setRate(int rate) {
        this.rate = rate;
    }

    public int getTone() {
        return tone;
    }

    public void setTone(int tone) {
        this.tone = tone;
    }
}

In B4A:
Play:
#AdditionalJar:xftts.aar

Sub Process_Globals
    Private xui As XUI
End Sub

Sub Activity_Create(FirstTime As Boolean)
    Activity.LoadLayout("Layout")
    GetTTS.RunMethodJO("init", Array(GetContext))
End Sub

Sub Activity_Resume

End Sub

Sub GetTTS As JavaObject
    Dim jo As JavaObject
    Return jo.InitializeNewInstance("com.iflytek.TTS",Null).RunMethodJO("getInstance", Null)
End Sub

Sub GetContext As JavaObject
    Return GetBA.GetField("context")
End Sub

Sub GetBA As JavaObject
    Dim jo As JavaObject
    Dim cls As String = Me
    cls = cls.SubString("class ".Length)
    jo.InitializeStatic(cls)
    Return jo.GetFieldJO("processBA")
End Sub

Sub Button1_Click
    Dim ttt As String
    ttt="this is test"
    GetTTS.RunMethodJO("speakText", Array(ttt))
End Sub

I have spent a lot of time looking for the reason, hope to get your help, thanks in advance.
Sorry, don't move to "Libraries developers questions", where almost nobody noticed.
 
Last edited:
Solution
Have you tried InitializeStatic instead of InitializeNewInstance? From the source code 'getInstance' is a static method and should be called on the class. I don'tknow why you don't get an error though.
Thank you agraham,I hava tried InitializeStatic instead of InitializeNewInstance,again no errors and no sound.
The same aar file,there is no problem with Android Studio connecting the device to debug via USB, or generating apk for installation.this is a very miraculous thing.

watesoft

Active Member
Licensed User
Longtime User
Have you tried InitializeStatic instead of InitializeNewInstance? From the source code 'getInstance' is a static method and should be called on the class. I don'tknow why you don't get an error though.
Thank you agraham,I hava tried InitializeStatic instead of InitializeNewInstance,again no errors and no sound.
The same aar file,there is no problem with Android Studio connecting the device to debug via USB, or generating apk for installation.this is a very miraculous thing.
 
Upvote 0
Solution

watesoft

Active Member
Licensed User
Longtime User
The problem is solved, there is a switch in Logs, Unchecked it, more debugging information can be found. I know this feature for the first time.
 
Upvote 0
Cookies are required to use this site. You must accept them to continue using the site. Learn more…