资讯专栏INFORMATION COLUMN

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

ermaoL / 3199人阅读

摘要:推荐阅读封装之路学习资源分享合集最近写了一个金额的语音播报功能,已封装成依赖库到,希望对大家有所帮助。把要播报的金额转换成大写的金额,比如零壹贰叁肆伍陆柒捌玖分角拾佰仟万拾佰仟亿拾佰仟万的组合。设置当前的播放位置,单位是毫秒。

推荐阅读:
SurfaceView+MediaPlayer封装之路
Android学习资源分享合集(1)

最近写了一个金额的语音播报功能,已封装成依赖库到Github,希望对大家有所帮助。
Github地址 :
https://github.com/javaexcept...

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

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

四.使用

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以上的,所以代码我没添加,等解决后一起更新。
如果有什么不清楚的可以加我公众号或者加微信,希望对大家有所帮助。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/67647.html

相关文章

  • 【收藏篇】32篇技术博文汇总(九月总结)

    摘要:首先先祝大家国庆节快乐今天距离为我运营公众号已经一个月了,今天把文章整合一下,希望对大家有帮助,也谢谢朋友的支持,我会继续坚持原创,写更好的文章给大家一视频获取学习资源分享合集二功能篇实现金额的语音播报功能基于模式风格的封装之路炫酷动画跳 showImg(https://segmentfault.com/img/remote/1460000011437678?w=900&h=500);...

    whlong 评论0 收藏0
  • 【收藏篇】32篇技术博文汇总(九月总结)

    摘要:首先先祝大家国庆节快乐今天距离为我运营公众号已经一个月了,今天把文章整合一下,希望对大家有帮助,也谢谢朋友的支持,我会继续坚持原创,写更好的文章给大家一视频获取学习资源分享合集二功能篇实现金额的语音播报功能基于模式风格的封装之路炫酷动画跳 showImg(https://segmentfault.com/img/remote/1460000011437678?w=900&h=500);...

    Eric 评论0 收藏0

发表评论

0条评论

ermaoL

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<