使用 Delphi,我正在尝试更改 AndroidTTS 的音量,但我似乎一直收到错误 "External exeception 1"

Using Delphi, I'm trying to change the volume of the AndroidTTS, but I seem to keep getting the error "External exeception 1"

我正在使用这些库:

https://github.com/jimmckeeth/FireMonkey-Android-Voice

https://github.com/FMXExpress/android-object-pascal-wrapper/tree/master/android-25

这是我的源代码:

unit Unit1;

interface

uses
  System.SysUtils, System.Types, System.UITypes, System.Classes, System.Variants,
  FMX.Types, FMX.Controls, FMX.Forms, FMX.Graphics, FMX.Dialogs,
  SpeechRecognition, FMX.Controls.Presentation, FMX.ScrollBox, FMX.Memo,
  FMX.StdCtrls, FMX.Memo.Types, AndroidTTS, FMX.Media, System.IOUtils;

type
  TForm1 = class(TForm)
    SpeechRecognition1: TSpeechRecognition;
    Memo1: TMemo;
    Button1: TButton;
    AndroidTTS1: TAndroidTTS;
    Button2: TButton;
    Button3: TButton;
    Button4: TButton;
    MediaPlayer1: TMediaPlayer;
    Button5: TButton;
    procedure SpeechRecognition1Command(Sender: TObject; Guess: string);
    procedure SpeechRecognition1Recognition(Sender: TObject; Guess: string);
    procedure Button1Click(Sender: TObject);
    procedure Button2Click(Sender: TObject);
    procedure Button3Click(Sender: TObject);
    procedure Button4Click(Sender: TObject);
    procedure Button5Click(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.fmx}
{$R *.NmXhdpiPh.fmx ANDROID}

procedure TForm1.Button1Click(Sender: TObject);
begin
  SpeechRecognition1.Prompt := 'What you want?';
  SpeechRecognition1.Listen;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
  AndroidTTS1.setSpeechRate(0.75);
  AndroidTTS1.SpeakVolume('Hello, whats up?',0.75);
end;

procedure TForm1.Button3Click(Sender: TObject);
begin
  MediaPlayer1.Volume := 0.25;
  MediaPlayer1.FileName := TPath.GetDocumentsPath + PathDelim + 'HerosOfLegend.wav';
  MediaPlayer1.Play;
end;

procedure TForm1.Button4Click(Sender: TObject);
begin
  MediaPlayer1.Stop;
end;

procedure TForm1.Button5Click(Sender: TObject);
begin
  AndroidTTS1.setSpeechRate(0.75);
  AndroidTTS1.SpeakBundle('Hello bundle is this method!');
end;

procedure TForm1.SpeechRecognition1Command(Sender: TObject; Guess: string);
begin
  memo1.Lines.Add('Command: ' + Guess);
end;

procedure TForm1.SpeechRecognition1Recognition(Sender: TObject; Guess: string);
begin
  memo1.Lines.Add('OnRecognition: ' + Guess);
end;

end.

https://github.com/jimmckeeth/FireMonkey-Android-Voice/blob/master/JNIBridge/Androidapi.JNI.TTS.pas的第123行....我改成:

function speak(text: JString; queueMode: Integer; params: JHashMap) : Integer; cdecl; Overload;
function speak(text: JString; queueMode: Integer; params: JBundle; utteranceId: JString) : Integer; cdecl; Overload;

https://github.com/jimmckeeth/FireMonkey-Android-Voice/blob/master/Components/AndroidTTS.pas的第44行...我改成了:

  procedure Speak(say: String);
  procedure SpeakBundle(say: String);
  procedure SpeakVolume(say: String; volume: single);
  procedure setPitch(pitch: Single);
  procedure setSpeechRate(speechRate: Single);
  function isSpeaking: Boolean;

https://github.com/jimmckeeth/FireMonkey-Android-Voice/blob/master/Components/AndroidTTS.pas 的第 80 到 97 行 ... 我将其更改为:

procedure TAndroidTTS.SpeakBundle(say: String);
{$IFDEF ANDROID}
var
  params: JBundle;
begin
  params := nil;
  //params := TJHashMap.Create;
  //params.put(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_VOLUME,
     //StringToJString('0.75'));
  //params := TJBundle.JavaClass.init();
  //params.putFloat(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_VOLUME,volume);
