Android中實現(xiàn)短音頻和震動的一些總結(jié)

好長時間沒有寫博客了,因為最近事情比較多。所以好長時間沒有寫博客了。堅持是一件很辛苦的事情。但還需要努力。。。好了,閑話不扯了。因為最近項目中用到了相應(yīng)的短音頻和震動的功能,所以這里總結(jié)一下相應(yīng)的內(nèi)容!

本文知識點:

    1. 音頻中的一些知識和常用的API介紹;
    1. 震動中的一些知識和常用的API介紹;
    1. 簡單的使用和封裝;

1. 音頻中的一些知識介紹和常用的API

1.1 關(guān)于短音頻一些知識的介紹

在項目中突然有個需求,就是實現(xiàn)短音頻,好比短信音那種!最開始想到的方案就是MediaPlayer解決。但是我隨手百度了一下,發(fā)現(xiàn)其實Android提供了一個單獨播放短音頻的 類(SoundPool),為什么是它呢?因為soundPool用于播放密集,急促的短暫音效,例如微信的搖一搖等。。。SoundPool使用了音效池的來播放音頻,如果超過流的最大數(shù)目,SoundPool會基于優(yōu)先級自動停止先前播放的流。所以播放短促且密集的音頻應(yīng)該使用SoundPool進行相應(yīng)的播放,好了就簡單介紹到這里吧!

1.2 音頻的一些相應(yīng)的API介紹

這里說明一點,在android5.0的時候廢棄了相應(yīng)SoundPool使用構(gòu)造方法的創(chuàng)建,所以為了兼容,在創(chuàng)建的時候要進行相應(yīng)的適配!相應(yīng)的適配代碼如下:

1.2.1 構(gòu)造對象的方法

        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簡介

其實就是幾個重載的方法,基本上就是傳入?yún)?shù)進行相應(yīng)的加載資源。

  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對應(yīng)后面的soundID),后面我們可以通過這個ID來播放指定的聲音。

因為使用的參數(shù)都差不多,所以這里統(tǒng)一進行講解一下:

  • 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)

上面是開始播放的代碼,參數(shù)含義如下:

  • soundID load()返回的相應(yīng)索引
  • leftVolume:左聲道音量設(shè)置
  • rightVolume:右聲道音量設(shè)置
  • priority:指定播放聲音的優(yōu)先級,數(shù)值越高,優(yōu)先級越大。
  • loop:指定是否循環(huán):-1表示無限循環(huán),0表示不循環(huán),其他值表示要重復(fù)播放的次數(shù)
  • rate:指定播放速率:1.0的播放率可以使聲音按照其原始頻率,而2.0的播放速率,可以使聲音按照其 原始頻率的兩倍播放。如果為0.5的播放率,則播放速率是原始頻率的一半。播放速率的取值范圍是0.5至2.0
  1. release() 釋放相應(yīng)的資源
  2. setOnLoadCompleteListener(OnLoadCompleteListener listener) 文件加載完畢的監(jiān)聽

以上就是SoundPool的一些常見API,基本上上面的代碼就可以輕松的使用SoundPool了!

2. 震動中的一些知識和常用的API介紹

2.1 震動的一些知識點介紹

關(guān)于震動沒有什么好說的,只能使用Vibrator進行開發(fā),但是切記一點就是權(quán)限的聲明,基本上只要相關(guān)的權(quán)限處理好了,震動還是很容易的。哦,忘記了,這個也要進行相應(yīng)的版本適配,下面會說到的。

2.2 一些相應(yīng)的API介紹

2.2.1 構(gòu)造函數(shù)的創(chuàng)建

Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);

這個沒有什么好說的,就是系統(tǒng)的相應(yīng)服務(wù)。

2.2.2 常見的API簡介

幾個相應(yīng)的重載方法

  1. vibrate(long milliseconds);

  2. vibrate(long milliseconds, AudioAttributes attributes);

  3. vibrate(long[] pattern, int repeat);

  4. vibrate(long[] pattern, int repeat, AudioAttributes attributes);

