MediaPlayer實現金額的語音播報功能

推薦閱讀:
SurfaceView+MediaPlayer封裝之路
Android學習資源分享合集(1)java

最近寫了一個金額的語音播報功能,已封裝成依賴庫到Github,但願對你們有所幫助。
Github地址 :
https://github.com/javaexcept...git

思路:
(1).準備音頻文件。
(2).把要播報的金額轉換成大寫的金額,好比"零壹貳叄肆伍陸柒捌玖,分角 拾佰仟萬拾佰仟億拾佰仟萬"的組合。
(3).經過MediaPlayer播放音頻。github


一.準備音頻文件

下面是我音頻文件,裏面是大寫的數字,爲播報金額組合作準備。api


二.金額轉換

public class PlaySound {


        /**
         * 截取字符串
         *
         * @param str  須要截取的字符串
         * @param idx1 開始位置
         * @param idx2 截止位置
         * @return 截取後的字符串
         */
        public static String subString(String str, int idx1, int idx2) {
            try {
                return str.substring(idx1, idx2);
            } catch (Exception ex) {
                return "";
            }
        }

        /**
         * 傳遞一個字符串參數,若是是null返回「」字符串,不然去除先後的空格。
         *
         * @param str 傳入參數
         * @return 沒有先後沒有空格的字符串
         */
        public static final String trim(String str) {
            if (str == null) return "";
            else return str.trim();
        }

        /**
         * 把double類型數據轉換成有格式的字符串
         *
         * @param d      須要轉換的double類型數據
         * @param format 格式化方式
         * @return 有格式的字符串
         */
        public static String formatDoubleToString(double d, String format) {
            String doubleStr = String.valueOf(d);
            java.text.DecimalFormat decf = new java.text.DecimalFormat(format);
            String formatStr = decf.format(d);
            /**
             * 經過java保留小數了
             * 若是轉換前的長度>轉換後的長度,Java的轉換就有可能出錯
             */
            if (doubleStr.length() > formatStr.length()) {
                /**
                 * 若是前面的都一致,但最後一位大於4就須要進位
                 * 不然不進位
                 */
                if (formatStr.equals(doubleStr.substring(0, formatStr.length()))) {
                    /**
                     * 取轉換前的後一位,
                     * 有多是「.」
                     */
                    String followStr = doubleStr.substring(formatStr.length(), formatStr.length() + 1);
                    if (".".equals(followStr)) {
                        followStr = doubleStr.substring(formatStr.length() + 1, formatStr.length() + 2);
                    }

                    if (Integer.valueOf(followStr).intValue() > 4) {
                        /**
                         * 這個時候Java沒有進位
                         */
                        formatStr = decf.format(Double.valueOf(formatStr).doubleValue() + Double.valueOf(format.substring(0, format.length() - 1) + "1").
                                doubleValue());
                    }
                }
            }

            return formatStr;
        }
        /**
         * 把一個都money轉換成大寫的money
         *
         * @param d 須要轉換的money
         * @return 換成大寫的money
         */
        public static String capitalValueOf(double d) {
            String lowStr;
            int strLen;
            String currentStr;
            String upperPart;
            String upperStr = "";
            int index = 0;
            int findCount;
            String chns = "零壹貳叄肆伍陸柒捌玖";
            String units = "分角  拾佰仟萬拾佰仟億拾佰仟萬";

            if (d >= 100000000 || d < 0) {
                return "";
            }
            if (d == 0) {
                return "零元整";
            }
            lowStr = trim(formatDoubleToString(d, "0.00"));
            strLen = lowStr.length();
            if (strLen == 0) {
                return "";
            }
            while (index < strLen) {
                currentStr = subString(lowStr, strLen - index - 1, strLen - index);
                if (".".equals(currentStr)) {
                    upperPart = "元";
                } else {
                    upperPart = subString(chns, Integer.valueOf(currentStr).intValue(), Integer.valueOf(currentStr).intValue() + 1);
                }
                upperPart += trim(subString(units, index, index + 1));
                upperStr = upperPart + upperStr;
                index += 1;
            }
            for (; ; ) {
                findCount = 0;
                if (upperStr.indexOf("拾零萬零仟") < 0) {
                    if (upperStr.indexOf("拾零萬") >= 0) {
                        if ("仟".equals(subString(upperStr, upperStr.indexOf("拾零萬") + 4, upperStr.indexOf("拾零萬") + 5))) {
                            findCount++;
                            upperStr = upperStr.replaceFirst("拾零萬", "拾萬零");
                        }
                    }
                }
                if (upperStr.indexOf("零元") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零元", "元");
                }
                if (upperStr.indexOf("零拾") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零拾", "零");
                }
                if (upperStr.indexOf("零佰") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零佰", "零");
                }
                if (upperStr.indexOf("零仟") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零仟", "零");
                }
                if (upperStr.indexOf("零萬") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零萬", "萬");
                }
                if (upperStr.indexOf("零億") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零億", "億");
                }
                if (upperStr.indexOf("零零") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零零", "零");
                }
                if (upperStr.indexOf("零角零分") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零角零分", "整");
                }
                if (upperStr.indexOf("零分") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零分", "整");
                }
                if (upperStr.indexOf("零角") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零角", "零");
                }
                if (upperStr.indexOf("零億零萬零元") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零億零萬零元", "億元");
                }
                if (upperStr.indexOf("億零萬零元") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("億零萬零元", "億元");
                }
                if (upperStr.indexOf("零億零萬") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零億零萬", "億");
                }
                if (upperStr.indexOf("零萬零元") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("零萬零元", "萬元");
                }
                if (upperStr.indexOf("萬零元") >= 0) {
                    findCount++;
                    upperStr = upperStr.replaceAll("萬零元", "萬元");
                }
                if (findCount == 0) {
                    break;
                }
            }
            while ("元".equals(subString(upperStr, 0, 1)) || "零".equals(subString(upperStr, 0, 1)) || "角".equals(subString(upperStr, 0, 1)) || "分".equals(subString(upperStr, 0, 1)) || "整".equals(subString(upperStr, 0, 1))) {
                strLen = upperStr.length();
                upperStr = subString(upperStr, 1, strLen);
            }
            return upperStr;
        }
        public static void main(String[] args){
        }
    }

