Hello everybody.
I have a question about inline java and classes.
In summary.
I need to make an app in B4J that listens to the microphone so I can use it with the VOSK right after.
The objective is to listen to the microphone with inline java and pass the stream to b4j.
However, I am experiencing some errors when trying.
Error
if I try to use static.
How can I use inline java, have classes in java and at the same time be able to return values to subs in b4j
Obs: I know that there are already recording libraries in b4j, but this question is about inline java/class and subs.
Thx
I have a question about inline java and classes.
In summary.
I need to make an app in B4J that listens to the microphone so I can use it with the VOSK right after.
The objective is to listen to the microphone with inline java and pass the stream to b4j.
However, I am experiencing some errors when trying.
B4X:
Sub Inicia_Java
Dim thisClass As String = (Me).As(JavaObject).RunMethod("getClass",Null)
jo.InitializeNewInstance(thisClass.Replace("class ","") & "$" & "AudioCapture",Null)
StartRecording
End Sub
Sub StartRecording
jo.RunMethod("startRecording", Null)
End Sub
Sub StopRecording
jo.RunMethod("stopRecording", Null)
End Sub
#if java
import javax.sound.sampled.*;
import java.io.ByteArrayOutputStream;
public class AudioCapture {
public AudioCapture() {
// inicialização necessária
}
private TargetDataLine line;
private boolean running = false;
public void startRecording() {
try {
AudioFormat format = new AudioFormat(16000, 16, 1, true, false);
DataLine.Info info = new DataLine.Info(TargetDataLine.class, format);
if (!AudioSystem.isLineSupported(info)) {
subQvEvent("logs", "Line not supported");
return;
}
line = (TargetDataLine) AudioSystem.getLine(info);
line.open(format);
line.start();
running = true;
new Thread(() -> {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] buffer = new byte[1024];
while (running) {
int numRead = line.read(buffer, 0, buffer.length);
if (numRead > 0) {
out.write(buffer, 0, numRead);
}
}
line.drain();
line.close();
subQvEvent("audio_data", out.toByteArray());
}).start();
} catch (LineUnavailableException e) {
subQvEvent("logs", "Line unavailable: " + e.getMessage());
}
}
public void stopRecording() {
running = false;
}
private void subQvEvent(String eventName, Object data) {
getBA().raiseEventFromDifferentThread(null, null, 0, eventName.toLowerCase() + "_qv", true, new Object[]{data});
}
}
#end if
Sub audio_data(data() As Byte)
Log("Received audio data of length: " & data.Length)
End Sub
Sub logs(message As String)
Log(message)
End Sub
Error
WARNING: package com.sun.javafx.embed.swing.oldimpl not in javafx.swing
Waiting for debugger to connect...
Program started.
Error occurred on line: 58 (B4XMainPage)
java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at anywheresoftware.b4a.keywords.Common.CallSubDebug2(Common.java:486)
at teste.app.b4xpagesmanager._createpageifneeded(b4xpagesmanager.java:872)
at teste.app.b4xpagesmanager._showpage(b4xpagesmanager.java:351)
at teste.app.b4xpagesmanager._addpage(b4xpagesmanager.java:172)
at teste.app.b4xpagesmanager._addpageandcreate(b4xpagesmanager.java:186)
at teste.app.b4xpagesmanager._initialize(b4xpagesmanager.java:122)
at teste.app.main._appstart(main.java:80)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at anywheresoftware.b4a.shell.Shell.runMethod(Shell.java:629)
at anywheresoftware.b4a.shell.Shell.raiseEventImpl(Shell.java:237)
at anywheresoftware.b4a.shell.Shell.raiseEvent(Shell.java:167)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at anywheresoftware.b4a.BA.raiseEvent2(BA.java:111)
at anywheresoftware.b4a.shell.ShellBA.raiseEvent2(ShellBA.java:100)
at anywheresoftware.b4a.BA.raiseEvent(BA.java:98)
at teste.app.main.start(main.java:38)
at javafx.graphics/com.sun.javafx.application.LauncherImpl.lambda$launchApplication1$9(LauncherImpl.java:846)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runAndWait$12(PlatformImpl.java:455)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$10(PlatformImpl.java:428)
at java.base/java.security.AccessController.doPrivileged(AccessController.java:391)
at javafx.graphics/com.sun.javafx.application.PlatformImpl.lambda$runLater$11(PlatformImpl.java:427)
at javafx.graphics/com.sun.glass.ui.InvokeLaterDispatcher$Future.run(InvokeLaterDispatcher.java:96)
at javafx.graphics/com.sun.glass.ui.win.WinApplication._runLoop(Native Method)
at javafx.graphics/com.sun.glass.ui.win.WinApplication.lambda$runLoop$3(WinApplication.java:174)
at java.base/java.lang.Thread.run(Thread.java:832)
Caused by: java.lang.RuntimeException: java.lang.reflect.InvocationTargetException
at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:134)
at anywheresoftware.b4a.debug.Debug.CallSubNew2(Debug.java:81)
... 35 more
Caused by: java.lang.reflect.InvocationTargetException
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at java.base/jdk.internal.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at java.base/jdk.internal.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.base/java.lang.reflect.Method.invoke(Method.java:564)
at anywheresoftware.b4a.debug.Debug.CallSub4(Debug.java:115)
... 36 more
Caused by: java.lang.InstantiationException: teste.app.b4xmainpage$AudioCapture
at java.base/java.lang.Class.newInstance(Class.java:598)
at anywheresoftware.b4j.object.JavaObject.InitializeNewInstance(JavaObject.java:86)
at teste.app.b4xmainpage._inicia_java(b4xmainpage.java:86)
at teste.app.b4xmainpage._b4xpage_created(b4xmainpage.java:68)
... 41 more
Caused by: java.lang.NoSuchMethodException: teste.app.b4xmainpage$AudioCapture.<init>()
at java.base/java.lang.Class.getConstructor0(Class.java:3427)
at java.base/java.lang.Class.newInstance(Class.java:585)
... 44 more
if I try to use static.
B4J Version: 10.00
Parsing code. (0.01s)
Java Version: 14
Building folders structure. (0.01s)
Running custom action. (0.02s)
Compiling code. (0.04s)
Compiling layouts code. (0.00s)
Organizing libraries. (0.00s)
Compiling generated Java code. Error
src\teste\app\b4xmainpage.java:249: error: non-static method getBA() cannot be referenced from a static context
getBA().raiseEventFromDifferentThread(null, null, 0, eventName.toLowerCase() + "_qv", true, new Object[]{data});
^
1 error
javac 14.0.1
How can I use inline java, have classes in java and at the same time be able to return values to subs in b4j
Obs: I know that there are already recording libraries in b4j, but this question is about inline java/class and subs.
Thx