Android 从资源中播放.wav文件

Android 从资源中播放.wav文件,android,delphi,audio,firemonkey,Android,Delphi,Audio,Firemonkey,我正在使用Firemonkey编写一个android应用程序 因此,我无法使用彩信系统的功能sndPlaySound从资源文件中播放,因为这仅限于Windows Firemonkey支持媒体播放器的工作和资源。但是媒体播放器不能直接使用资源文件 如何使用TMediaPlayer播放资源中的声音 播放不在文件中的媒体 TMediaPlayer不以本机方式实现任何非文件系统数据源, 因此,您必须实现自己的自定义编解码器/媒体类才能访问 (并播放)您想要的资源数据。TMediaPlayer本身就是这

我正在使用Firemonkey编写一个android应用程序

因此,我无法使用彩信系统的功能sndPlaySound从资源文件中播放,因为这仅限于Windows

Firemonkey支持媒体播放器的工作和资源。但是媒体播放器不能直接使用资源文件

如何使用TMediaPlayer播放资源中的声音

播放不在文件中的媒体

TMediaPlayer不以本机方式实现任何非文件系统数据源, 因此,您必须实现自己的自定义编解码器/媒体类才能访问 (并播放)您想要的资源数据。TMediaPlayer本身就是这样 不管它的文件名是否存在于文件系统中。它只是问 TMediaCodecManager类检索合适的TMedia对象以访问和 播放文件名所指的任何来源的数据

创建从FMX.Media.TMedia派生的自定义类并实现其 根据需要抽象方法(DoPlay()、DoStop()、GetDuration()等)。这 类访问并播放实际的媒体数据,因此您可以传递所需的 文件名,并让它根据需要加载/访问您的资源流。看 例如,在默认的TMedia实现中(FMX.Media.Win.TWindowsMedia, FMX.Media.Mac.TQTMedia等)

创建从FMX.Media.TCustomMediaCodec派生的自定义类并实现 它的抽象CreateFromFile()方法返回自定义 TMedia类。然后,您可以在程序启动时使用 FMX.Media.TMediaCodecManager.registerDiacodeClass()。诀窍在于 您必须使用文件扩展名注册该类,因此请选择一些内容 这是唯一的,对于真正的文件来说不能混淆

例如:

unit PlayMediaFromResource;

uses
   ..., FMX.Media;

type
  TMyResourceMedia = class(TMedia)
    ...
  protected
    function GetDuration: TMediaTime; override;
    function GetCurrent: TMediaTime; override;
    procedure SetCurrent(const Value: TMediaTime); override;
    function GetVideoSize: TPointF; override;
    function GetMediaState: TMediaState; override;
    function GetVolume: Single; override;
    procedure SetVolume(const Value: Single); override;
    procedure UpdateMediaFromControl; override;
    procedure DoPlay; override;
    procedure DoStop; override;
  public
    constructor Create(const AFileName: string); override;
    destructor Destroy; override;
  end;

  TMyResourceMediaCodec = class(TCustomMediaCodec)
  public
    function CreateFromFile(const AFileName: string): TMedia; override;
  end;

function TMyResourceMediaCodec.CreateFromFile(const AFileName: string): TMedia;
begin
  Result := TMyResourceMedia.Create(AFileName);
end;

constructor TMyResourceMedia.Create(const AFileName: string);
var
  ResName: string;
begin
  ResName := ChangeFileExt(AFileName, ''); // strip off '.myres' file extension
  // load resource identified by ResName as needed...
end;

....

initialization
  TMediaCodecManager.RegisterMediaCodecClass('.myres', 'My Resource Stream', 
TMediaType.Audio, TMyResourceMediaCodec);
然后你可以这样做:

MediaPlayer1.FileName := 'MyResourceName.myres';
MediaPlayer1.Play;
end;
--

或者您可以将资源保存到文件中
如果你能以某种方式将资源保存到一个文件中并从那里播放,那么一切都会变得容易得多。您只需使用stock TMediaPlayer即可。
播放完毕后不要忘记删除文件,否则会填满磁盘。

播放不在文件中的媒体

TMediaPlayer不以本机方式实现任何非文件系统数据源, 因此,您必须实现自己的自定义编解码器/媒体类才能访问 (并播放)您想要的资源数据。TMediaPlayer本身就是这样 不管它的文件名是否存在于文件系统中。它只是问 TMediaCodecManager类检索合适的TMedia对象以访问和 播放文件名所指的任何来源的数据