三.MediaPlayer播放音頻

1.MediaPlayer簡介微信

MediaPlayer實際上是一個封裝的很好的音頻、視頻流媒體操做類,若是查看其源碼,會發現其內部是調用的native方法,既然是一個流媒體操做類,那麼必然涉及到,播放、暫停、中止等操做,實際上MediaPlayer也爲咱們提供了相應的方法來直接操做流媒體。
void start():開始或恢復播放。app

void stop():中止播放。異步

void pause():暫停播放。 maven

經過上面三個方法,只要設定好流媒體數據源,便可在應用中播放流媒體資源,爲了更好的操做流媒體,MediaPlayer還爲咱們提供了一些其餘的方法,這裏列出一些經常使用的,詳細內容參閱官方文檔。
int getDuration():獲取流媒體的總播放時長,單位是毫秒。ide

int getCurrentPosition():獲取當前流媒體的播放的位置,單位是毫秒。oop

void seekTo(int msec):設置當前MediaPlayer的播放位置,單位是毫秒。

void setLooping(boolean looping):設置是否循環播放。

boolean isLooping():判斷是否循環播放。

boolean isPlaying():判斷是否正在播放。

void prepare():同步的方式裝載流媒體文件。

void prepareAsync():異步的方式裝載流媒體文件。

void release ():回收流媒體資源。

void setAudioStreamType(int streamtype):設置播放流媒體類型。

void setWakeMode(Context context, int mode):設置CPU喚醒的狀態。

setNextMediaPlayer(MediaPlayer next):設置當前流媒體播放完畢,下一個播放的MediaPlayer。

在使用start()播放流媒體以前,須要裝載流媒體資源。

2.MediaPlayer實現播報源碼

public class VoiceUtils {
    private static volatile VoiceUtils singleton = null;
    public    boolean IsPlaying;

      MediaPlayer mediaPlayer=null;
    private Context mContext;

    public VoiceUtils(Context context) {
        this.mContext = context.getApplicationContext();
    }

    /**
     * 單例
     * @param context
     * @return
     */
    public static VoiceUtils with(Context context){
        if (singleton == null) {
            synchronized (VoiceUtils.class) {
                if (singleton == null) {
                    singleton = new VoiceUtils(context);
                }
            }
        }
        return singleton;
    }

public void SetIsPlay( boolean IsPlaying){

    this.IsPlaying=IsPlaying;
}

