阅读 929

Android中实现短音频和震动的一些总结

好长时间没有写博客了,因为最近事情比较多。所以好长时间没有写博客了。坚持是一件很辛苦的事情。但还需要努力。。。好了,闲话不扯了。因为最近项目中用到了相应的短音频和震动的功能,所以这里总结一下相应的内容!

本文知识点:

    1. 音频中的一些知识和常用的API介绍;
    1. 震动中的一些知识和常用的API介绍;
    1. 简单的使用和封装;

1. 音频中的一些知识介绍和常用的API

1.1 关于短音频一些知识的介绍

在项目中突然有个需求,就是实现短音频,好比短信音那种!最开始想到的方案就是MediaPlayer解决。但是我随手百度了一下,发现其实Android提供了一个单独播放短音频的 类(SoundPool),为什么是它呢?因为soundPool用于播放密集,急促的短暂音效,例如微信的摇一摇等。。。SoundPool使用了音效池的来播放音频,如果超过流的最大数目,SoundPool会基于优先级自动停止先前播放的流。所以播放短促且密集的音频应该使用SoundPool进行相应的播放,好了就简单介绍到这里吧!

1.2 音频的一些相应的API介绍

这里说明一点,在android5.0的时候废弃了相应SoundPool使用构造方法的创建,所以为了兼容,在创建的时候要进行相应的适配!相应的适配代码如下:

1.2.1 构造对象的方法

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mSoundPool = new SoundPool.Builder()
                    .setMaxStreams(MAX_STREAMS)
                    .build();
        } else {
            mSoundPool = new SoundPool(MAX_STREAMS, AudioManager.STREAM_MUSIC, DEFAULT_QUALITY);
        }
复制代码

1.2.2 常见的API简介

其实就是几个重载的方法,基本上就是传入参数进行相应的加载资源。

  1. load(Context context, int resId, int priority)
  2. load(String path, int priority)
  3. load(FileDescriptor fd, long offset, long length, int priority)
  4. load(AssetFileDescriptor afd, int priority)

上述方法都会返回一个声音的ID(这个ID对应后面的soundID),后面我们可以通过这个ID来播放指定的声音。

因为使用的参数都差不多,所以这里统一进行讲解一下:

  • context 上下文,没有什么好说的
  • resId 资源Id(这里说明一下:一般音频文件都会放在res->raw文件夹下)
  • priority 没有什么实际用处,这里传入1就好了
  • path 文件路径
  • AssetFileDescriptor:从asset目录读取某个资源文件,用法: AssetFileDescriptor descriptor = assetManager.openFd("biaobiao.mp3");
  1. play(int soundID, float leftVolume, float rightVolume, int priority, int loop, float rate)

上面是开始播放的代码,参数含义如下:

  • soundID load()返回的相应索引
  • leftVolume:左声道音量设置
  • rightVolume:右声道音量设置
  • priority:指定播放声音的优先级,数值越高,优先级越大。
  • loop:指定是否循环:-1表示无限循环,0表示不循环,其他值表示要重复播放的次数
  • rate:指定播放速率:1.0的播放率可以使声音按照其原始频率,而2.0的播放速率,可以使声音按照其 原始频率的两倍播放。如果为0.5的播放率,则播放速率是原始频率的一半。播放速率的取值范围是0.5至2.0
  1. release() 释放相应的资源
  2. setOnLoadCompleteListener(OnLoadCompleteListener listener) 文件加载完毕的监听

以上就是SoundPool的一些常见API,基本上上面的代码就可以轻松的使用SoundPool了!

2. 震动中的一些知识和常用的API介绍

2.1 震动的一些知识点介绍

关于震动没有什么好说的,只能使用Vibrator进行开发,但是切记一点就是权限的声明,基本上只要相关的权限处理好了,震动还是很容易的。哦,忘记了,这个也要进行相应的版本适配,下面会说到的。

2.2 一些相应的API介绍

2.2.1 构造函数的创建

Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
复制代码

这个没有什么好说的,就是系统的相应服务。

2.2.2 常见的API简介

几个相应的重载方法

  1. vibrate(long milliseconds);
  2. vibrate(long milliseconds, AudioAttributes attributes);
  3. vibrate(long[] pattern, int repeat);
  4. vibrate(long[] pattern, int repeat, AudioAttributes attributes);

其实调用这个就可以直接进行相应的震动了,所以说挺简单的。解释一下相应的参数含义

  • milliseconds 震动的持续时间
  • attributes 震动的属性,AudioAttributes类中定义了很多的属性,感兴趣的可以尝试一下
  • pattern 这是一个数组,可以实现一个间断的震动效果(第一个值表示在打开振动器之前要等待的毫秒数下一个值表示在关闭振动器之前保持振动器的毫秒数)实验一下就可以了。
  • repeat 振动重复的模式 。"-1"代表不重复