创建从FMX.Media.TMedia派生的自定义类并实现其 根据需要抽象方法(DoPlay()、DoStop()、GetDuration()等)。这 类访问并播放实际的媒体数据,因此您可以传递所需的 文件名,并让它根据需要加载/访问您的资源流。看 例如,在默认的TMedia实现中(FMX.Media.Win.TWindowsMedia, FMX.Media.Mac.TQTMedia等)

创建从FMX.Media.TCustomMediaCodec派生的自定义类并实现 它的抽象CreateFromFile()方法返回自定义 TMedia类。然后,您可以在程序启动时使用 FMX.Media.TMediaCodecManager.registerDiacodeClass()。诀窍在于 您必须使用文件扩展名注册该类,因此请选择一些内容 这是唯一的,对于真正的文件来说不能混淆

例如:

unit PlayMediaFromResource;

uses
   ..., FMX.Media;

type
  TMyResourceMedia = class(TMedia)
    ...
  protected
    function GetDuration: TMediaTime; override;
    function GetCurrent: TMediaTime; override;
    procedure SetCurrent(const Value: TMediaTime); override;
    function GetVideoSize: TPointF; override;
    function GetMediaState: TMediaState; override;
    function GetVolume: Single; override;
    procedure SetVolume(const Value: Single); override;
    procedure UpdateMediaFromControl; override;
    procedure DoPlay; override;
    procedure DoStop; override;
  public
    constructor Create(const AFileName: string); override;
    destructor Destroy; override;
  end;

  TMyResourceMediaCodec = class(TCustomMediaCodec)
  public
    function CreateFromFile(const AFileName: string): TMedia; override;
  end;

function TMyResourceMediaCodec.CreateFromFile(const AFileName: string): TMedia;
begin
  Result := TMyResourceMedia.Create(AFileName);
end;

constructor TMyResourceMedia.Create(const AFileName: string);
var
  ResName: string;
begin
  ResName := ChangeFileExt(AFileName, ''); // strip off '.myres' file extension
  // load resource identified by ResName as needed...
end;

....

initialization
  TMediaCodecManager.RegisterMediaCodecClass('.myres', 'My Resource Stream', 
TMediaType.Audio, TMyResourceMediaCodec);
然后你可以这样做:

MediaPlayer1.FileName := 'MyResourceName.myres';
MediaPlayer1.Play;
end;
--

或者您可以将资源保存到文件中
如果你能以某种方式将资源保存到一个文件中并从那里播放,那么一切都会变得容易得多。您只需使用stock TMediaPlayer即可。

播放完毕后不要忘记删除文件,否则会填满磁盘。

这不起作用。在这个例子中,我得到了与该类相关的大量错误。“我得到了大量错误”并没有给我们提供太多的信息。祝您好运。例如:
[DCC Error]Unit2.pas(18):在基类[DCC Error]Unit2.pas(45)中找不到E2137方法“GetDuration”:E2004标识符重新声明:“AFileName”[DCC Error]Unit2.pas(73):E2066缺少运算符或分号[DCC Error]Unit2.pas(23):E2065未满足的转发或外部声明:“TForm2.GetVolume”
您刚刚将这些方法塞进了一个表单中。仔细阅读我链接的代码。试着花些时间思考它的作用并理解它。不要只是盲目地将代码粘贴到程序的随机部分,希望它能成功。这是行不通的。在这个例子中,我得到了与该类相关的大量错误。“我得到了大量错误”并没有给我们提供太多的信息。祝您好运。例如:
[DCC Error]Unit2.pas(18):在基类[DCC Error]Unit2.pas(45)中找不到E2137方法“GetDuration”:E2004标识符重新声明:“AFileName”[DCC Error]Unit2.pas(73):E2066缺少运算符或分号[DCC Error]Unit2.pas(23):E2065未满足的转发或外部声明:“TForm2.GetVolume”
您刚刚将这些方法塞进了一个表单中。仔细阅读我链接的代码。试着花些时间思考它的作用并理解它。不要只是盲目地将代码粘贴到程序的随机部分,希望它能成功。我自己说得再好不过了:-)我自己说得再好不过了:-)