使用Delphi,我试图更改AndroidTTS的音量,但似乎不断收到错误“外部感知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,StringToJString('id'));   }

  //ftts.speak(StringToJString(say),TJTextToSpeech.JavaClass.QUEUE_ADD,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,因为他们将其更改为使用Bundles而不是Hashmaps。

我不完全确定 params.putFloat(TJTextToSpeech_Engine.JavaClass.KEY_ParaM_VOLUME,0.75); 出什么问题了。 ...这是Android停止并提供代码的地方。

其他资源:

我已经查看了为什么我的代码使用params.putFloat:

Android text to speech volume not changing

我唯一发现的关于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,%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'));