摘要:推薦閱讀封裝之路學(xué)習(xí)資源分享合集最近寫(xiě)了一個(gè)金額的語(yǔ)音播報(bào)功能,已封裝成依賴(lài)庫(kù)到,希望對(duì)大家有所幫助。把要播報(bào)的金額轉(zhuǎn)換成大寫(xiě)的金額,比如零壹貳叁肆伍陸柒捌玖分角拾佰仟萬(wàn)拾佰仟億拾佰仟萬(wàn)的組合。設(shè)置當(dāng)前的播放位置,單位是毫秒。
推薦閱讀:
SurfaceView+MediaPlayer封裝之路
Android學(xué)習(xí)資源分享合集(1)
最近寫(xiě)了一個(gè)金額的語(yǔ)音播報(bào)功能,已封裝成依賴(lài)庫(kù)到Github,希望對(duì)大家有所幫助。
Github地址 :
https://github.com/javaexcept...
思路:
(1).準(zhǔn)備音頻文件。
(2).把要播報(bào)的金額轉(zhuǎn)換成大寫(xiě)的金額,比如"零壹貳叁肆伍陸柒捌玖,分角 拾佰仟萬(wàn)拾佰仟億拾佰仟萬(wàn)"的組合。
(3).通過(guò)MediaPlayer播放音頻。
下面是我音頻文件,里面是大寫(xiě)的數(shù)字,為播報(bào)金額組合做準(zhǔn)備。
二.金額轉(zhuǎn)換public class PlaySound { /** * 截取字符串 * * @param str 需要截取的字符串 * @param idx1 開(kāi)始位置 * @param idx2 截止位置 * @return 截取后的字符串 */ public static String subString(String str, int idx1, int idx2) { try { return str.substring(idx1, idx2); } catch (Exception ex) { return ""; } } /** * 傳遞一個(gè)字符串參數(shù),如果是null返回“”字符串,否則去除前后的空格。 * * @param str 傳入?yún)?shù) * @return 沒(méi)有前后沒(méi)有空格的字符串 */ public static final String trim(String str) { if (str == null) return ""; else return str.trim(); } /** * 把double類(lèi)型數(shù)據(jù)轉(zhuǎn)換成有格式的字符串 * * @param d 需要轉(zhuǎn)換的double類(lèi)型數(shù)據(jù) * @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); /** * 通過(guò)java保留小數(shù)了 * 如果轉(zhuǎn)換前的長(zhǎng)度>轉(zhuǎn)換后的長(zhǎng)度,Java的轉(zhuǎn)換就有可能出錯(cuò) */ if (doubleStr.length() > formatStr.length()) { /** * 如果前面的都一致,但最后一位大于4就需要進(jìn)位 * 否則不進(jìn)位 */ if (formatStr.equals(doubleStr.substring(0, formatStr.length()))) { /** * 取轉(zhuǎn)換前的后一位, * 有可能是“.” */ 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) { /** * 這個(gè)時(shí)候Java沒(méi)有進(jìn)位 */ formatStr = decf.format(Double.valueOf(formatStr).doubleValue() + Double.valueOf(format.substring(0, format.length() - 1) + "1"). doubleValue()); } } } return formatStr; } /** * 把一個(gè)都money轉(zhuǎn)換成大寫(xiě)的money * * @param d 需要轉(zhuǎn)換的money * @return 換成大寫(xiě)的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 = "分角 拾佰仟萬(wàn)拾佰仟億拾佰仟萬(wàn)"; 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("拾零萬(wàn)零仟") < 0) { if (upperStr.indexOf("拾零萬(wàn)") >= 0) { if ("仟".equals(subString(upperStr, upperStr.indexOf("拾零萬(wàn)") + 4, upperStr.indexOf("拾零萬(wàn)") + 5))) { findCount++; upperStr = upperStr.replaceFirst("拾零萬(wàn)", "拾萬(wàn)零"); } } } 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("零萬(wàn)") >= 0) { findCount++; upperStr = upperStr.replaceAll("零萬(wàn)", "萬(wàn)"); } 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("零億零萬(wàn)零元") >= 0) { findCount++; upperStr = upperStr.replaceAll("零億零萬(wàn)零元", "億元"); } if (upperStr.indexOf("億零萬(wàn)零元") >= 0) { findCount++; upperStr = upperStr.replaceAll("億零萬(wàn)零元", "億元"); } if (upperStr.indexOf("零億零萬(wàn)") >= 0) { findCount++; upperStr = upperStr.replaceAll("零億零萬(wàn)", "億"); } if (upperStr.indexOf("零萬(wàn)零元") >= 0) { findCount++; upperStr = upperStr.replaceAll("零萬(wàn)零元", "萬(wàn)元"); } if (upperStr.indexOf("萬(wàn)零元") >= 0) { findCount++; upperStr = upperStr.replaceAll("萬(wàn)零元", "萬(wàn)元"); } 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簡(jiǎn)介
MediaPlayer其實(shí)是一個(gè)封裝的很好的音頻、視頻流媒體操作類(lèi),如果查看其源碼,會(huì)發(fā)現(xiàn)其內(nèi)部是調(diào)用的native方法,既然是一個(gè)流媒體操作類(lèi),那么必然涉及到,播放、暫停、停止等操作,實(shí)際上MediaPlayer也為我們提供了相應(yīng)的方法來(lái)直接操作流媒體。
void start():開(kāi)始或恢復(fù)播放。
void stop():停止播放。
void pause():暫停播放?!?/p>
通過(guò)上面三個(gè)方法,只要設(shè)定好流媒體數(shù)據(jù)源,即可在應(yīng)用中播放流媒體資源,為了更好的操作流媒體,MediaPlayer還為我們提供了一些其他的方法,這里列出一些常用的,詳細(xì)內(nèi)容參閱官方文檔。
int getDuration():獲取流媒體的總播放時(shí)長(zhǎng),單位是毫秒。
int getCurrentPosition():獲取當(dāng)前流媒體的播放的位置,單位是毫秒。
void seekTo(int msec):設(shè)置當(dāng)前MediaPlayer的播放位置,單位是毫秒。
void setLooping(boolean looping):設(shè)置是否循環(huán)播放。
boolean isLooping():判斷是否循環(huán)播放。
boolean isPlaying():判斷是否正在播放。
void prepare():同步的方式裝載流媒體文件。
void prepareAsync():異步的方式裝載流媒體文件。
void release ():回收流媒體資源。
void setAudioStreamType(int streamtype):設(shè)置播放流媒體類(lèi)型。
void setWakeMode(Context context, int mode):設(shè)置CPU喚醒的狀態(tài)。
setNextMediaPlayer(MediaPlayer next):設(shè)置當(dāng)前流媒體播放完畢,下一個(gè)播放的MediaPlayer。
在使用start()播放流媒體之前,需要裝載流媒體資源。
2.MediaPlayer實(shí)現(xiàn)播報(bào)源碼
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 就播放“收款成功”這句話(huà) 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("金額的長(zhǎng)度 "+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+"]"); //播放完成觸發(fā)此事件 mediaPlayer.setOnCompletionListener(new MediaPlayer.OnCompletionListener() { @Override public void onCompletion(MediaPlayer mp) { mp.release();//釋放音頻資源 int newsoundindex =soundindex; System.out.println("釋放資源[" +soundindex+"]"); if(soundindex四.使用 Gradle依賴(lài) -
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.普通調(diào)用:我想強(qiáng)調(diào)的是傳入的金額最多精確到”分”,還有在調(diào)用的時(shí)候應(yīng)該進(jìn)行try-catch因?yàn)槿绻麄魅氲牟皇墙痤~,會(huì)出現(xiàn)異常的。 如果是true播報(bào)語(yǔ)音為”收款成功+收款金額”,如果是false只播報(bào)收款金額。//普通用法 VoiceUtils.with(this).Play("111",true);2.防止用戶(hù)同時(shí)接收多條語(yǔ)音造成語(yǔ)音重疊的調(diào)用方法:
private synchronized void Play(final String str) { if (VoiceUtils.with(this).GetIsPlay()){ System.out.println("正在播放語(yǔ)音 "); new Thread() { @Override public void run() { super.run(); try { Thread.sleep(100);//休眠0.1秒 Play(str); } catch (InterruptedException e) { e.printStackTrace(); } /** * 要執(zhí)行的操作 */ } }.start(); }else { System.out.println("不沖突"); VoiceUtils.with(this).Play(str,true); } }播報(bào)語(yǔ)速的調(diào)控問(wèn)題,現(xiàn)在因?yàn)橹荒苤С諥ndroid6.0以上的,所以代碼我沒(méi)添加,等解決后一起更新。
如果有什么不清楚的可以加我公眾號(hào)或者加微信,希望對(duì)大家有所幫助。
文章版權(quán)歸作者所有,未經(jīng)允許請(qǐng)勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。
轉(zhuǎn)載請(qǐng)注明本文地址:http://m.hztianpu.com/yun/67647.html
摘要:首先先祝大家國(guó)慶節(jié)快樂(lè)今天距離為我運(yùn)營(yíng)公眾號(hào)已經(jīng)一個(gè)月了,今天把文章整合一下,希望對(duì)大家有幫助,也謝謝朋友的支持,我會(huì)繼續(xù)堅(jiān)持原創(chuàng),寫(xiě)更好的文章給大家一視頻獲取學(xué)習(xí)資源分享合集二功能篇實(shí)現(xiàn)金額的語(yǔ)音播報(bào)功能基于模式風(fēng)格的封裝之路炫酷動(dòng)畫(huà)跳 showImg(https://segmentfault.com/img/remote/1460000011437678?w=900&h=500);...
摘要:首先先祝大家國(guó)慶節(jié)快樂(lè)今天距離為我運(yùn)營(yíng)公眾號(hào)已經(jīng)一個(gè)月了,今天把文章整合一下,希望對(duì)大家有幫助,也謝謝朋友的支持,我會(huì)繼續(xù)堅(jiān)持原創(chuàng),寫(xiě)更好的文章給大家一視頻獲取學(xué)習(xí)資源分享合集二功能篇實(shí)現(xiàn)金額的語(yǔ)音播報(bào)功能基于模式風(fēng)格的封裝之路炫酷動(dòng)畫(huà)跳 showImg(https://segmentfault.com/img/remote/1460000011437678?w=900&h=500);...
閱讀 1321·2023-04-25 15:53
閱讀 2168·2021-11-19 09:40
閱讀 3568·2021-10-11 10:59
閱讀 2132·2019-08-30 15:55
閱讀 2029·2019-08-30 15:54
閱讀 2388·2019-08-29 13:03
閱讀 2828·2019-08-28 18:17
閱讀 1572·2019-08-27 10:51