I am using RAD Studio 10.2 Tokyo and am programming in Delphi.
I am having general problems with a Java object using the JNI libraries.
What I am trying to do is find the maximum audio amplitude of an Android audio source between button presses.
Here is the code that I am using.
var
Form1: TForm1;
Recorder: JMediaRecorder;
procedure TForm1.Button1Click(Sender: TObject);
begin
if not assigned(Recorder) then
begin
Recorder:= TJMediaRecorder.Create();
Recorder.setAudioSource(1);
Recorder.setOutputFormat(1);
Recorder.setAudioEncoder(1);
Recorder.setOutputFile(TPath.GetTempPath+'/test');
Recorder.prepare();
Recorder.start();
end;
Label1.Text:=IntToStr(Recorder.getMaxAmplitude());
end;
This appears to generate multiple issues.
Issue #1:
Although I am aware that in java the Media recorder settings should look something like
Recorder.setAudioSource(MediaRecorder.AudioSource.MIC).
That is not something that I can enter in RAD Studio. I took a look at the API and found that that is supposed to mean an integer of 1. The problem is that it gives me an error saying that it can't find an audio source.
Issue #2:
I need to set a path for the file using
Recorder.setOutputFile()
The problem with this is that it only accepts JStrings as input. I have looked all over the place and found a few people who use
StringToJString('my super cool string')
I think this is a part of a library that I am unaware of though because it doesn't work when I use it.
If you know of another way to get an amplitude reading off an Android audio source I would also accept that as an answer as that is the overall problem I am trying to solve.
In general, within the Delphi Android JNI framework:
Java class types are represented in Delphi using classes that are prefixed with TJ
, and Java object instances are represented in Delphi using interfaces that are prefixed with J
.
nested Java classes are represented by Delphi classes and interfaces that are named after the parent class name followed by _
followed by the nested class name.
Java static constants/fields/properties/methods are represented in Delphi as sub-properties/methods of a special JavaClass
class property.
So, in your case:
the Java MediaRecorder
class is represented by the TJMediaRecorder
class and JMediaRecorder
interface.
the Java MediaRecorder.AudioSource
class is represented by the TJMediaRecorder_AudioSource
class and JMediaRecorder_AudioSource
interface.
the Java MediaRecorder.AudioSource.MIC
constant is represented by the TJMediaRecorder_AudioSource.JavaClass.MIC
class property:
Recorder.setAudioSource(TJMediaRecorder_AudioSource.JavaClass.MIC);
The same thing applies to the MediaRecorder.setOutputFormat()
and MediaRecorder.setAudioEncoder()
methods:
Recorder.setOutputFormat(TJMediaRecorder_OutputFormat.JavaClass.THREE_GPP);
Recorder.setAudioEncoder(TJMediaRecorder_AudioEncoder.JavaClass.AMR_NB);
As for strings, JNI knows nothing about Delphi strings, so you must use StringToJString()
to convert Delphi strings to JNI strings, and use JStringToString()
to convert JNI strings to Delphi strings. Both functions are in the Delphi RTL, specifically in the Androidapi.Helpers
unit (XE6+) or Androidapi.JNI.JavaTypes
unit (XE5), depending on which version of Delphi you are using.
Recorder.setOutputFile(StringToJString(TPath.Combine(TPath.GetTempPath, 'test')));