美文网首页
Android 音效 & SoundPool 封装类 & 停止音

Android 音效 & SoundPool 封装类 & 停止音

作者: 南窗云 | 来源:发表于2019-01-10 14:45 被阅读0次

项目中,需要添加点击或者状态回调的音效。
Android 有专门用于实现音效播放的类,就是 SoundPool 。

1 工具类封装

共四种音效,更多可在 init 中 自行添加。

/**
 * <pre>
 *     author : jake
 *     time   : 2019/01/10
 *     function   :   音效管理类
 *     version: 1.3.0
 * </pre>
 */

class SoundPoolManager {

    companion object {
        private var instance: SoundPoolManager? = null
            get() {
                if (field == null) {
                    field = SoundPoolManager()
                }
                return field
            }

        @Synchronized
        fun get(): SoundPoolManager {
            return instance!!
        }

        const val TASK_CLICK = 1
        const val TASK_SUCCESS = 2
        const val TASK_WRONG = 3
        const val TASK_REWARD = 4
    }


    private var soundPool: SoundPool = SoundPool(4, AudioManager.STREAM_MUSIC, 0)
    private var sourcesMap = HashMap<Int, Int>()

    init {
        sourcesMap[TASK_CLICK] = soundPool.load(RiseApp.mContext, R.raw.click, 1)
        sourcesMap[TASK_SUCCESS] = soundPool.load(RiseApp.mContext, R.raw.success, 1)
        sourcesMap[TASK_WRONG] = soundPool.load(RiseApp.mContext, R.raw.wrong, 1)
        sourcesMap[TASK_REWARD] = soundPool.load(RiseApp.mContext, R.raw.reward, 1)
    }

    fun play(type: Int) {
        // 防止type不存在
        if (sourcesMap[type] != null) {
            soundPool.play(sourcesMap[type]!!, 1.0f, 1.0f, 0, 0, 1.0f)
        }
    }
}

在触发的地方,直接使用即可

   SoundPoolManager.get().play(SoundPoolManager.TASK_CLICK)

2 音效停止播放(2019.4.23)

头一次遇到还要音效播一半,还要停止的。(音效比较多,且比较长,多次点击重复混合播放)

按照经验,肯定是通过 url 来判断是停止播放,还是开始播放新音效(两次传入相同则停止,否则则播放新的),然而发现并不生效。

后来想到,因为是一个 音效对象池,是不是播放第一个音效和播放第二个音效用不是同一个对象,从而导致调用停止方法无效的?

就是这个原因

当我们调用下面方法播放音效时,其返回值就是当前播放音效的 对象ID,且每次都不一样

soundPool.play(sourcesMap[path]!!, 1.0f, 1.0f, 0, 0, 1.0f)

所以我们只需要存储一下,上一次播放音效时的 对象ID ,然后在调用 stop 方法时,传入 对象ID 即可停止播放音效。

存储上次播放时的 音效对象ID

 lastSound = soundPool.play(sourcesMap[path]!!, 1.0f, 1.0f, 0, 0, 1.0f)

停止时传入

 soundPool.stop(lastSound)

由于,后来项目中用的不是打在APK 中的本地音效,而是下载到设备特定目录的音频文件,还有一些其他对应关系,故又重新封装了新的工具类,如下:

/**
 * <pre>
 *     author : jake
 *     time   : 2019/03/10
 *     function   :   音效管理类
 *     version: 1.0
 * </pre>
 *
 * 根据下载到本地的音效路径,播放音效
 *
 * 在音效下载完毕后,会调用初始化方法  LibrarySoundsManager
 *
 */

class LibrarySoundPoolManager {

    companion object {
        private var instance: LibrarySoundPoolManager? = null
            get() {
                if (field == null) {
                    field = LibrarySoundPoolManager()
                }
                return field
            }

        @Synchronized
        fun get(): LibrarySoundPoolManager {
            return instance!!
        }

        private var soundPool: SoundPool = SoundPool(37, AudioManager.STREAM_MUSIC, 0)
        private var sourcesMap = HashMap<String, Int>()
        private var lastSound = 0
    }

    /**
     * 预加载 图书馆音效资源
     *
     * 调用此方法时,证明图书馆音效资源已经下载完毕
     */
    fun init(content: String) {
        /**
         * 获取前端数据,并解析
         */
        val json = JSONObject(content)
        val path = json["path"].toString()
        val data = path.split("^")
        if (data != null && data.size > 0) {
            for (item in data) {
                if (!item.isEmpty() && sourcesMap[RiseWebPath.LibraryWebKey.plus("/sounds/").plus(item)] == null) {
                    sourcesMap[RiseWebPath.LibraryWebKey.plus("/sounds/").plus(item)] = soundPool.load("${RisePath.libraryDir}/sounds/$item", 1)
                }
            }
        }

    }

    /**
     * 根据下载到本地的音效路径,播放音效
     */
    fun play(path: String) {
        if (!path.isEmpty() && sourcesMap[path] != null) {
            soundPool.stop(lastSound)
            lastSound = soundPool.play(sourcesMap[path]!!, 1.0f, 1.0f, 0, 0, 1.0f)
        }
    }

    /**
     * 停止播放所有音效
     */
    fun stop() {
        soundPool.stop(lastSound)
    }
}

具体各个参数的含义,可参考这篇文章,说的蛮详细的。

うずまき ナルト

相关文章

网友评论

      本文标题:Android 音效 & SoundPool 封装类 & 停止音

      本文链接:https://www.haomeiwen.com/subject/pukarqtx.html