    public boolean GetIsPlay() {
        return IsPlaying;
    }
    public void Play(String stramount,boolean strsuccess)
    {



        String str=null;
        //若是是TRUE  就播放「收款成功」這句話
        if (strsuccess){
     str  =    "$" + PlaySound.capitalValueOf(Double.valueOf(String.format("%.2f", Double.parseDouble(stramount))));
}else {
     str  = PlaySound.capitalValueOf(Double.valueOf(String.format("%.2f", Double.parseDouble(stramount))));

}
        System.out.println("金額的長度 "+str);
        String temp ="";



        try {
            Thread.sleep(1000);
        } catch (InterruptedException e1) {
            // TODO Auto-generated catch block
            e1.printStackTrace();
        }

        PlaySoundList(1,str,str.length());

    }
    public  void PlaySoundList( final int soundindex, final String soundString, final int soundcount)
    {
        singleton.SetIsPlay(true);
        boolean createState=false;
        if(mediaPlayer==null) {
            mediaPlayer = null;
        }
        System.out.println("加載音頻["+soundindex+"]");
        mediaPlayer = createSound(soundindex,soundString);
        createState=true;

        if(createState==true)
            System.out.println("加載音頻成功["+soundindex+"]");
        else
            System.out.println("加載音頻失敗["+soundindex+"]");

        //播放完成觸發此事件
        mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() {
            @Override
            public void onCompletion(MediaPlayer mp) {
                mp.release();//釋放音頻資源
                int newsoundindex =soundindex;
                System.out.println("釋放資源[" +soundindex+"]");
                if(soundindex<soundcount) {
                    newsoundindex=newsoundindex+1;
                    PlaySoundList(newsoundindex, soundString,soundcount);
                }else {
                    singleton.SetIsPlay(false);
                }

            }
        });
        try {
            //在播放音頻資源以前,必須調用Prepare方法完成些準備工做
            if(createState)
                mediaPlayer.prepare();
            else
                mediaPlayer.prepare();
            //開始播放音頻
            mediaPlayer.start();

            System.out.println("播放音頻["+soundindex+"]");
        } catch (IllegalStateException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    public  MediaPlayer createSound(int soundIndex, String soundString){
        MediaPlayer mp=null;

        String soundChar = soundString.substring(soundIndex-1,soundIndex);

        switch (soundChar)
        {
            case "零":
                mp=MediaPlayer.create(mContext,R.raw.sound0);
                break;
            case "壹":
                mp=MediaPlayer.create(mContext,R.raw.sound1);
                break;
            case "貳":
                mp=MediaPlayer.create(mContext,R.raw.sound2);
                break;
            case "叄":
                mp=MediaPlayer.create(mContext,R.raw.sound3);
                break;
            case "肆":
                mp=MediaPlayer.create(mContext,R.raw.sound4);
                break;
            case "伍":
                mp=MediaPlayer.create(mContext,R.raw.sound5);
                break;
            case "陸":
                mp=MediaPlayer.create(mContext,R.raw.sound6);
                break;
            case "柒":
                mp=MediaPlayer.create(mContext,R.raw.sound7);
                break;
            case "捌":
                mp=MediaPlayer.create(mContext,R.raw.sound8);
                break;
            case "玖":
                mp=MediaPlayer.create(mContext,R.raw.sound9);
                break;
            case "拾":
                mp=MediaPlayer.create(mContext,R.raw.soundshi);
                break;
            case "佰":
                mp=MediaPlayer.create(mContext,R.raw.soundbai);
                break;
            case "仟":
                mp=MediaPlayer.create(mContext,R.raw.soundqian);
                break;
            case "角":
                mp=MediaPlayer.create(mContext,R.raw.soundjiao);
                break;
            case "分":
                mp=MediaPlayer.create(mContext,R.raw.soundfen);
                break;
            case "元":
                mp=MediaPlayer.create(mContext,R.raw.soundyuan);
                break;
            case "整":
                mp=MediaPlayer.create(mContext,R.raw.soundzheng);
                break;
            case "萬":
                mp=MediaPlayer.create(mContext,R.raw.soundwan);
                break;
            case "$":
                mp=MediaPlayer.create(mContext,R.raw.soundsuccess);
                break;

        }
        //下面這三句是控制語速,可是隻適用於Android6.0 以上,如下的就會報錯,因此這個功能下次更新時解決
//        PlaybackParams pbp = new PlaybackParams();
//        pbp.setSpeed(1.5F);
//        mp.setPlaybackParams(pbp);
        mp.stop();
        return mp;
    }

}

四.使用

Gradle依賴 -
1.最app外層的build.gradle 添加代碼:

allprojects {
    repositories {
        jcenter()
        maven { url 'https://jitpack.io' }
    }
}

2.在app 的build.gradle中添加:

dependencies {
            compile 'com.github.javaexception:VoiceAnnouncements:v1.2'
    }

使用方法 -
1.普通調用:我想強調的是傳入的金額最多精確到」分」,還有在調用的時候應該進行try-catch由於若是傳入的不是金額,會出現異常的。 若是是true播報語音爲」收款成功+收款金額」,若是是false只播報收款金額。

//普通用法        VoiceUtils.with(this).Play("111",true);

2.防止用戶同時接收多條語音形成語音重疊的調用方法:

private synchronized  void Play(final String str) {

        if (VoiceUtils.with(this).GetIsPlay()){
            System.out.println("正在播放語音 ");
            new Thread() {
                @Override
                public  void run() {
                    super.run();
                    try {
                        Thread.sleep(100);//休眠0.1秒
                        Play(str);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    /**
                     * 要執行的操做
                     */
                }
            }.start();
        }else {
            System.out.println("不衝突");
            VoiceUtils.with(this).Play(str,true);
        }
    }

播報語速的調控問題,如今由於只能支持Android6.0以上的,因此代碼我沒添加,等解決後一塊兒更新。
若是有什麼不清楚的能夠加我公衆號或者加微信,但願對你們有所幫助。

相關文章
相關標籤/搜索