其實調(diào)用這個就可以直接進行相應(yīng)的震動了,所以說挺簡單的。解釋一下相應(yīng)的參數(shù)含義

  • milliseconds 震動的持續(xù)時間
  • attributes 震動的屬性,AudioAttributes類中定義了很多的屬性,感興趣的可以嘗試一下
  • pattern 這是一個數(shù)組,可以實現(xiàn)一個間斷的震動效果(第一個值表示在打開振動器之前要等待的毫秒數(shù)下一個值表示在關(guān)閉振動器之前保持振動器的毫秒數(shù))實驗一下就可以了。
  • repeat 振動重復(fù)的模式 。"-1"代表不重復(fù)

記得我上面說過關(guān)于版本適配的問題吧,其實在26版本也就是Android O的時候,需要進行相應(yīng)的適配,使用了VibrationEffect封裝了一層。

  1. vibrator.vibrate(long milliseconds); 設(shè)置手機震動

  2. vibrator.hasVibrator(); 判斷手機硬件是否有振動器

  3. vibrator.cancel(); 關(guān)閉振動

  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);

也就是說之前直接調(diào)用的代碼通過VibrationEffect進行了相應(yīng)的封裝。解釋一個參數(shù)

  • amplitude 振幅值. 振幅在0~255之間,隨便選擇一個吧
  1. vibrate(VibrationEffect vibe); 開啟震動

  2. vibrate(VibrationEffect vibe, AudioAttributes attributes); 開啟震動

3. 簡單的使用和封裝

基本上關(guān)于短音頻和振幅的內(nèi)容就是上面這些,基本上按照上面這些進行相應(yīng)的組合就可以了.但是為了大家的方便,我簡單的封裝了一個工具類給大家使用.封裝的不好還請見諒!!!

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;

    /**
     * 音頻的相關(guān)類
     */
    private SoundPool mSoundPool;
    private Context mContext;
    private Vibrator mVibrator;


    private SoundPoolUtils(Context context) {
        mContext = context;
        //初始化行營的音頻類
        intSoundPool();
        initVibrator();
    }

    /**
     * @author Angle
     * 創(chuàng)建時間: 2018/11/4 13:02
     * 方法描述: 初始化短音頻的內(nèi)容
     */
    private void intSoundPool() {
        //根據(jù)不同的版本進行相應(yīng)的創(chuàng)建
        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
     * 創(chuàng)建時間: 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
     * 創(chuàng)建時間: 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
     * 創(chuàng)建時間: 2018/11/4 13:04
     * 方法描述: 開啟相應(yīng)的震動
     */
    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
     * 創(chuàng)建時間: 2018/11/4 13:06
     * 方法描述: 同時開始音樂和震動
     */
    public void startVideoAndVibrator(int resId, long milliseconds) {
        playVideo(resId);
        startVibrator(milliseconds);
    }

    /**
     * @author Angle
     * 創(chuàng)建時間: 2018/11/4 13:05
     * 方法描述:  釋放相應(yīng)的資源
     */
    public void release() {
        //釋放所有的資源
        if (mSoundPool != null) {
            mSoundPool.release();
            mSoundPool = null;
        }

        if (mVibrator != null) {
            mVibrator.cancel();
            mVibrator = null;
        }
    }
}

因為我們項目中,只用到了相應(yīng)的播放一個短音頻所以這里就只簡單的封裝了一下.見諒!!!

使用起來就很簡單了,在你使用的地方直接調(diào)用

  • startVibrator 單獨的震動
  • playVideo 單獨的聲音
  • startVideoAndVibrator 震動加聲音
  • release 在onPause的時候釋放相應(yīng)的資源

好了今天的內(nèi)容就這么多了,有什么不明白的地方歡迎騷擾...

?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容