查看原文
其他

MediaPlayer实现金额的语音播报功能

2017-09-28 qzs 安卓干货铺

最近写了一个金额的语音播报功能,已封装成依赖库到Github,希望对大家有所帮助。

Github地址 :

https://github.com/javaexception

思路:

(1).准备音频文件。

(2).把要播报的金额转换成大写的金额,比如"零壹贰叁肆伍陆柒捌玖,分角  拾佰仟万拾佰仟亿拾佰仟万"的组合。

(3).通过MediaPlayer播放音频。


一.准备音频文件


下面是我音频文件,里面是大写的数字,为播报金额组合做准备。



二.金额转换

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 statr():开始或恢复播放。

  • void stop():停止播放。

  • void pause():暂停播放。 

通过上面三个方法,只要设定好流媒体数据源,即可在应用中播放流媒体资源,为了更好的操作流媒体,MediaPlayer还为我们提供了一些其他的方法,这里列出一些常用的,详细内容参阅官方文档。

  • int getDuration():获取流媒体的总播放时长,单位是毫秒。

  • int getCurrentPosition():获取当前流媒体的播放的位置,单位是毫秒。

  • 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以上的,所以代码我没添加,等解决后一起更新。


推荐阅读

 


SurfaceView+MediaPlayer封装之路


Android学习资源分享合集(1)


萤石云视频EZOpenSDK集成(实现播放,视频放大功能)



您可能也对以下帖子感兴趣

文章有问题?点此查看未经处理的缓存