记得我上面说过关于版本适配的问题吧,其实在26版本也就是Android O的时候,需要进行相应的适配,使用了VibrationEffect封装了一层。

  1. vibrator.vibrate(long milliseconds); 设置手机震动
  2. vibrator.hasVibrator(); 判断手机硬件是否有振动器
  3. vibrator.cancel(); 关闭振动
  4. VibrationEffect vibrationEffect = VibrationEffect.createOneShot(long milliseconds, int amplitude);
  5. VibrationEffect vibrationEffect = VibrationEffect.createWaveform(long[] timings, int repeat);
  6. VibrationEffect vibrationEffect = VibrationEffect.createWaveform(long[] timings, int[] amplitudes, int repeat);

也就是说之前直接调用的代码通过VibrationEffect进行了相应的封装。解释一个参数

  • amplitude 振幅值. 振幅在0~255之间,随便选择一个吧
  1. vibrate(VibrationEffect vibe); 开启震动
  2. vibrate(VibrationEffect vibe, AudioAttributes attributes); 开启震动

3. 简单的使用和封装

基本上关于短音频和振幅的内容就是上面这些,基本上按照上面这些进行相应的组合就可以了.但是为了大家的方便,我简单的封装了一个工具类给大家使用.封装的不好还请见谅!!!

public class SoundPoolUtils {

    private static final int MAX_STREAMS = 2;
    private static final int DEFAULT_QUALITY = 0;
    private static final int DEFAULT_PRIORITY = 1;
    private static final int LEFT_VOLUME = 1;
    private static final int RIGHT_VOLUME = 1;
    private static final int LOOP = 0;
    private static final float RATE = 1.0f;

    private static SoundPoolUtils sSoundPoolUtils;

    /**
     * 音频的相关类
     */
    private SoundPool mSoundPool;
    private Context mContext;
    private Vibrator mVibrator;


    private SoundPoolUtils(Context context) {
        mContext = context;
        //初始化行营的音频类
        intSoundPool();
        initVibrator();
    }

    /**
     * @author Angle
     * 创建时间: 2018/11/4 13:02
     * 方法描述: 初始化短音频的内容
     */
    private void intSoundPool() {
        //根据不同的版本进行相应的创建
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
            mSoundPool = new SoundPool.Builder()
                    .setMaxStreams(MAX_STREAMS)
                    .build();
        } else {
            mSoundPool = new SoundPool(MAX_STREAMS, AudioManager.STREAM_MUSIC, DEFAULT_QUALITY);
        }
    }

    /**
     * @author Angle
     * 创建时间: 2018/11/4 13:03
     * 方法描述: 初始化震动的对象
     */
    private void initVibrator() {
        mVibrator = (Vibrator) mContext.getSystemService(Context.VIBRATOR_SERVICE);
    }

    public static SoundPoolUtils getInstance(Context context) {
        if (sSoundPoolUtils == null) {
            synchronized (SoundPoolUtils.class) {
                if (sSoundPoolUtils == null) {
                    sSoundPoolUtils = new SoundPoolUtils(context);
                }
            }
        }
        return sSoundPoolUtils;
    }

    /**
     * @param resId 音频的资源ID
     * @author Angle
     * 创建时间: 2018/11/4 13:03
     * 方法描述: 开始播放音频
     */
    public void playVideo(int resId) {
        if (mSoundPool == null) {
            intSoundPool();
        }
        int load = mSoundPool.load(mContext, resId, DEFAULT_PRIORITY);
        mSoundPool.play(load, LEFT_VOLUME, RIGHT_VOLUME, DEFAULT_PRIORITY, LOOP, RATE);
    }

    /**
     * @param milliseconds 震动时间
     * @author Angle
     * 创建时间: 2018/11/4 13:04
     * 方法描述: 开启相应的震动
     */
    public void startVibrator(long milliseconds) {
        if (mVibrator == null) {
            initVibrator();
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
            VibrationEffect vibrationEffect = VibrationEffect.createOneShot(milliseconds, 100);
            mVibrator.vibrate(vibrationEffect);
        } else {
            mVibrator.vibrate(1000);
        }
    }

    /**
     * @param resId        资源id
     * @param milliseconds 震动时间
     * @author Angle
     * 创建时间: 2018/11/4 13:06
     * 方法描述: 同时开始音乐和震动
     */
    public void startVideoAndVibrator(int resId, long milliseconds) {
        playVideo(resId);
        startVibrator(milliseconds);
    }

    /**
     * @author Angle
     * 创建时间: 2018/11/4 13:05
     * 方法描述:  释放相应的资源
     */
    public void release() {
        //释放所有的资源
        if (mSoundPool != null) {
            mSoundPool.release();
            mSoundPool = null;
        }

        if (mVibrator != null) {
            mVibrator.cancel();
            mVibrator = null;
        }
    }
}
复制代码

因为我们项目中,只用到了相应的播放一个短音频所以这里就只简单的封装了一下.见谅!!!

使用起来就很简单了,在你使用的地方直接调用

  • startVibrator 单独的震动
  • playVideo 单独的声音
  • startVideoAndVibrator 震动加声音
  • release 在onPause的时候释放相应的资源

好了今天的内容就这么多了,有什么不明白的地方欢迎骚扰...

关注下面的标签,发现更多相似文章
评论