// This needs to be a <String,String> hashmap for the OnDone to work.
{  params := TJHashMap.JavaClass.init();
  params.put(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_UTTERANCE_ID,
     StringToJString('id'));   }

  ftts.speak(StringToJString(say), TJTextToSpeech.JavaClass.QUEUE_FLUSH, params, StringToJString('1'));
end;
{$ELSE}
begin

end;
{$ENDIF}

procedure TAndroidTTS.SpeakVolume(say: String; volume: single);
{$IFDEF ANDROID}
var
  params: JBundle;
begin
  //params := TJHashMap.Create;
  //params.put(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_VOLUME,
     //StringToJString('0.75'));
  //params := nil;
  params := TJBundle.JavaClass.init();
  params.putFloat(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_VOLUME,0.75);
// This needs to be a <String,String> hashmap for the OnDone to work.
{  params := TJHashMap.JavaClass.init();
  params.put(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_UTTERANCE_ID,
     StringToJString('id'));   }

  //ftts.speak(StringToJString(say), TJTextToSpeech.JavaClass.QUEUE_ADD, params, StringToJString('1'));
end;
{$ELSE}
begin

end;
{$ENDIF}

procedure TAndroidTTS.setPitch(pitch: Single);
{$IFDEF ANDROID}
begin
  //pitch   float: Speech pitch. 1.0 is the normal pitch, lower values lower the tone of the synthesized voice, greater values increase it.
  ftts.setPitch(pitch);
end;
{$ELSE}
begin

end;
{$ENDIF}

procedure TAndroidTTS.setSpeechRate(speechRate: Single);
{$IFDEF ANDROID}
begin
  //float: Speech rate. 1.0 is the normal speech rate, lower values slow down the speech (0.5 is half the normal speech rate), greater values accelerate it (2.0 is twice the normal speech rate).
  ftts.setSpeechRate(speechRate);
end;
{$ELSE}
begin

end;
{$ENDIF}

function TAndroidTTS.isSpeaking: Boolean;
{$IFDEF ANDROID}
begin
  // Checks whether the TTS engine is busy speaking.
  result := ftts.isSpeaking;
end;
{$ELSE}
begin
  result := false;
end;
{$ENDIF}

我好像无法获取程序TAndroidTTS.SpeakVolume(say: String; volume: single);才能正常工作。 Android 给我一个错误“外部异常 1”。与“params.putFloat(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_VOLUME,0.75);”

我更改并更新了代码以及 https://developer.android.com/reference/android/speech/tts/TextToSpeech.Engine#KEY_PARAM_VOLUME 因为他们将其更改为使用 Bundle 而不是 Hashmaps。

我不完全确定 params.putFloat(TJTextToSpeech_Engine.JavaClass.KEY_PARAM_VOLUME,0.75); 有什么问题...这是 Android 停止并给出代码。

其他资源:

我查看了这就是我的代码使用 params.putFloat:

的原因

关于 Delphi 的错误,我唯一能找到的是:

https://community.idera.com/developer-tools/platforms/f/android-platform/70741/inapppurchase

哪个应该在 Delphi 10.4.1 中修复,对吗?我检查了 https://quality.embarcadero.com/browse/RSP-27140 网页,发现它已修复。我有不同的问题吗?

非常感谢任何帮助!

您收到的异常是因为此导入有错误:

https://github.com/jimmckeeth/FireMonkey-Android-Voice/blob/master/JNIBridge/Androidapi.JNI.TTS.pas

..因为 JTextToSpeech_Engine 没有 JavaSignature 属性。应该是:

  [JavaSignature('android/speech/tts/TextToSpeech$Engine')]
  JTextToSpeech_Engine = interface(JObject)
    ['{5BAC3048-CB0C-4DC4-AF62-D0D9AE4394CF}']
  end;

speak 方法的重载也不正确。参考:

https://developer.android.com/reference/android/speech/tts/TextToSpeech#speak(java.lang.CharSequence,%20int,%20android.os.Bundle,%20java.lang.String)

声明应该是:

function speak(text: JCharSequence; queueMode: Integer; params: JBundle; utteranceId: JString): Integer; cdecl; overload;

这样称呼它:

ftts.speak(StrToJCharSequence(say), TJTextToSpeech.JavaClass.QUEUE_ADD, params, StringToJString('1'));