简单播放mp3的正确方法就是通知

时间:2016-06-16 22:21:09

标签: c# android xamarin xamarin.android

我有一些小的mp3文件,我想在我的应用程序中作为通知声音播放。为了清楚起见,我已经创建了一个" raw"在Resources下的文件夹并在那里添加了我的mp3文件。作为第一关,我只是使用MediaPlayer:

MediaPlayer mPlayer;

mPlayer = MediaPlayer.Create(context, Resource.Raw.warning);

mPlayer.Start();

这很有效,但是当我想要做的就是将它们用作通知而不是播放音轨时,它似乎有点笨拙。我还认为这种方法有更多的开销来确保播放器完成播放,处理等...

所以,我找到了SoundPool并实现了它。有一些早期的问题,例如,当您将声音加载到SoundPool中时,它会返回SoundID的int,然后您可以将其用作对要播放的声音的引用。因此,我必须创建一个单独的类来处理这些属性。

这是我到目前为止所做的工作似乎仍然有效,但我想知道这是不是最好的方法呢?

首先,我创建了一个包装SoundPool的类,它也有一个SoundID类。

using Android.Content;
using Android.Media;

namespace PocketPacTracAndroid.Media
{
    public class Sounds
    {
        SoundPool soundPool;
        Context context;
        int maxStreams = 1;
        bool isLoaded = false;

    public bool IsLoaded
    {
        get { return isLoaded; }
    }

    public Sounds(Context oContext)
    {
        soundPool = new SoundPool(maxStreams, Stream.Music, 0);
        context = oContext;
        loadSoundPool();
    }

    public Sounds(Context oContext, int streams)
    {
        maxStreams = streams;
        soundPool = new SoundPool(maxStreams, Stream.Music, 0);
        loadSoundPool();
    }

    private void loadSoundPool()
    {
        soundPool.LoadComplete += SoundPool_LoadComplete;
        SoundIDs sid = new SoundIDs();
        sid.Scan = soundPool.Load(context, Resource.Raw.scan, 1);
        sid.PackageAdded = soundPool.Load(context, Resource.Raw.packageAdded, 1);
        sid.HubTransfer = soundPool.Load(context, Resource.Raw.hubtransfer, 1);
        sid.Alert = soundPool.Load(context, Resource.Raw.alert, 1);
        sid.Warning = soundPool.Load(context, Resource.Raw.warning, 1);
        sid.ScanChange = soundPool.Load(context, Resource.Raw.scanchange, 1);
    }

    private void SoundPool_LoadComplete(object sender, SoundPool.LoadCompleteEventArgs e)
    {
        isLoaded = true;
    }

    public void playSound(int sid)
    {
        if (isLoaded)
        {
            soundPool.Play(sid, 1f, 1f, 1, 0, 1f);
        }
    }
}

public class SoundIDs
{
    int scan;
    int packageAdded;
    int hubTransfer;
    int alert;
    int warning;
    int scanChange;


    public int Scan
    {
        get { return scan; }
        set { scan = value; }
    }

    public int PackageAdded
    {
        get { return packageAdded; }
        set { packageAdded = value; }
    }

    public int HubTransfer
    {
        get { return hubTransfer; }
        set { hubTransfer = value; }
    }

    public int Alert
    {
        get { return alert; }
        set { alert = value; }
    }

    public int Warning
    {
        get { return warning; }
        set { warning = value; }
    }

    public int ScanChange
    {
        get { return scanChange; }
        set { scanChange = value; }
    }
}
}

然后,从我的应用程序的任何地方,我实例化类:

    Sounds sounds;
    SoundIDs sid;

    public override void OnCreate(Bundle savedInstanceState)
    {
        base.OnCreate(savedInstanceState);
        context = Context;
        getServiceTypes();
        sounds = new Sounds(context);
        sid = new SoundIDs();
    }

最后,我可以根据我加载文件时返回的soundID来调用它来播放声音。我也暴露了IsLoaded,以防我想在外部检查,但是在调用playSound时会在内部检查。

sounds.playSound(sid.Scan);

这看起来像是一种好方法吗?它是最好的吗?任何建议,将不胜感激。它似乎确实有效但我只是想确保在应用程序生命周期中反复调用相同或不同的通知时,我不会遇到任何资源问题或播放问题。

谢谢!

1 个答案:

答案 0 :(得分:0)

是的SoundPool是要走的路。请注意同时播放不同声音的线程。除非你建立一个队列,否则一些声音会阻止其他人,因为只有一个发言者。