:给;
\ No newline at end of file
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/grammar_sample.abnf b/src/讯飞SDK/sample/speechDemo/src/main/assets/grammar_sample.abnf
new file mode 100644
index 0000000..993856d
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/assets/grammar_sample.abnf
@@ -0,0 +1,8 @@
+#ABNF 1.0 UTF-8;
+language zh-CN;
+mode voice;
+
+root $main;
+$main = $place1 到 $place2;
+$place1 = 北京|武汉|南京|天津|东京;
+$place2 = 上海|合肥;
\ No newline at end of file
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/iattest.wav b/src/讯飞SDK/sample/speechDemo/src/main/assets/iattest.wav
new file mode 100644
index 0000000..fcee567
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/iattest.wav differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/recognize.xml b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/recognize.xml
new file mode 100644
index 0000000..78300c1
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/recognize.xml differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_bg.9.png b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_bg.9.png
new file mode 100644
index 0000000..217f9dc
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_bg.9.png differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_empty.png b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_empty.png
new file mode 100644
index 0000000..08ffc43
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_empty.png differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_full.png b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_full.png
new file mode 100644
index 0000000..4bf5bbc
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/voice_full.png differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/waiting.png b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/waiting.png
new file mode 100644
index 0000000..d13bb33
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/waiting.png differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/warning.png b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/warning.png
new file mode 100644
index 0000000..48150ff
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/iflytek/warning.png differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/isetest.wav b/src/讯飞SDK/sample/speechDemo/src/main/assets/isetest.wav
new file mode 100644
index 0000000..175fd1b
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/isetest.wav differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/keys b/src/讯飞SDK/sample/speechDemo/src/main/assets/keys
new file mode 100644
index 0000000..34039f1
Binary files /dev/null and b/src/讯飞SDK/sample/speechDemo/src/main/assets/keys differ
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/assets/userwords b/src/讯飞SDK/sample/speechDemo/src/main/assets/userwords
new file mode 100644
index 0000000..7c107cc
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/assets/userwords
@@ -0,0 +1 @@
+{"userword":[{"name":"我的常用词","words":["佳晨实业","蜀南庭苑","高兰路","复联二"]},{"name":"我的好友","words":["李馨琪","鹿晓雷","张集栋","周家莉","叶震珂","熊泽萌"]}]}
\ No newline at end of file
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/FinalResult.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/FinalResult.java
new file mode 100644
index 0000000..44c2d87
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/FinalResult.java
@@ -0,0 +1,23 @@
+/**
+ *
+ */
+package com.iflytek.ise.result;
+
+/**
+ * Title: FinalResult
+ * Description:
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月14日 上午11:12:58
+ */
+public class FinalResult extends Result {
+
+ public int ret;
+
+ public float total_score;
+
+ @Override
+ public String toString() {
+ return "返回值:" + ret + ",总分:" + total_score;
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadSentenceResult.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadSentenceResult.java
new file mode 100644
index 0000000..289a53c
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadSentenceResult.java
@@ -0,0 +1,45 @@
+/**
+ *
+ */
+package com.iflytek.ise.result;
+
+import com.iflytek.ise.result.util.ResultFormatUtil;
+
+/**
+ * Title: ReadSentenceResult
+ * Description:
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午5:04:14
+ */
+public class ReadSentenceResult extends Result {
+
+ public ReadSentenceResult() {
+ category = "read_sentence";
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+
+ if ("cn".equals(language)) {
+ buffer.append("[总体结果]\n")
+ .append("评测内容:" + content + "\n")
+ .append("朗读时长:" + time_len + "\n")
+ .append("总分:" + total_score + "\n\n")
+ .append("[朗读详情]").append(ResultFormatUtil.formatDetails_CN(sentences));
+ } else {
+ if (is_rejected) {
+ buffer.append("检测到乱读,")
+ .append("except_info:" + except_info + "\n\n"); // except_info代码说明详见《语音评测参数、结果说明文档》
+ }
+
+ buffer.append("[总体结果]\n")
+ .append("评测内容:" + content + "\n")
+ .append("总分:" + total_score + "\n\n")
+ .append("[朗读详情]").append(ResultFormatUtil.formatDetails_EN(sentences));
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadSyllableResult.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadSyllableResult.java
new file mode 100644
index 0000000..efab1f1
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadSyllableResult.java
@@ -0,0 +1,33 @@
+/**
+ *
+ */
+package com.iflytek.ise.result;
+
+import com.iflytek.ise.result.util.ResultFormatUtil;
+
+/**
+ * Title: ReadSyllableResult
+ * Description: 中文单字评测结果
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午5:03:14
+ */
+public class ReadSyllableResult extends Result {
+
+ public ReadSyllableResult() {
+ language = "cn";
+ category = "read_syllable";
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+ buffer.append("[总体结果]\n")
+ .append("评测内容:" + content + "\n")
+ .append("朗读时长:" + time_len + "\n")
+ .append("总分:" + total_score + "\n\n")
+ .append("[朗读详情]").append(ResultFormatUtil.formatDetails_CN(sentences));
+
+ return buffer.toString();
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadWordResult.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadWordResult.java
new file mode 100644
index 0000000..130f797
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/ReadWordResult.java
@@ -0,0 +1,47 @@
+/**
+ *
+ */
+package com.iflytek.ise.result;
+
+import com.iflytek.ise.result.util.ResultFormatUtil;
+
+/**
+ * Title: ReadWordResult
+ * Description:
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午5:03:50
+ */
+public class ReadWordResult extends Result {
+
+ public ReadWordResult() {
+ category = "read_word";
+ }
+
+ @Override
+ public String toString() {
+ StringBuffer buffer = new StringBuffer();
+
+ if ("cn".equals(language)) {
+ buffer.append("[总体结果]\n")
+ .append("评测内容:" + content + "\n")
+ .append("朗读时长:" + time_len + "\n")
+ .append("总分:" + total_score + "\n\n")
+ .append("[朗读详情]")
+ .append(ResultFormatUtil.formatDetails_CN(sentences));
+ } else {
+ if (is_rejected) {
+ buffer.append("检测到乱读,")
+ .append("except_info:" + except_info + "\n\n"); // except_info代码说明详见《语音评测参数、结果说明文档》
+ }
+
+ buffer.append("[总体结果]\n")
+ .append("评测内容:" + content + "\n")
+ .append("总分:" + total_score + "\n\n")
+ .append("[朗读详情]")
+ .append(ResultFormatUtil.formatDetails_EN(sentences));
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/Result.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/Result.java
new file mode 100644
index 0000000..0c6cf5a
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/Result.java
@@ -0,0 +1,58 @@
+/**
+ *
+ */
+package com.iflytek.ise.result;
+
+import com.iflytek.ise.result.entity.Sentence;
+
+import java.util.ArrayList;
+
+/**
+ * Title: Result
+ * Description: 评测结果
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午4:58:38
+ */
+public class Result {
+ /**
+ * 评测语种:en(英文)、cn(中文)
+ */
+ public String language;
+ /**
+ * 评测种类:read_syllable(cn单字)、read_word(词语)、read_sentence(句子)
+ */
+ public String category;
+ /**
+ * 开始帧位置,每帧相当于10ms
+ */
+ public int beg_pos;
+ /**
+ * 结束帧位置
+ */
+ public int end_pos;
+ /**
+ * 评测内容
+ */
+ public String content;
+ /**
+ * 总得分
+ */
+ public float total_score;
+ /**
+ * 时长(cn)
+ */
+ public int time_len;
+ /**
+ * 异常信息(en)
+ */
+ public String except_info;
+ /**
+ * 是否乱读(cn)
+ */
+ public boolean is_rejected;
+ /**
+ * xml结果中的sentence标签
+ */
+ public ArrayList sentences;
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Phone.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Phone.java
new file mode 100644
index 0000000..df9eff1
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Phone.java
@@ -0,0 +1,105 @@
+/**
+ *
+ */
+package com.iflytek.ise.result.entity;
+
+import java.util.HashMap;
+
+/**
+ * Title: Phone
+ * Description: 音素,对应于xml结果中的Phone标签
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午3:55:56
+ */
+public class Phone {
+ /**
+ * 讯飞音标-标准音标映射表(en)
+ */
+ public static HashMap phone_map = new HashMap();
+
+ static {
+ phone_map.put("aa", "ɑ:");
+ phone_map.put("oo", "ɔ");
+ phone_map.put("ae", "æ");
+ phone_map.put("ah", "ʌ");
+ phone_map.put("ao", "ɔ:");
+ phone_map.put("aw", "aʊ");
+ phone_map.put("ax", "ə");
+ phone_map.put("ay", "aɪ");
+ phone_map.put("eh", "e");
+ phone_map.put("er", "ə:");
+ phone_map.put("ey", "eɪ");
+ phone_map.put("ih", "ɪ");
+ phone_map.put("iy", "i:");
+ phone_map.put("ow", "əʊ");
+ phone_map.put("oy", "ɔɪ");
+ phone_map.put("uh", "ʊ");
+ phone_map.put("uw", "ʊ:");
+ phone_map.put("ch", "tʃ");
+ phone_map.put("dh", "ð");
+ phone_map.put("hh", "h");
+ phone_map.put("jh", "dʒ");
+ phone_map.put("ng", "ŋ");
+ phone_map.put("sh", "ʃ");
+ phone_map.put("th", "θ");
+ phone_map.put("zh", "ʒ");
+ phone_map.put("y", "j");
+ phone_map.put("d", "d");
+ phone_map.put("k", "k");
+ phone_map.put("l", "l");
+ phone_map.put("m", "m");
+ phone_map.put("n", "n");
+ phone_map.put("b", "b");
+ phone_map.put("f", "f");
+ phone_map.put("g", "g");
+ phone_map.put("p", "p");
+ phone_map.put("r", "r");
+ phone_map.put("s", "s");
+ phone_map.put("t", "t");
+ phone_map.put("v", "v");
+ phone_map.put("w", "w");
+ phone_map.put("z", "z");
+ phone_map.put("ar", "eə");
+ phone_map.put("ir", "iə");
+ phone_map.put("ur", "ʊə");
+ phone_map.put("tr", "tr");
+ phone_map.put("dr", "dr");
+ phone_map.put("ts", "ts");
+ phone_map.put("dz", "dz");
+ }
+
+ /**
+ * 开始帧位置,每帧相当于10ms
+ */
+ public int beg_pos;
+ /**
+ * 结束帧位置
+ */
+ public int end_pos;
+ /**
+ * 音素内容
+ */
+ public String content;
+ /**
+ * 增漏读信息:0(正确),16(漏读),32(增读),64(回读),128(替换)
+ */
+ public int dp_message;
+ /**
+ * 时长(单位:帧,每帧相当于10ms)(cn)
+ */
+ public int time_len;
+
+ /**
+ * 得到content对应的标准音标(en)
+ */
+ public String getStdSymbol() {
+ return getStdSymbol(content);
+ }
+
+ public static String getStdSymbol(String content) {
+ String std = phone_map.get(content);
+ return (null == std) ? content : std;
+ }
+
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Sentence.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Sentence.java
new file mode 100644
index 0000000..00ec451
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Sentence.java
@@ -0,0 +1,48 @@
+/**
+ *
+ */
+package com.iflytek.ise.result.entity;
+
+import java.util.ArrayList;
+
+/**
+ * Title: Sentence
+ * Description: 句子,对应于xml结果中的sentence标签
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午4:10:09
+ */
+public class Sentence {
+ /**
+ * 开始帧位置,每帧相当于10ms
+ */
+ public int beg_pos;
+ /**
+ * 结束帧位置
+ */
+ public int end_pos;
+ /**
+ * 句子内容
+ */
+ public String content;
+ /**
+ * 总得分
+ */
+ public float total_score;
+ /**
+ * 时长(单位:帧,每帧相当于10ms)(cn)
+ */
+ public int time_len;
+ /**
+ * 句子的索引(en)
+ */
+ public int index;
+ /**
+ * 单词数(en)
+ */
+ public int word_count;
+ /**
+ * sentence包括的word
+ */
+ public ArrayList words;
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Syll.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Syll.java
new file mode 100644
index 0000000..562b04c
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Syll.java
@@ -0,0 +1,60 @@
+/**
+ *
+ */
+package com.iflytek.ise.result.entity;
+
+import java.util.ArrayList;
+
+/**
+ * Title: Syll
+ * Description: 音节,对应于结果xml中的Syll标签
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午3:49:51
+ */
+public class Syll {
+ /**
+ * 开始帧位置,每帧相当于10ms
+ */
+ public int beg_pos;
+ /**
+ * 结束帧位置
+ */
+ public int end_pos;
+ /**
+ * 音节内容
+ */
+ public String content;
+ /**
+ * 拼音(cn),数字代表声调,5表示轻声,如fen1
+ */
+ public String symbol;
+ /**
+ * 增漏读信息:0(正确),16(漏读),32(增读),64(回读),128(替换)
+ */
+ public int dp_message;
+ /**
+ * 时长(单位:帧,每帧相当于10ms)(cn)
+ */
+ public int time_len;
+ /**
+ * Syll包含的音节
+ */
+ public ArrayList phones;
+
+ /**
+ * 获取音节的标准音标(en)
+ *
+ * @return 标准音标
+ */
+ public String getStdSymbol() {
+ String stdSymbol = "";
+ String[] symbols = content.split(" ");
+
+ for (int i = 0; i < symbols.length; i++) {
+ stdSymbol += Phone.getStdSymbol(symbols[i]);
+ }
+
+ return stdSymbol;
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Word.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Word.java
new file mode 100644
index 0000000..9cc6893
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/entity/Word.java
@@ -0,0 +1,57 @@
+/**
+ *
+ */
+package com.iflytek.ise.result.entity;
+
+import java.util.ArrayList;
+
+/**
+ * Title: Word
+ * Description: 单词,对应于结果xml中的word标签
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午3:29:30
+ */
+public class Word {
+ /**
+ * 开始帧位置,每帧相当于10ms
+ */
+ public int beg_pos;
+ /**
+ * 结束帧位置
+ */
+ public int end_pos;
+ /**
+ * 单词内容
+ */
+ public String content;
+ /**
+ * 增漏读信息:0(正确),16(漏读),32(增读),64(回读),128(替换)
+ */
+ public int dp_message;
+ /**
+ * 单词在全篇索引(en)
+ */
+ public int global_index;
+ /**
+ * 单词在句子中的索引(en)
+ */
+ public int index;
+ /**
+ * 拼音(cn),数字代表声调,5表示轻声,如fen1
+ */
+ public String symbol;
+ /**
+ * 时长(单位:帧,每帧相当于10ms)(cn)
+ */
+ public int time_len;
+ /**
+ * 单词得分(en)
+ */
+ public float total_score;
+ /**
+ * Word包含的Syll
+ */
+ public ArrayList sylls;
+
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/util/ResultFormatUtil.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/util/ResultFormatUtil.java
new file mode 100644
index 0000000..f4b5405
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/util/ResultFormatUtil.java
@@ -0,0 +1,122 @@
+/**
+ *
+ */
+package com.iflytek.ise.result.util;
+
+import com.iflytek.ise.result.entity.Phone;
+import com.iflytek.ise.result.entity.Sentence;
+import com.iflytek.ise.result.entity.Syll;
+import com.iflytek.ise.result.entity.Word;
+
+import java.util.ArrayList;
+
+/**
+ * Title: ResultFormatUtl
+ * Description:
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月19日 上午10:01:14
+ */
+public class ResultFormatUtil {
+
+ /**
+ * 将英语评测详情按格式输出
+ *
+ * @param sentences
+ * @return 英语评测详情
+ */
+ public static String formatDetails_EN(ArrayList sentences) {
+ StringBuffer buffer = new StringBuffer();
+ if (null == sentences) {
+ return buffer.toString();
+ }
+
+ for (Sentence sentence : sentences) {
+ if ("噪音".equals(ResultTranslateUtil.getContent(sentence.content))
+ || "静音".equals(ResultTranslateUtil.getContent(sentence.content))) {
+ continue;
+ }
+
+ if (null == sentence.words) {
+ continue;
+ }
+ for (Word word : sentence.words) {
+ if ("噪音".equals(ResultTranslateUtil.getContent(word.content))
+ || "静音".equals(ResultTranslateUtil.getContent(word.content))) {
+ continue;
+ }
+
+ buffer.append("\n单词[" + ResultTranslateUtil.getContent(word.content) + "] ")
+ .append("朗读:" + ResultTranslateUtil.getDpMessageInfo(word.dp_message))
+ .append(" 得分:" + word.total_score);
+ if (null == word.sylls) {
+ buffer.append("\n");
+ continue;
+ }
+
+ for (Syll syll : word.sylls) {
+ buffer.append("\n└音节[" + ResultTranslateUtil.getContent(syll.getStdSymbol()) + "] ");
+ if (null == syll.phones) {
+ continue;
+ }
+
+ for (Phone phone : syll.phones) {
+ buffer.append("\n\t└音素[" + ResultTranslateUtil.getContent(phone.getStdSymbol()) + "] ")
+ .append(" 朗读:" + ResultTranslateUtil.getDpMessageInfo(phone.dp_message));
+ }
+
+ }
+ buffer.append("\n");
+ }
+ }
+
+ return buffer.toString();
+ }
+
+ /**
+ * 将汉语评测详情按格式输出
+ *
+ * @param sentences
+ * @return 汉语评测详情
+ */
+ public static String formatDetails_CN(ArrayList sentences) {
+ StringBuffer buffer = new StringBuffer();
+ if (null == sentences) {
+ return buffer.toString();
+ }
+
+ for (Sentence sentence : sentences) {
+ if (null == sentence.words) {
+ continue;
+ }
+
+ for (Word word : sentence.words) {
+ buffer.append("\n词语[" + ResultTranslateUtil.getContent(word.content) + "] " + word.symbol + " 时长:" + word.time_len);
+ if (null == word.sylls) {
+ continue;
+ }
+
+ for (Syll syll : word.sylls) {
+ if ("噪音".equals(ResultTranslateUtil.getContent(syll.content))
+ || "静音".equals(ResultTranslateUtil.getContent(syll.content))) {
+ continue;
+ }
+
+ buffer.append("\n└音节[" + ResultTranslateUtil.getContent(syll.content) + "] " + syll.symbol + " 时长:" + syll.time_len);
+ if (null == syll.phones) {
+ continue;
+ }
+
+ for (Phone phone : syll.phones) {
+ buffer.append("\n\t└音素[" + ResultTranslateUtil.getContent(phone.content) + "] " + "时长:" + phone.time_len)
+ .append(" 朗读:" + ResultTranslateUtil.getDpMessageInfo(phone.dp_message));
+ }
+
+ }
+ buffer.append("\n");
+ }
+ }
+
+ return buffer.toString();
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/util/ResultTranslateUtil.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/util/ResultTranslateUtil.java
new file mode 100644
index 0000000..0858321
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/util/ResultTranslateUtil.java
@@ -0,0 +1,40 @@
+/**
+ *
+ */
+package com.iflytek.ise.result.util;
+
+import java.util.HashMap;
+
+/**
+ * Title: ResultTranslateUtl
+ * Description:
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月13日 下午6:05:03
+ */
+public class ResultTranslateUtil {
+
+ private static HashMap dp_message_map = new HashMap();
+ private static HashMap special_content_map = new HashMap();
+
+ static {
+ dp_message_map.put(0, "正常");
+ dp_message_map.put(16, "漏读");
+ dp_message_map.put(32, "增读");
+ dp_message_map.put(64, "回读");
+ dp_message_map.put(128, "替换");
+
+ special_content_map.put("sil", "静音");
+ special_content_map.put("silv", "静音");
+ special_content_map.put("fil", "噪音");
+ }
+
+ public static String getDpMessageInfo(int dp_message) {
+ return dp_message_map.get(dp_message);
+ }
+
+ public static String getContent(String content) {
+ String val = special_content_map.get(content);
+ return (null == val) ? content : val;
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/xml/XmlResultParser.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/xml/XmlResultParser.java
new file mode 100644
index 0000000..3d32fef
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/ise/result/xml/XmlResultParser.java
@@ -0,0 +1,279 @@
+/**
+ *
+ */
+package com.iflytek.ise.result.xml;
+
+import android.text.TextUtils;
+import android.util.Xml;
+
+import com.iflytek.ise.result.FinalResult;
+import com.iflytek.ise.result.ReadSentenceResult;
+import com.iflytek.ise.result.ReadSyllableResult;
+import com.iflytek.ise.result.ReadWordResult;
+import com.iflytek.ise.result.Result;
+import com.iflytek.ise.result.entity.Phone;
+import com.iflytek.ise.result.entity.Sentence;
+import com.iflytek.ise.result.entity.Syll;
+import com.iflytek.ise.result.entity.Word;
+
+import org.xmlpull.v1.XmlPullParser;
+import org.xmlpull.v1.XmlPullParserException;
+
+import java.io.ByteArrayInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+/**
+ * Title: XmlResultParser
+ * Description:
+ * Company: www.iflytek.com
+ * @author iflytek
+ * @date 2015年1月12日 下午5:21:53
+ */
+public class XmlResultParser {
+
+ public Result parse(String xml) {
+ if (TextUtils.isEmpty(xml)) {
+ return null;
+ }
+
+ XmlPullParser pullParser = Xml.newPullParser();
+
+ try {
+ InputStream ins = new ByteArrayInputStream(xml.getBytes());
+ pullParser.setInput(ins, "utf-8");
+ FinalResult finalResult = null;
+
+ int eventType = pullParser.getEventType();
+ while (XmlPullParser.END_DOCUMENT != eventType) {
+ switch (eventType) {
+ case XmlPullParser.START_TAG:
+ if ("FinalResult".equals(pullParser.getName())) {
+ // 只有一个总分的结果
+ finalResult = new FinalResult();
+ } else if ("ret".equals(pullParser.getName())) {
+ finalResult.ret = getInt(pullParser, "value");
+ } else if ("total_score".equals(pullParser.getName())) {
+ finalResult.total_score = getFloat(pullParser, "value");
+ } else if ("xml_result".equals(pullParser.getName())) {
+ // 详细结果
+ return parseResult(pullParser);
+ }
+
+ break;
+ case XmlPullParser.END_TAG:
+ if ("FinalResult".equals(pullParser.getName())) {
+ return finalResult;
+ }
+ break;
+
+ default:
+ break;
+ }
+ eventType = pullParser.next();
+ }
+ } catch (XmlPullParserException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+ private Result parseResult(XmlPullParser pullParser) {
+ Result result = null;
+ // 标签是否已扫描到
+ boolean rec_paperPassed = false;
+ Sentence sentence = null;
+ Word word = null;
+ Syll syll = null;
+ Phone phone = null;
+
+ int eventType;
+ try {
+ eventType = pullParser.getEventType();
+ while (XmlPullParser.END_DOCUMENT != eventType) {
+ switch (eventType) {
+ case XmlPullParser.START_TAG:
+ if ("rec_paper".equals(pullParser.getName())) {
+ rec_paperPassed = true;
+ } else if ("read_syllable".equals(pullParser.getName())) {
+ if (!rec_paperPassed) {
+ result = new ReadSyllableResult();
+ } else {
+ readTotalResult(result, pullParser);
+ }
+ } else if ("read_word".equals(pullParser.getName())) {
+ if (!rec_paperPassed) {
+ result = new ReadWordResult();
+ String lan = getLanguage(pullParser);
+ result.language = (null == lan) ? "cn" : lan;
+ } else {
+ readTotalResult(result, pullParser);
+ }
+ } else if ("read_sentence".equals(pullParser.getName()) ||
+ "read_chapter".equals(pullParser.getName())) {
+ if (!rec_paperPassed) {
+ result = new ReadSentenceResult();
+ String lan = getLanguage(pullParser);
+ result.language = (null == lan) ? "cn" : lan;
+ } else {
+ readTotalResult(result, pullParser);
+ }
+ } else if ("sentence".equals(pullParser.getName())) {
+ if (null == result.sentences) {
+ result.sentences = new ArrayList();
+ }
+ sentence = createSentence(pullParser);
+ } else if ("word".equals(pullParser.getName())) {
+ if (null != sentence && null == sentence.words) {
+ sentence.words = new ArrayList();
+ }
+ word = createWord(pullParser);
+ } else if ("syll".equals(pullParser.getName())) {
+ if (null != word && null == word.sylls) {
+ word.sylls = new ArrayList();
+ }
+ syll = createSyll(pullParser);
+ } else if ("phone".equals(pullParser.getName())) {
+ if (null != syll && null == syll.phones) {
+ syll.phones = new ArrayList();
+ }
+ phone = createPhone(pullParser);
+ }
+
+ break;
+ case XmlPullParser.END_TAG:
+ if ("phone".equals(pullParser.getName())) {
+ syll.phones.add(phone);
+ } else if ("syll".equals(pullParser.getName())) {
+ word.sylls.add(syll);
+ } else if ("word".equals(pullParser.getName())) {
+ sentence.words.add(word);
+ } else if ("sentence".equals(pullParser.getName())) {
+ result.sentences.add(sentence);
+ } else if ("read_syllable".equals(pullParser.getName())
+ || "read_word".equals(pullParser.getName())
+ || "read_sentence".equals(pullParser.getName())) {
+ return result;
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ eventType = pullParser.next();
+ }
+ } catch (XmlPullParserException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
+ return result;
+ }
+
+ private void readTotalResult(Result result, XmlPullParser pullParser) {
+ result.beg_pos = getInt(pullParser, "beg_pos");
+ result.end_pos = getInt(pullParser, "end_pos");
+ result.content = getContent(pullParser);
+ result.total_score = getFloat(pullParser, "total_score");
+ result.time_len = getInt(pullParser, "time_len");
+ result.except_info = getExceptInfo(pullParser);
+ result.is_rejected = getIsRejected(pullParser);
+ }
+
+ private Phone createPhone(XmlPullParser pullParser) {
+ Phone phone;
+ phone = new Phone();
+ phone.beg_pos = getInt(pullParser, "beg_pos");
+ phone.end_pos = getInt(pullParser, "end_pos");
+ phone.content = getContent(pullParser);
+ phone.dp_message = getInt(pullParser, "dp_message");
+ phone.time_len = getInt(pullParser, "time_len");
+ return phone;
+ }
+
+ private Syll createSyll(XmlPullParser pullParser) {
+ Syll syll;
+ syll = new Syll();
+ syll.beg_pos = getInt(pullParser, "beg_pos");
+ syll.end_pos = getInt(pullParser, "end_pos");
+ syll.content = getContent(pullParser);
+ syll.symbol = getSymbol(pullParser);
+ syll.dp_message = getInt(pullParser, "dp_message");
+ syll.time_len = getInt(pullParser, "time_len");
+ return syll;
+ }
+
+ private Word createWord(XmlPullParser pullParser) {
+ Word word;
+ word = new Word();
+ word.beg_pos = getInt(pullParser, "beg_pos");
+ word.end_pos = getInt(pullParser, "end_pos");
+ word.content = getContent(pullParser);
+ word.symbol = getSymbol(pullParser);
+ word.time_len = getInt(pullParser, "time_len");
+ word.dp_message = getInt(pullParser, "dp_message");
+ word.total_score = getFloat(pullParser, "total_score");
+ word.global_index = getInt(pullParser, "global_index");
+ word.index = getInt(pullParser, "index");
+ return word;
+ }
+
+ private Sentence createSentence(XmlPullParser pullParser) {
+ Sentence sentence;
+ sentence = new Sentence();
+ sentence.beg_pos = getInt(pullParser, "beg_pos");
+ sentence.end_pos = getInt(pullParser, "end_pos");
+ sentence.content = getContent(pullParser);
+ sentence.time_len = getInt(pullParser, "time_len");
+ sentence.index = getInt(pullParser, "index");
+ sentence.word_count = getInt(pullParser, "word_count");
+ return sentence;
+ }
+
+ private String getLanguage(XmlPullParser pullParser) {
+ return pullParser.getAttributeValue(null, "lan");
+ }
+
+ private String getExceptInfo(XmlPullParser pullParser) {
+ return pullParser.getAttributeValue(null, "except_info");
+ }
+
+ private boolean getIsRejected(XmlPullParser pullParser) {
+ String isRejected = pullParser.getAttributeValue(null, "is_rejected");
+ if (null == isRejected) {
+ return false;
+ }
+
+ return Boolean.parseBoolean(isRejected);
+ }
+
+ private String getSymbol(XmlPullParser pullParser) {
+ return pullParser.getAttributeValue(null, "symbol");
+ }
+
+ private float getFloat(XmlPullParser pullParser, String attrName) {
+ String val = pullParser.getAttributeValue(null, attrName);
+ if (null == val) {
+ return 0f;
+ }
+ return Float.parseFloat(val);
+ }
+
+ private String getContent(XmlPullParser pullParser) {
+ return pullParser.getAttributeValue(null, "content");
+ }
+
+ private int getInt(XmlPullParser pullParser, String attrName) {
+ String val = pullParser.getAttributeValue(null, attrName);
+ if (null == val) {
+ return 0;
+ }
+ return Integer.parseInt(val);
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/IatSettings.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/IatSettings.java
new file mode 100644
index 0000000..fc8cfdf
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/IatSettings.java
@@ -0,0 +1,40 @@
+package com.iflytek.speech.setting;
+
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceActivity;
+import android.view.Window;
+
+import com.iflytek.speech.util.SettingTextWatcher;
+import com.iflytek.videoDemo.R;
+
+/**
+ * 听写设置界面
+ */
+public class IatSettings extends PreferenceActivity implements OnPreferenceChangeListener {
+
+ public static final String PREFER_NAME = "com.iflytek.setting";
+ private EditTextPreference mVadbosPreference;
+ private EditTextPreference mVadeosPreference;
+
+ @SuppressWarnings("deprecation")
+ public void onCreate(Bundle savedInstanceState) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ super.onCreate(savedInstanceState);
+ getPreferenceManager().setSharedPreferencesName(PREFER_NAME);
+ addPreferencesFromResource(R.xml.iat_setting);
+
+ mVadbosPreference = (EditTextPreference) findPreference("iat_vadbos_preference");
+ mVadbosPreference.getEditText().addTextChangedListener(new SettingTextWatcher(IatSettings.this, mVadbosPreference, 0, 10000));
+
+ mVadeosPreference = (EditTextPreference) findPreference("iat_vadeos_preference");
+ mVadeosPreference.getEditText().addTextChangedListener(new SettingTextWatcher(IatSettings.this, mVadeosPreference, 0, 10000));
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ return true;
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/IseSettings.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/IseSettings.java
new file mode 100644
index 0000000..c2fb23f
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/IseSettings.java
@@ -0,0 +1,243 @@
+/**
+ *
+ */
+package com.iflytek.speech.setting;
+
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceActivity;
+import android.text.InputType;
+import android.text.TextUtils;
+import android.view.Window;
+import android.widget.Toast;
+
+import com.iflytek.cloud.SpeechConstant;
+import com.iflytek.voicedemo.R;
+
+import java.util.HashMap;
+
+/**
+ * 评测设置界面
+ */
+public class IseSettings extends PreferenceActivity {
+ private final static String PREFER_NAME = "ise_settings";
+
+ private ListPreference mLanguagePref;
+ private ListPreference mCategoryPref;
+ private ListPreference mResultLevelPref;
+ private EditTextPreference mVadBosPref;
+ private EditTextPreference mVadEosPref;
+ private EditTextPreference mSpeechTimeoutPref;
+
+ private Toast mToast;
+
+ private HashMap zhMap = new HashMap<>();
+ private HashMap enMap = new HashMap<>();
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ super.onCreate(savedInstanceState);
+
+ getPreferenceManager().setSharedPreferencesName(PREFER_NAME);
+ addPreferencesFromResource(R.xml.ise_settings);
+ initCategoryMap();
+ initUI();
+ }
+
+ private void initCategoryMap() {
+ zhMap.put("read_syllable", "单字");
+ zhMap.put("read_word", "词语");
+ zhMap.put("read_sentence", "句子");
+ zhMap.put("read_chapter", "篇章");
+
+ enMap.put("read_word", "词语");
+ enMap.put("read_sentence", "句子");
+ enMap.put("read_chapter", "篇章");
+ enMap.put("simple_expression", "英文情景反应");
+ enMap.put("read_choice", "英文选择题");
+ enMap.put("topic", "英文自由题");
+ enMap.put("retell", "英文复述题");
+ enMap.put("picture_talk", "英文看图说话");
+ enMap.put("oral_translation", "英文口头翻译");
+ }
+
+ private void initUI() {
+ mLanguagePref = (ListPreference) findPreference(SpeechConstant.LANGUAGE);
+ mCategoryPref = (ListPreference) findPreference(SpeechConstant.ISE_CATEGORY);
+ mResultLevelPref = (ListPreference) findPreference(SpeechConstant.RESULT_LEVEL);
+ mVadBosPref = (EditTextPreference) findPreference(SpeechConstant.VAD_BOS);
+ mVadEosPref = (EditTextPreference) findPreference(SpeechConstant.VAD_EOS);
+ mSpeechTimeoutPref = (EditTextPreference) findPreference(SpeechConstant.KEY_SPEECH_TIMEOUT);
+
+ mToast = Toast.makeText(IseSettings.this, "", Toast.LENGTH_LONG);
+
+ mLanguagePref.setSummary("当前:" + mLanguagePref.getEntry());
+ mCategoryPref.setSummary("当前:" + mCategoryPref.getEntry());
+ mResultLevelPref.setSummary("当前:" + mResultLevelPref.getEntry());
+ mVadBosPref.setSummary("当前:" + mVadBosPref.getText() + "ms");
+ mVadEosPref.setSummary("当前:" + mVadEosPref.getText() + "ms");
+
+ String speech_timeout = mSpeechTimeoutPref.getText();
+ String summary = "当前:" + speech_timeout;
+ if (!"-1".equals(speech_timeout)) {
+ summary += "ms";
+ }
+ mSpeechTimeoutPref.setSummary(summary);
+
+ mLanguagePref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+
+ String categoryValue = mCategoryPref.getValue();
+
+ if ("zh_cn".equals(newValue.toString())) {
+ // 中文
+ if ("plain".equals(mResultLevelPref.getValue())) {
+ showTip("汉语评测结果格式不支持plain设置");
+ return false;
+ }
+ if (!zhMap.containsKey(categoryValue)) {
+ showTip("中文评测不支持" + enMap.get(categoryValue));
+ return false;
+ }
+ } else {
+ // 英文
+ if (!enMap.containsKey(categoryValue)) {
+ showTip("英语评测不支持" + zhMap.get(categoryValue));
+ return false;
+ }
+ }
+
+ int newValueIndex = mLanguagePref.findIndexOfValue(newValue.toString());
+ String newEntry = (String) mLanguagePref.getEntries()[newValueIndex];
+ mLanguagePref.setSummary("当前:" + newEntry);
+ return true;
+ }
+ });
+
+ mCategoryPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ String categoryValue = newValue.toString();
+
+ if ("en_us".equals(mLanguagePref.getValue())) {
+ if (!enMap.containsKey(categoryValue)) {
+ showTip("英语评测不支持" + zhMap.get(categoryValue) + ",请选其他项");
+ return false;
+ }
+ }
+ if ("zh_cn".equals(mLanguagePref.getValue())) {
+ if (!zhMap.containsKey(categoryValue)) {
+ showTip("中文评测不支持" + enMap.get(categoryValue) + ",请选其他项");
+ return false;
+ }
+ }
+
+ int newValueIndex = mCategoryPref.findIndexOfValue(newValue.toString());
+ String newEntry = (String) mCategoryPref.getEntries()[newValueIndex];
+ mCategoryPref.setSummary("当前:" + newEntry);
+ return true;
+ }
+ });
+
+ mResultLevelPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ if ("zh_cn".equals(mLanguagePref.getValue()) && "plain".equals(newValue.toString())) {
+ showTip("汉语评测不支持plain,请选其他项");
+ return false;
+ }
+
+ mResultLevelPref.setSummary("当前:" + newValue.toString());
+ return true;
+ }
+ });
+
+ mVadBosPref.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
+ mVadBosPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ int bos;
+ try {
+ bos = Integer.parseInt(newValue.toString());
+ } catch (Exception e) {
+ showTip("无效输入!");
+ return false;
+ }
+ if (bos < 0 || bos > 30000) {
+ showTip("取值范围为0~30000");
+ return false;
+ }
+
+ mVadBosPref.setSummary("当前:" + bos + "ms");
+ return true;
+ }
+ });
+
+ mVadEosPref.getEditText().setInputType(InputType.TYPE_CLASS_NUMBER);
+ mVadEosPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ int eos;
+ try {
+ eos = Integer.parseInt(newValue.toString());
+ } catch (Exception e) {
+ showTip("无效输入!");
+ return false;
+ }
+ if (eos < 0 || eos > 30000) {
+ showTip("取值范围为0~30000");
+ return false;
+ }
+
+ mVadEosPref.setSummary("当前:" + eos + "ms");
+ return true;
+ }
+ });
+
+ mSpeechTimeoutPref.getEditText().setInputType(InputType.TYPE_NUMBER_FLAG_SIGNED | InputType.TYPE_CLASS_NUMBER);
+ mSpeechTimeoutPref.setOnPreferenceChangeListener(new OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ int speech_timeout;
+ try {
+ speech_timeout = Integer.parseInt(newValue.toString());
+ } catch (Exception e) {
+ showTip("无效输入!");
+ return false;
+ }
+
+ if (speech_timeout < -1) {
+ showTip("必须大于等于-1");
+ return false;
+ }
+
+ if (speech_timeout == -1) {
+ mSpeechTimeoutPref.setSummary("当前:-1");
+ } else {
+ mSpeechTimeoutPref.setSummary("当前:" + speech_timeout + "ms");
+ }
+
+ return true;
+ }
+ });
+ }
+
+ private void showTip(String str) {
+ if (!TextUtils.isEmpty(str)) {
+ mToast.cancel();
+ mToast.setText(str);
+ mToast.show();
+ }
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/TtsSettings.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/TtsSettings.java
new file mode 100644
index 0000000..fba24b4
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/TtsSettings.java
@@ -0,0 +1,49 @@
+package com.iflytek.speech.setting;
+
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.Preference;
+import android.preference.Preference.OnPreferenceChangeListener;
+import android.preference.PreferenceActivity;
+import android.view.Window;
+
+import com.iflytek.speech.util.SettingTextWatcher;
+import com.iflytek.voicedemo.R;
+
+
+/**
+ * 合成设置界面
+ */
+public class TtsSettings extends PreferenceActivity implements OnPreferenceChangeListener {
+
+ public static final String PREFER_NAME = "com.iflytek.setting";
+ private EditTextPreference mSpeedPreference;
+ private EditTextPreference mPitchPreference;
+ private EditTextPreference mVolumePreference;
+
+ @SuppressWarnings("deprecation")
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ super.onCreate(savedInstanceState);
+ // 指定保存文件名字
+ getPreferenceManager().setSharedPreferencesName(PREFER_NAME);
+ addPreferencesFromResource(R.xml.tts_setting);
+ mSpeedPreference = (EditTextPreference) findPreference("speed_preference");
+ mSpeedPreference.getEditText().addTextChangedListener(new SettingTextWatcher(TtsSettings.this, mSpeedPreference, 0, 200));
+
+ mPitchPreference = (EditTextPreference) findPreference("pitch_preference");
+ mPitchPreference.getEditText().addTextChangedListener(new SettingTextWatcher(TtsSettings.this, mPitchPreference, 0, 100));
+
+ mVolumePreference = (EditTextPreference) findPreference("volume_preference");
+ mVolumePreference.getEditText().addTextChangedListener(new SettingTextWatcher(TtsSettings.this, mVolumePreference, 0, 100));
+
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ return true;
+ }
+
+
+}
\ No newline at end of file
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/UrlSettings.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/UrlSettings.java
new file mode 100644
index 0000000..18c32c1
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/setting/UrlSettings.java
@@ -0,0 +1,57 @@
+package com.iflytek.speech.setting;
+
+import android.os.Bundle;
+import android.preference.EditTextPreference;
+import android.preference.ListPreference;
+import android.preference.Preference;
+import android.preference.PreferenceActivity;
+import android.view.Window;
+
+import androidx.annotation.Nullable;
+
+import com.iflytek.voicedemo.R;
+
+/**
+ * @author hjyu
+ * @date 2018/5/31.
+ * @see 讯飞开放平台
+ */
+
+public class UrlSettings extends PreferenceActivity implements Preference.OnPreferenceChangeListener {
+
+ public static final String PREFER_NAME = "com.iflytek.setting";
+ private ListPreference url_preference;
+ private EditTextPreference url_edit;
+
+ @Override
+ public void onCreate(@Nullable Bundle savedInstanceState) {
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ super.onCreate(savedInstanceState);
+ getPreferenceManager().setSharedPreferencesName(PREFER_NAME);
+ addPreferencesFromResource(R.xml.url_setting);
+
+ url_preference = (ListPreference) findPreference("url_preference");
+ url_preference.setSummary("当前:" + url_preference.getEntry());
+ url_preference.setOnPreferenceChangeListener(this);
+
+
+ url_edit = (EditTextPreference) findPreference("url_edit");
+ url_edit.setSummary("当前域名:" + url_edit.getText());
+ url_edit.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ url_edit.setSummary("当前机房:" + newValue.toString());
+ return true;
+ }
+ });
+ }
+
+ @Override
+ public boolean onPreferenceChange(Preference preference, Object newValue) {
+ int newValueIndex = url_preference.findIndexOfValue(newValue.toString());
+ String newEntry = (String) url_preference.getEntries()[newValueIndex];
+ url_preference.setSummary("当前:" + newEntry);
+ return true;
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FaceRect.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FaceRect.java
new file mode 100644
index 0000000..5e7a7bd
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FaceRect.java
@@ -0,0 +1,23 @@
+package com.iflytek.speech.util;
+
+import android.graphics.Point;
+import android.graphics.Rect;
+
+/**
+ * @author MatrixCV
+ * FaceRect是用于表示人脸检测的结果,其中包括了 人脸的角度、得分、检测框位置、关键点
+ */
+public class FaceRect {
+ public float score;
+
+ public Rect bound = new Rect();
+ public Point point[];
+
+ public Rect raw_bound = new Rect();
+ public Point raw_point[];
+
+ @Override
+ public String toString() {
+ return bound.toString();
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FaceUtil.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FaceUtil.java
new file mode 100644
index 0000000..481a75d
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FaceUtil.java
@@ -0,0 +1,277 @@
+package com.iflytek.speech.util;
+
+import android.app.Activity;
+import android.content.Context;
+import android.content.Intent;
+import android.content.pm.PackageManager;
+import android.content.pm.ResolveInfo;
+import android.graphics.Bitmap;
+import android.graphics.Canvas;
+import android.graphics.Color;
+import android.graphics.Matrix;
+import android.graphics.Paint;
+import android.graphics.Paint.Style;
+import android.graphics.Point;
+import android.graphics.Rect;
+import android.media.ExifInterface;
+import android.net.Uri;
+import android.os.Build;
+import android.provider.MediaStore;
+
+import androidx.core.content.FileProvider;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.util.List;
+import java.util.regex.Pattern;
+
+public class FaceUtil {
+ public final static int REQUEST_PICTURE_CHOOSE = 1;
+ public final static int REQUEST_CAMERA_IMAGE = 2;
+ public final static int REQUEST_CROP_IMAGE = 3;
+
+
+ public static Uri parseUri(Context context, File file) {
+ Uri imageUri = Uri.fromFile(file);
+ if (Build.VERSION.SDK_INT >= 24) {
+ imageUri = FileProvider.getUriForFile(
+ context,
+ context.getPackageName() + ".fileprovider",
+ file
+ );
+ }
+ return imageUri;
+ }
+
+ /***
+ * 裁剪图片
+ * @param activity Activity
+ * @param uri 图片的Uri
+ */
+ public static void cropPicture(Activity activity, Uri uri) {
+ Intent innerIntent = new Intent("com.android.camera.action.CROP");
+ innerIntent.setDataAndType(uri, "image/*");
+ innerIntent.putExtra("crop", "true");// 才能出剪辑的小方框,不然没有剪辑功能,只能选取图片
+ innerIntent.putExtra("aspectX", 1); // 放大缩小比例的X
+ innerIntent.putExtra("aspectY", 1);// 放大缩小比例的X 这里的比例为: 1:1
+ innerIntent.putExtra("outputX", 320); //这个是限制输出图片大小
+ innerIntent.putExtra("outputY", 320);
+ innerIntent.putExtra("return-data", false);
+ // 切图大小不足输出,无黑框
+ innerIntent.putExtra("scale", true);
+ innerIntent.putExtra("scaleUpIfNeeded", true);
+ File imageFile = new File(getImagePath(activity.getApplicationContext()));
+ imageFile.delete();
+ Uri cropUri = parseUri(activity, imageFile);
+ innerIntent.putExtra(MediaStore.EXTRA_OUTPUT, cropUri);
+ innerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
+
+ List resolveInfos = activity.getPackageManager()
+ .queryIntentActivities(innerIntent, PackageManager.MATCH_DEFAULT_ONLY);
+ for (ResolveInfo resolveInfo : resolveInfos) {
+ activity.grantUriPermission(activity.getPackageName(), uri, Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ activity.grantUriPermission(resolveInfo.activityInfo.packageName, cropUri,
+ (Intent.FLAG_GRANT_READ_URI_PERMISSION | Intent.FLAG_GRANT_WRITE_URI_PERMISSION));
+ }
+ innerIntent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ innerIntent.addFlags(Intent.FLAG_GRANT_WRITE_URI_PERMISSION);
+ activity.startActivityForResult(innerIntent, REQUEST_CROP_IMAGE);
+ }
+
+ /**
+ * 保存裁剪的图片的路径
+ *
+ * @return
+ */
+ public static String getImagePath(Context context) {
+ String path = context.getExternalFilesDir("msc").getAbsolutePath();
+ if (!path.endsWith("/")) {
+ path += "/";
+ }
+ File folder = new File(path);
+ if (!folder.exists()) {
+ folder.mkdirs();
+ }
+ path += "ifd.jpg";
+ return path;
+ }
+
+ /**
+ * 读取图片属性:旋转的角度
+ *
+ * @param path 图片绝对路径
+ * @return degree 旋转角度
+ */
+ public static int readPictureDegree(String path) {
+ int degree = 0;
+ try {
+ ExifInterface exifInterface = new ExifInterface(path);
+ int orientation = exifInterface.getAttributeInt(
+ ExifInterface.TAG_ORIENTATION,
+ ExifInterface.ORIENTATION_NORMAL);
+ switch (orientation) {
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ degree = 90;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ degree = 180;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ degree = 270;
+ break;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return degree;
+ }
+
+ /**
+ * 旋转图片
+ *
+ * @param angle 旋转角度
+ * @param bitmap 原图
+ * @return bitmap 旋转后的图片
+ */
+ public static Bitmap rotateImage(int angle, Bitmap bitmap) {
+ // 图片旋转矩阵
+ Matrix matrix = new Matrix();
+ matrix.postRotate(angle);
+ // 得到旋转后的图片
+ Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+ return resizedBitmap;
+ }
+
+ /**
+ * 在指定画布上将人脸框出来
+ *
+ * @param canvas 给定的画布
+ * @param face 需要绘制的人脸信息
+ * @param width 原图宽
+ * @param height 原图高
+ * @param frontCamera 是否为前置摄像头,如为前置摄像头需左右对称
+ * @param DrawOriRect 可绘制原始框,也可以只画四个角
+ */
+ static public void drawFaceRect(Canvas canvas, FaceRect face, int width, int height, boolean frontCamera, boolean DrawOriRect) {
+ if (canvas == null) {
+ return;
+ }
+
+ Paint paint = new Paint();
+ paint.setColor(Color.rgb(255, 203, 15));
+ int len = (face.bound.bottom - face.bound.top) / 8;
+ if (len / 8 >= 2) paint.setStrokeWidth(len / 8);
+ else paint.setStrokeWidth(2);
+
+ Rect rect = face.bound;
+
+ if (frontCamera) {
+ int top = rect.top;
+ rect.top = width - rect.bottom;
+ rect.bottom = width - top;
+ }
+
+ if (DrawOriRect) {
+ paint.setStyle(Style.STROKE);
+ canvas.drawRect(rect, paint);
+ } else {
+ int drawl = rect.left - len;
+ int drawr = rect.right + len;
+ int drawu = rect.top - len;
+ int drawd = rect.bottom + len;
+
+ canvas.drawLine(drawl, drawd, drawl, drawd - len, paint);
+ canvas.drawLine(drawl, drawd, drawl + len, drawd, paint);
+ canvas.drawLine(drawr, drawd, drawr, drawd - len, paint);
+ canvas.drawLine(drawr, drawd, drawr - len, drawd, paint);
+ canvas.drawLine(drawl, drawu, drawl, drawu + len, paint);
+ canvas.drawLine(drawl, drawu, drawl + len, drawu, paint);
+ canvas.drawLine(drawr, drawu, drawr, drawu + len, paint);
+ canvas.drawLine(drawr, drawu, drawr - len, drawu, paint);
+ }
+
+ if (face.point != null) {
+ for (Point p : face.point) {
+ if (frontCamera) {
+ p.y = width - p.y;
+ }
+ canvas.drawPoint(p.x, p.y, paint);
+ }
+ }
+ }
+
+ /**
+ * 将矩形随原图顺时针旋转90度
+ *
+ * @param r 待旋转的矩形
+ * @param width 输入矩形对应的原图宽
+ * @param height 输入矩形对应的原图高
+ * @return 旋转后的矩形
+ */
+ static public Rect RotateDeg90(Rect r, int width, int height) {
+ int left = r.left;
+ r.left = height - r.bottom;
+ r.bottom = r.right;
+ r.right = height - r.top;
+ r.top = left;
+ return r;
+ }
+
+ /**
+ * 将点随原图顺时针旋转90度
+ *
+ * @param p 待旋转的点
+ * @param width 输入点对应的原图宽
+ * @param height 输入点对应的原图宽
+ * @return 旋转后的点
+ */
+ static public Point RotateDeg90(Point p, int width, int height) {
+ int x = p.x;
+ p.x = height - p.y;
+ p.y = x;
+ return p;
+ }
+
+ public static int getNumCores() {
+ class CpuFilter implements FileFilter {
+ @Override
+ public boolean accept(File pathname) {
+ if (Pattern.matches("cpu[0-9]", pathname.getName())) {
+ return true;
+ }
+ return false;
+ }
+ }
+ try {
+ File dir = new File("/sys/devices/system/cpu/");
+ File[] files = dir.listFiles(new CpuFilter());
+ return files.length;
+ } catch (Exception e) {
+ e.printStackTrace();
+ return 1;
+ }
+ }
+
+ /**
+ * 保存Bitmap至本地
+ */
+ public static void saveBitmapToFile(Context context, Bitmap bmp) {
+ String file_path = getImagePath(context);
+ File file = new File(file_path);
+ FileOutputStream fOut;
+ try {
+ fOut = new FileOutputStream(file);
+ bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
+ fOut.flush();
+ fOut.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FucUtil.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FucUtil.java
new file mode 100644
index 0000000..0c0fb60
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/FucUtil.java
@@ -0,0 +1,144 @@
+package com.iflytek.speech.util;
+
+import android.content.Context;
+
+import com.iflytek.cloud.ErrorCode;
+import com.iflytek.cloud.SpeechConstant;
+import com.iflytek.cloud.SpeechUtility;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+
+/**
+ * 功能性函数扩展类
+ */
+public class FucUtil {
+ /**
+ * 读取asset目录下文件。
+ *
+ * @return content
+ */
+ public static String readFile(Context mContext, String file, String code) {
+ int len = 0;
+ byte[] buf = null;
+ String result = "";
+ try {
+ InputStream in = mContext.getAssets().open(file);
+ len = in.available();
+ buf = new byte[len];
+ in.read(buf, 0, len);
+
+ result = new String(buf, code);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return result;
+ }
+
+ /**
+ * 将字节缓冲区按照固定大小进行分割成数组
+ *
+ * @param buffer 缓冲区
+ * @param length 缓冲区大小
+ * @param spsize 切割块大小
+ * @return
+ */
+ public static ArrayList splitBuffer(byte[] buffer, int length, int spsize) {
+ ArrayList array = new ArrayList();
+ if (spsize <= 0 || length <= 0 || buffer == null || buffer.length < length)
+ return array;
+ int size = 0;
+ while (size < length) {
+ int left = length - size;
+ if (spsize < left) {
+ byte[] sdata = new byte[spsize];
+ System.arraycopy(buffer, size, sdata, 0, spsize);
+ array.add(sdata);
+ size += spsize;
+ } else {
+ byte[] sdata = new byte[left];
+ System.arraycopy(buffer, size, sdata, 0, left);
+ array.add(sdata);
+ size += left;
+ }
+ }
+ return array;
+ }
+
+ /**
+ * 获取语记是否包含离线听写资源,如未包含跳转至资源下载页面
+ * 1.PLUS_LOCAL_ALL: 本地所有资源
+ * 2.PLUS_LOCAL_ASR: 本地识别资源
+ * 3.PLUS_LOCAL_TTS: 本地合成资源
+ */
+ public static String checkLocalResource() {
+ String resource = SpeechUtility.getUtility().getParameter(SpeechConstant.PLUS_LOCAL_ASR);
+ try {
+ JSONObject result = new JSONObject(resource);
+ int ret = result.getInt(SpeechUtility.TAG_RESOURCE_RET);
+ switch (ret) {
+ case ErrorCode.SUCCESS:
+ JSONArray asrArray = result.getJSONObject("result").optJSONArray("asr");
+ if (asrArray != null) {
+ int i = 0;
+ // 查询否包含离线听写资源
+ for (; i < asrArray.length(); i++) {
+ if ("iat".equals(asrArray.getJSONObject(i).get(SpeechConstant.DOMAIN))) {
+ //asrArray中包含语言、方言字段,后续会增加支持方言的本地听写。
+ //如:"accent": "mandarin","language": "zh_cn"
+ break;
+ }
+ }
+ if (i >= asrArray.length()) {
+
+ SpeechUtility.getUtility().openEngineSettings(SpeechConstant.ENG_ASR);
+ return "没有听写资源,跳转至资源下载页面";
+ }
+ } else {
+ SpeechUtility.getUtility().openEngineSettings(SpeechConstant.ENG_ASR);
+ return "没有听写资源,跳转至资源下载页面";
+ }
+ break;
+ case ErrorCode.ERROR_VERSION_LOWER:
+ return "语记版本过低,请更新后使用本地功能";
+ case ErrorCode.ERROR_INVALID_RESULT:
+ SpeechUtility.getUtility().openEngineSettings(SpeechConstant.ENG_ASR);
+ return "获取结果出错,跳转至资源下载页面";
+ case ErrorCode.ERROR_SYSTEM_PREINSTALL:
+ default:
+ break;
+ }
+ } catch (Exception e) {
+ SpeechUtility.getUtility().openEngineSettings(SpeechConstant.ENG_ASR);
+ return "获取结果出错,跳转至资源下载页面";
+ }
+ return "";
+ }
+
+ /**
+ * 读取asset目录下音频文件。
+ *
+ * @return 二进制文件数据
+ */
+ public static byte[] readAudioFile(Context context, String filename) {
+ try {
+ InputStream ins = context.getAssets().open(filename);
+ byte[] data = new byte[ins.available()];
+
+ ins.read(data);
+ ins.close();
+
+ return data;
+ } catch (IOException e) {
+ // TODO Auto-generated catch block
+ e.printStackTrace();
+ }
+
+ return null;
+ }
+
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/JsonParser.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/JsonParser.java
new file mode 100644
index 0000000..ac73c80
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/JsonParser.java
@@ -0,0 +1,173 @@
+package com.iflytek.speech.util;
+
+import org.json.JSONArray;
+import org.json.JSONObject;
+import org.json.JSONTokener;
+
+/**
+ * Json结果解析类
+ */
+public class JsonParser {
+
+ public static String parseIatResult(String json) {
+ StringBuffer ret = new StringBuffer();
+ try {
+ JSONTokener tokener = new JSONTokener(json);
+ JSONObject joResult = new JSONObject(tokener);
+
+ JSONArray words = joResult.getJSONArray("ws");
+ for (int i = 0; i < words.length(); i++) {
+ // 转写结果词,默认使用第一个结果
+ JSONArray items = words.getJSONObject(i).getJSONArray("cw");
+ JSONObject obj = items.getJSONObject(0);
+ ret.append(obj.getString("w"));
+// 如果需要多候选结果,解析数组其他字段
+// for(int j = 0; j < items.length(); j++)
+// {
+// JSONObject obj = items.getJSONObject(j);
+// ret.append(obj.getString("w"));
+// }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return ret.toString();
+ }
+
+ public static String parseGrammarResult(String json, String engType) {
+ StringBuffer ret = new StringBuffer();
+ try {
+ JSONTokener tokener = new JSONTokener(json);
+ JSONObject joResult = new JSONObject(tokener);
+
+ JSONArray words = joResult.getJSONArray("ws");
+ // 云端和本地结果分情况解析
+ if ("cloud".equals(engType)) {
+ for (int i = 0; i < words.length(); i++) {
+ JSONArray items = words.getJSONObject(i).getJSONArray("cw");
+ for (int j = 0; j < items.length(); j++) {
+ JSONObject obj = items.getJSONObject(j);
+ if (obj.getString("w").contains("nomatch")) {
+ ret.append("没有匹配结果.");
+ return ret.toString();
+ }
+ ret.append("【结果】" + obj.getString("w"));
+ ret.append("【置信度】" + obj.getInt("sc"));
+ ret.append("\n");
+ }
+ }
+ } else if ("local".equals(engType)) {
+ ret.append("【结果】");
+ for (int i = 0; i < words.length(); i++) {
+ JSONObject wsItem = words.getJSONObject(i);
+ JSONArray items = wsItem.getJSONArray("cw");
+ if ("".equals(wsItem.getString("slot"))) {
+ // 可能会有多个联系人供选择,用中括号括起来,这些候选项具有相同的置信度
+ ret.append("【");
+ for (int j = 0; j < items.length(); j++) {
+ JSONObject obj = items.getJSONObject(j);
+ if (obj.getString("w").contains("nomatch")) {
+ ret.append("没有匹配结果.");
+ return ret.toString();
+ }
+ ret.append(obj.getString("w")).append("|");
+ }
+ ret.setCharAt(ret.length() - 1, '】');
+ } else {
+ //本地多候选按照置信度高低排序,一般选取第一个结果即可
+ JSONObject obj = items.getJSONObject(0);
+ if (obj.getString("w").contains("nomatch")) {
+ ret.append("没有匹配结果.");
+ return ret.toString();
+ }
+ ret.append(obj.getString("w"));
+ }
+ }
+ ret.append("【置信度】" + joResult.getInt("sc"));
+ ret.append("\n");
+ }
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ ret.append("没有匹配结果.");
+ }
+ return ret.toString();
+ }
+
+ public static String parseGrammarResult(String json) {
+ StringBuffer ret = new StringBuffer();
+ try {
+ JSONTokener tokener = new JSONTokener(json);
+ JSONObject joResult = new JSONObject(tokener);
+
+ JSONArray words = joResult.getJSONArray("ws");
+ for (int i = 0; i < words.length(); i++) {
+ JSONArray items = words.getJSONObject(i).getJSONArray("cw");
+ for (int j = 0; j < items.length(); j++) {
+ JSONObject obj = items.getJSONObject(j);
+ if (obj.getString("w").contains("nomatch")) {
+ ret.append("没有匹配结果.");
+ return ret.toString();
+ }
+ ret.append("【结果】" + obj.getString("w"));
+ ret.append("【置信度】" + obj.getInt("sc"));
+ ret.append("\n");
+ }
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ ret.append("没有匹配结果.");
+ }
+ return ret.toString();
+ }
+
+ public static String parseLocalGrammarResult(String json) {
+ StringBuffer ret = new StringBuffer();
+ try {
+ JSONTokener tokener = new JSONTokener(json);
+ JSONObject joResult = new JSONObject(tokener);
+
+ JSONArray words = joResult.getJSONArray("ws");
+ for (int i = 0; i < words.length(); i++) {
+ JSONArray items = words.getJSONObject(i).getJSONArray("cw");
+ for (int j = 0; j < items.length(); j++) {
+ JSONObject obj = items.getJSONObject(j);
+ if (obj.getString("w").contains("nomatch")) {
+ ret.append("没有匹配结果.");
+ return ret.toString();
+ }
+ ret.append("【结果】" + obj.getString("w"));
+ ret.append("\n");
+ }
+ }
+ ret.append("【置信度】" + joResult.optInt("sc"));
+
+ } catch (Exception e) {
+ e.printStackTrace();
+ ret.append("没有匹配结果.");
+ }
+ return ret.toString();
+ }
+
+ public static String parseTransResult(String json, String key) {
+ StringBuffer ret = new StringBuffer();
+ try {
+ JSONTokener tokener = new JSONTokener(json);
+ JSONObject joResult = new JSONObject(tokener);
+ String errorCode = joResult.optString("ret");
+ if (!errorCode.equals("0")) {
+ return joResult.optString("errmsg");
+ }
+ JSONObject transResult = joResult.optJSONObject("trans_result");
+ ret.append(transResult.optString(key));
+ /*JSONArray words = joResult.getJSONArray("results");
+ for (int i = 0; i < words.length(); i++) {
+ JSONObject obj = words.getJSONObject(i);
+ ret.append(obj.getString(key));
+ }*/
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ return ret.toString();
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/SettingTextWatcher.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/SettingTextWatcher.java
new file mode 100644
index 0000000..a1c1c62
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/SettingTextWatcher.java
@@ -0,0 +1,71 @@
+package com.iflytek.speech.util;
+
+import android.content.Context;
+import android.preference.EditTextPreference;
+import android.text.Editable;
+import android.text.TextUtils;
+import android.text.TextWatcher;
+import android.widget.Toast;
+
+import java.util.regex.Pattern;
+
+/**
+ * 输入框输入范围控制
+ */
+public class SettingTextWatcher implements TextWatcher {
+ private int editStart;
+ private int editCount;
+ private EditTextPreference mEditTextPreference;
+ int minValue;//最小值
+ int maxValue;//最大值
+ private Context mContext;
+
+ public SettingTextWatcher(Context context, EditTextPreference e, int min, int max) {
+ mContext = context;
+ mEditTextPreference = e;
+ minValue = min;
+ maxValue = max;
+ }
+
+ @Override
+ public void onTextChanged(CharSequence s, int start, int before, int count) {
+// Log.e("demo", "onTextChanged start:"+start+" count:"+count+" before:"+before);
+ editStart = start;
+ editCount = count;
+ }
+
+ @Override
+ public void beforeTextChanged(CharSequence s, int start, int count, int after) {
+// Log.e("demo", "beforeTextChanged start:"+start+" count:"+count+" after:"+after);
+ }
+
+ @Override
+ public void afterTextChanged(Editable s) {
+ if (TextUtils.isEmpty(s)) {
+ return;
+ }
+ String content = s.toString();
+// Log.e("demo", "content:"+content);
+ if (isNumeric(content)) {
+ int num = Integer.parseInt(content);
+ if (num > maxValue || num < minValue) {
+ s.delete(editStart, editStart + editCount);
+ mEditTextPreference.getEditText().setText(s);
+ Toast.makeText(mContext, "超出有效值范围", Toast.LENGTH_SHORT).show();
+ }
+ } else {
+ s.delete(editStart, editStart + editCount);
+ mEditTextPreference.getEditText().setText(s);
+ Toast.makeText(mContext, "只能输入数字哦", Toast.LENGTH_SHORT).show();
+ }
+ }
+
+ /**
+ * 正则表达式-判断是否为数字
+ */
+ public static boolean isNumeric(String str) {
+ Pattern pattern = Pattern.compile("[0-9]*");
+ return pattern.matcher(str).matches();
+ }
+
+};
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/XmlParser.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/XmlParser.java
new file mode 100644
index 0000000..f87f09e
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/speech/util/XmlParser.java
@@ -0,0 +1,55 @@
+package com.iflytek.speech.util;
+
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+/**
+ * Xml结果解析类
+ */
+public class XmlParser {
+
+ public static String parseNluResult(String xml) {
+ StringBuffer buffer = new StringBuffer();
+ try {
+ // DOM builder
+ DocumentBuilder domBuilder = null;
+ // DOM doc
+ Document domDoc = null;
+
+ // init DOM
+ DocumentBuilderFactory domFact = DocumentBuilderFactory.newInstance();
+ domBuilder = domFact.newDocumentBuilder();
+ InputStream is = new ByteArrayInputStream(xml.getBytes());
+ domDoc = domBuilder.parse(is);
+
+ // 获取根节点
+ Element root = (Element) domDoc.getDocumentElement();
+
+ Element raw = (Element) root.getElementsByTagName("rawtext").item(0);
+ buffer.append("【识别结果】" + raw.getFirstChild().getNodeValue());
+ buffer.append("\n");
+
+ Element e = (Element) root.getElementsByTagName("result").item(0);
+
+ Element focus = (Element) e.getElementsByTagName("focus").item(0);
+ buffer.append("【FOCUS】" + focus.getFirstChild().getNodeValue());
+ buffer.append("\n");
+
+ Element action = (Element) e.getElementsByTagName("action").item(0);
+ Element operation = (Element) action.getElementsByTagName("operation").item(0);
+ buffer.append("【ACTION】" + operation.getFirstChild().getNodeValue());
+ buffer.append("\n");
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+
+ buffer.append("【ALL】" + xml);
+ return buffer.toString();
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/AsrDemo.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/AsrDemo.java
new file mode 100644
index 0000000..9ee82bf
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/AsrDemo.java
@@ -0,0 +1,273 @@
+package com.iflytek.voicedemo;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.content.SharedPreferences;
+import android.content.SharedPreferences.Editor;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.EditText;
+import android.widget.Toast;
+
+import com.iflytek.cloud.ErrorCode;
+import com.iflytek.cloud.GrammarListener;
+import com.iflytek.cloud.InitListener;
+import com.iflytek.cloud.RecognizerListener;
+import com.iflytek.cloud.RecognizerResult;
+import com.iflytek.cloud.SpeechConstant;
+import com.iflytek.cloud.SpeechError;
+import com.iflytek.cloud.SpeechRecognizer;
+import com.iflytek.speech.util.FucUtil;
+import com.iflytek.speech.util.JsonParser;
+
+/**
+ * 识别示例
+ */
+public class AsrDemo extends Activity implements OnClickListener {
+ private static String TAG = AsrDemo.class.getSimpleName();
+ // 语音识别对象
+ private SpeechRecognizer mAsr;
+ private Toast mToast;
+ // 缓存
+ private SharedPreferences mSharedPreferences;
+ // 云端语法文件
+ private String mCloudGrammar = null;
+
+ private static final String KEY_GRAMMAR_ABNF_ID = "grammar_abnf_id";
+ private static final String GRAMMAR_TYPE_ABNF = "abnf";
+ private static final String GRAMMAR_TYPE_BNF = "bnf";
+
+ private String mEngineType = SpeechConstant.TYPE_CLOUD;
+
+ @SuppressLint("ShowToast")
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.isrdemo);
+ initLayout();
+
+ // 初始化识别对象
+ mAsr = SpeechRecognizer.createRecognizer(AsrDemo.this, mInitListener);
+ mCloudGrammar = FucUtil.readFile(this, "grammar_sample.abnf", "utf-8");
+
+ mSharedPreferences = getSharedPreferences(getPackageName(), MODE_PRIVATE);
+ }
+
+ /**
+ * 初始化Layout。
+ */
+ private void initLayout() {
+ findViewById(R.id.isr_recognize).setOnClickListener(AsrDemo.this);
+ findViewById(R.id.isr_grammar).setOnClickListener(AsrDemo.this);
+ findViewById(R.id.isr_stop).setOnClickListener(AsrDemo.this);
+ findViewById(R.id.isr_cancel).setOnClickListener(AsrDemo.this);
+
+ }
+
+ // 语法、词典临时变量
+ private String mContent;
+ // 函数调用返回值
+ private int ret = 0;
+
+ @Override
+ public void onClick(View view) {
+ if (null == mAsr) {
+ // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
+ this.showTip("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");
+ return;
+ }
+
+ if (null == mEngineType) {
+ showTip("请先选择识别引擎类型");
+ return;
+ }
+ switch (view.getId()) {
+ case R.id.isr_grammar:
+ showTip("上传预设关键词/语法文件");
+ // 在线-构建语法文件,生成语法id
+ ((EditText) findViewById(R.id.isr_text)).setText(mCloudGrammar);
+ mContent = new String(mCloudGrammar);
+ //指定引擎类型
+ mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
+ mAsr.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");
+ ret = mAsr.buildGrammar(GRAMMAR_TYPE_ABNF, mContent, mCloudGrammarListener);
+ if (ret != ErrorCode.SUCCESS) {
+ showTip("语法构建失败,错误码:" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ }
+ break;
+ // 开始识别
+ case R.id.isr_recognize:
+ ((EditText) findViewById(R.id.isr_text)).setText(null);// 清空显示内容
+ // 设置参数
+ if (!setParam()) {
+ showTip("请先构建语法。");
+ return;
+ }
+ ret = mAsr.startListening(mRecognizerListener);
+ if (ret != ErrorCode.SUCCESS) {
+ showTip("识别失败,错误码: " + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ }
+ break;
+ // 停止识别
+ case R.id.isr_stop:
+ mAsr.stopListening();
+ showTip("停止识别");
+ break;
+ // 取消识别
+ case R.id.isr_cancel:
+ mAsr.cancel();
+ showTip("取消识别");
+ break;
+ }
+ }
+
+ /**
+ * 初始化监听器。
+ */
+ private InitListener mInitListener = new InitListener() {
+
+ @Override
+ public void onInit(int code) {
+ Log.d(TAG, "SpeechRecognizer init() code = " + code);
+ if (code != ErrorCode.SUCCESS) {
+ showTip("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ }
+ }
+ };
+
+ /**
+ * 云端构建语法监听器。
+ */
+ private GrammarListener mCloudGrammarListener = new GrammarListener() {
+ @Override
+ public void onBuildFinish(String grammarId, SpeechError error) {
+ if (error == null) {
+ String grammarID = new String(grammarId);
+ Editor editor = mSharedPreferences.edit();
+ if (!TextUtils.isEmpty(grammarId))
+ editor.putString(KEY_GRAMMAR_ABNF_ID, grammarID);
+ editor.commit();
+ showTip("语法构建成功:" + grammarId);
+ } else {
+ showTip("语法构建失败,错误码:" + error.getErrorCode() + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ }
+ }
+ };
+
+ /**
+ * 识别监听器。
+ */
+ private RecognizerListener mRecognizerListener = new RecognizerListener() {
+
+ @Override
+ public void onVolumeChanged(int volume, byte[] data) {
+ showTip("当前正在说话,音量大小:" + volume);
+ Log.d(TAG, "返回音频数据:" + data.length);
+ }
+
+ @Override
+ public void onResult(final RecognizerResult result, boolean isLast) {
+ if (null != result) {
+ Log.d(TAG, "recognizer result:" + result.getResultString());
+ String text;
+ if ("cloud".equalsIgnoreCase(mEngineType)) {
+ text = JsonParser.parseGrammarResult(result.getResultString());
+ } else {
+ text = JsonParser.parseLocalGrammarResult(result.getResultString());
+ }
+
+ // 显示
+ ((EditText) findViewById(R.id.isr_text)).setText(text);
+ } else {
+ Log.d(TAG, "recognizer result : null");
+ }
+ }
+
+ @Override
+ public void onEndOfSpeech() {
+ // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
+ showTip("结束说话");
+ }
+
+ @Override
+ public void onBeginOfSpeech() {
+ // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
+ showTip("开始说话");
+ }
+
+ @Override
+ public void onError(SpeechError error) {
+ showTip("onError Code:" + error.getErrorCode());
+ }
+
+ @Override
+ public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
+ // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
+ // 若使用本地能力,会话id为null
+ // if (SpeechEvent.EVENT_SESSION_ID == eventType) {
+ // String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
+ // Log.d(TAG, "session id =" + sid);
+ // }
+ }
+
+ };
+
+
+ private void showTip(final String str) {
+ runOnUiThread(new Runnable() {
+ @Override
+ public void run() {
+ if (mToast != null) {
+ mToast.cancel();
+ }
+ mToast = Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT);
+ mToast.show();
+ }
+ });
+ }
+
+ /**
+ * 参数设置
+ *
+ * @return
+ */
+ public boolean setParam() {
+ boolean result = false;
+ //设置识别引擎
+ mAsr.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
+ //设置返回结果为json格式
+ mAsr.setParameter(SpeechConstant.RESULT_TYPE, "json");
+
+ if ("cloud".equalsIgnoreCase(mEngineType)) {
+ String grammarId = mSharedPreferences.getString(KEY_GRAMMAR_ABNF_ID, null);
+ if (TextUtils.isEmpty(grammarId)) {
+ result = false;
+ } else {
+ //设置云端识别使用的语法id
+ mAsr.setParameter(SpeechConstant.CLOUD_GRAMMAR, grammarId);
+ result = true;
+ }
+ }
+ // 设置音频保存路径,保存音频格式支持pcm、wav,
+ mAsr.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
+ mAsr.setParameter(SpeechConstant.ASR_AUDIO_PATH,
+ getExternalFilesDir("msc").getAbsolutePath() + "/asr.wav");
+ return result;
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (null != mAsr) {
+ // 退出时释放连接
+ mAsr.cancel();
+ mAsr.destroy();
+ }
+ }
+
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IatDemo.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IatDemo.java
new file mode 100644
index 0000000..3312b05
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IatDemo.java
@@ -0,0 +1,428 @@
+package com.iflytek.voicedemo;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.AlertDialog;
+import android.content.DialogInterface;
+import android.content.Intent;
+import android.content.SharedPreferences;
+import android.os.Bundle;
+import android.util.Log;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.EditText;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.iflytek.cloud.ErrorCode;
+import com.iflytek.cloud.InitListener;
+import com.iflytek.cloud.LexiconListener;
+import com.iflytek.cloud.RecognizerListener;
+import com.iflytek.cloud.RecognizerResult;
+import com.iflytek.cloud.SpeechConstant;
+import com.iflytek.cloud.SpeechError;
+import com.iflytek.cloud.SpeechRecognizer;
+import com.iflytek.cloud.ui.RecognizerDialog;
+import com.iflytek.cloud.ui.RecognizerDialogListener;
+import com.iflytek.speech.setting.IatSettings;
+import com.iflytek.speech.util.FucUtil;
+import com.iflytek.speech.util.JsonParser;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.HashMap;
+import java.util.LinkedHashMap;
+
+public class IatDemo extends Activity implements OnClickListener {
+ private static String TAG = IatDemo.class.getSimpleName();
+ // 语音听写对象
+ private SpeechRecognizer mIat;
+ // 语音听写UI
+ private RecognizerDialog mIatDialog;
+ // 用HashMap存储听写结果
+ private HashMap mIatResults = new LinkedHashMap<>();
+
+ private EditText mResultText;
+ private EditText showContacts;
+ private TextView languageText;
+ private Toast mToast;
+ private SharedPreferences mSharedPreferences;
+ // 引擎类型
+ private String mEngineType = SpeechConstant.TYPE_CLOUD;
+
+ private String[] languageEntries;
+ private String[] languageValues;
+ private String language = "zh_cn";
+ private int selectedNum = 0;
+
+ private String resultType = "json";
+
+ private StringBuffer buffer = new StringBuffer();
+
+
+ public void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.iatdemo);
+
+ languageEntries = getResources().getStringArray(R.array.iat_language_entries);
+ languageValues = getResources().getStringArray(R.array.iat_language_value);
+ initLayout();
+ // 初始化识别无UI识别对象
+ // 使用SpeechRecognizer对象,可根据回调消息自定义界面;
+ mIat = SpeechRecognizer.createRecognizer(IatDemo.this, mInitListener);
+
+ // 初始化听写Dialog,如果只使用有UI听写功能,无需创建SpeechRecognizer
+ // 使用UI听写功能,请根据sdk文件目录下的notice.txt,放置布局文件和图片资源
+ mIatDialog = new RecognizerDialog(IatDemo.this, mInitListener);
+
+ mSharedPreferences = getSharedPreferences(IatSettings.PREFER_NAME,
+ Activity.MODE_PRIVATE);
+ mResultText = ((EditText) findViewById(R.id.iat_text));
+ showContacts = (EditText) findViewById(R.id.iat_contacts);
+ }
+
+
+ /**
+ * 初始化Layout。
+ */
+ private void initLayout() {
+ findViewById(R.id.iat_recognize).setOnClickListener(IatDemo.this);
+ findViewById(R.id.iat_recognize_stream).setOnClickListener(IatDemo.this);
+ findViewById(R.id.iat_upload_userwords).setOnClickListener(IatDemo.this);
+ findViewById(R.id.iat_stop).setOnClickListener(IatDemo.this);
+ findViewById(R.id.iat_cancel).setOnClickListener(IatDemo.this);
+ findViewById(R.id.image_iat_set).setOnClickListener(IatDemo.this);
+ findViewById(R.id.languageText).setOnClickListener(IatDemo.this);
+ }
+
+ int ret = 0; // 函数调用返回值
+
+ @Override
+ public void onClick(View view) {
+ if (null == mIat) {
+ // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
+ this.showTip("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");
+ return;
+ }
+
+ switch (view.getId()) {
+ // 进入参数设置页面
+ case R.id.image_iat_set:
+ Intent intents = new Intent(IatDemo.this, IatSettings.class);
+ startActivity(intents);
+ break;
+ // 开始听写
+ // 如何判断一次听写结束:OnResult isLast=true 或者 onError
+ case R.id.iat_recognize:
+ buffer.setLength(0);
+ mResultText.setText(null);// 清空显示内容
+ mIatResults.clear();
+ // 设置参数
+ setParam();
+ boolean isShowDialog = mSharedPreferences.getBoolean(
+ getString(R.string.pref_key_iat_show), true);
+ if (isShowDialog) {
+ // 显示听写对话框
+ mIatDialog.setListener(mRecognizerDialogListener);
+ mIatDialog.show();
+ showTip(getString(R.string.text_begin));
+ } else {
+ // 不显示听写对话框
+ ret = mIat.startListening(mRecognizerListener);
+ if (ret != ErrorCode.SUCCESS) {
+ showTip("听写失败,错误码:" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ } else {
+ showTip(getString(R.string.text_begin));
+ }
+ }
+ break;
+ // 音频流识别
+ case R.id.iat_recognize_stream:
+ executeStream();
+ break;
+ case R.id.languageText:
+ setLanguage(view);
+ break;
+ // 停止听写
+ case R.id.iat_stop:
+ mIat.stopListening();
+ showTip("停止听写");
+ break;
+ // 取消听写
+ case R.id.iat_cancel:
+ mIat.cancel();
+ showTip("取消听写");
+ break;
+ // 上传用户词表
+ case R.id.iat_upload_userwords:
+ String contents = FucUtil.readFile(IatDemo.this, "userwords", "utf-8");
+ showContacts.setText(contents);
+ // 指定引擎类型
+ mIat.setParameter(SpeechConstant.ENGINE_TYPE, SpeechConstant.TYPE_CLOUD);
+ mIat.setParameter(SpeechConstant.TEXT_ENCODING, "utf-8");
+ ret = mIat.updateLexicon("userword", contents, mLexiconListener);
+ if (ret != ErrorCode.SUCCESS)
+ showTip("上传热词失败,错误码:" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ break;
+ default:
+ break;
+ }
+ }
+
+ /**
+ * 初始化监听器。
+ */
+ private InitListener mInitListener = new InitListener() {
+
+ @Override
+ public void onInit(int code) {
+ Log.d(TAG, "SpeechRecognizer init() code = " + code);
+ if (code != ErrorCode.SUCCESS) {
+ showTip("初始化失败,错误码:" + code + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ }
+ }
+ };
+
+ /**
+ * 在线听写支持多种小语种设置。支持语言类型如下:
+ * - zh_cn
中文
+ * - en_us
英文
+ * - ja_jp
日语
+ * - ru-ru
俄语
+ * - es_es
西班牙语
+ * - fr_fr
法语
+ * - ko_kr
韩语
+ *
+ * @param v
+ */
+ private void setLanguage(View v) {
+ new AlertDialog.Builder(v.getContext()).setTitle("语种语言种类")
+ .setSingleChoiceItems(languageEntries, // 单选框有几项,各是什么名字
+ 0, // 默认的选项
+ new DialogInterface.OnClickListener() { // 点击单选框后的处理
+ public void onClick(DialogInterface dialog,
+ int which) { // 点击了哪一项
+ language = languageValues[which];
+ ((TextView) findViewById(R.id.languageText)).setText("你选择的是:" + languageEntries[which]);
+ selectedNum = which;
+ dialog.dismiss();
+ }
+ }).show();
+ mIat.setParameter(SpeechConstant.LANGUAGE, language);
+ }
+
+ /**
+ * 上传联系人/词表监听器。
+ */
+ private LexiconListener mLexiconListener = new LexiconListener() {
+
+ @Override
+ public void onLexiconUpdated(String lexiconId, SpeechError error) {
+ if (error != null) {
+ showTip(error.toString());
+ } else {
+ showTip(getString(R.string.text_upload_success));
+ }
+ }
+ };
+
+ /**
+ * 听写监听器。
+ */
+ private RecognizerListener mRecognizerListener = new RecognizerListener() {
+
+ @Override
+ public void onBeginOfSpeech() {
+ // 此回调表示:sdk内部录音机已经准备好了,用户可以开始语音输入
+ showTip("开始说话");
+ }
+
+ @Override
+ public void onError(SpeechError error) {
+ // Tips:
+ // 错误码:10118(您没有说话),可能是录音机权限被禁,需要提示用户打开应用的录音权限。
+ Log.d(TAG, "onError " + error.getPlainDescription(true));
+ showTip(error.getPlainDescription(true));
+
+ }
+
+ @Override
+ public void onEndOfSpeech() {
+ // 此回调表示:检测到了语音的尾端点,已经进入识别过程,不再接受语音输入
+ showTip("结束说话");
+ }
+
+ @Override
+ public void onResult(RecognizerResult results, boolean isLast) {
+ Log.d(TAG, results.getResultString());
+ if (isLast) {
+ Log.d(TAG, "onResult 结束");
+ }
+ if (resultType.equals("json")) {
+ printResult(results);
+ return;
+ }
+ if (resultType.equals("plain")) {
+ buffer.append(results.getResultString());
+ mResultText.setText(buffer.toString());
+ mResultText.setSelection(mResultText.length());
+ }
+ }
+
+ @Override
+ public void onVolumeChanged(int volume, byte[] data) {
+ showTip("当前正在说话,音量大小 = " + volume + " 返回音频数据 = " + data.length);
+ }
+
+ @Override
+ public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
+ // 以下代码用于获取与云端的会话id,当业务出错时将会话id提供给技术支持人员,可用于查询会话日志,定位出错原因
+ // 若使用本地能力,会话id为null
+ // if (SpeechEvent.EVENT_SESSION_ID == eventType) {
+ // String sid = obj.getString(SpeechEvent.KEY_EVENT_SESSION_ID);
+ // Log.d(TAG, "session id =" + sid);
+ // }
+ }
+ };
+
+ /**
+ * 显示结果
+ */
+ private void printResult(RecognizerResult results) {
+ String text = JsonParser.parseIatResult(results.getResultString());
+ String sn = null;
+ // 读取json结果中的sn字段
+ try {
+ JSONObject resultJson = new JSONObject(results.getResultString());
+ sn = resultJson.optString("sn");
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+
+ mIatResults.put(sn, text);
+
+ StringBuffer resultBuffer = new StringBuffer();
+ for (String key : mIatResults.keySet()) {
+ resultBuffer.append(mIatResults.get(key));
+ }
+ mResultText.setText(resultBuffer.toString());
+ mResultText.setSelection(mResultText.length());
+ }
+
+ /**
+ * 听写UI监听器
+ */
+ private RecognizerDialogListener mRecognizerDialogListener = new RecognizerDialogListener() {
+ // 返回结果
+ public void onResult(RecognizerResult results, boolean isLast) {
+ printResult(results);
+ }
+
+ // 识别回调错误
+ public void onError(SpeechError error) {
+ showTip(error.getPlainDescription(true));
+ }
+
+ };
+
+
+ private void showTip(final String str) {
+ if (mToast != null) {
+ mToast.cancel();
+ }
+ mToast = Toast.makeText(getApplicationContext(), str, Toast.LENGTH_SHORT);
+ mToast.show();
+ }
+
+ /**
+ * 参数设置
+ *
+ * @return
+ */
+ public void setParam() {
+ // 清空参数
+ mIat.setParameter(SpeechConstant.PARAMS, null);
+ // 设置听写引擎
+ mIat.setParameter(SpeechConstant.ENGINE_TYPE, mEngineType);
+ // 设置返回结果格式
+ mIat.setParameter(SpeechConstant.RESULT_TYPE, resultType);
+
+ if (language.equals("zh_cn")) {
+ String lag = mSharedPreferences.getString("iat_language_preference",
+ "mandarin");
+ // 设置语言
+ Log.e(TAG, "language = " + language);
+ mIat.setParameter(SpeechConstant.LANGUAGE, "zh_cn");
+ // 设置语言区域
+ mIat.setParameter(SpeechConstant.ACCENT, lag);
+ } else {
+ mIat.setParameter(SpeechConstant.LANGUAGE, language);
+ }
+ Log.e(TAG, "last language:" + mIat.getParameter(SpeechConstant.LANGUAGE));
+
+ //此处用于设置dialog中不显示错误码信息
+ //mIat.setParameter("view_tips_plain","false");
+
+ // 设置语音前端点:静音超时时间,即用户多长时间不说话则当做超时处理
+ mIat.setParameter(SpeechConstant.VAD_BOS, mSharedPreferences.getString("iat_vadbos_preference", "4000"));
+
+ // 设置语音后端点:后端点静音检测时间,即用户停止说话多长时间内即认为不再输入, 自动停止录音
+ mIat.setParameter(SpeechConstant.VAD_EOS, mSharedPreferences.getString("iat_vadeos_preference", "1000"));
+
+ // 设置标点符号,设置为"0"返回结果无标点,设置为"1"返回结果有标点
+ mIat.setParameter(SpeechConstant.ASR_PTT, mSharedPreferences.getString("iat_punc_preference", "1"));
+
+ // 设置音频保存路径,保存音频格式支持pcm、wav.
+ mIat.setParameter(SpeechConstant.AUDIO_FORMAT, "wav");
+ mIat.setParameter(SpeechConstant.ASR_AUDIO_PATH,
+ getExternalFilesDir("msc").getAbsolutePath() + "/iat.wav");
+ }
+
+ /**
+ * 执行音频流识别操作
+ */
+ private void executeStream() {
+ buffer.setLength(0);
+ mResultText.setText(null);// 清空显示内容
+ mIatResults.clear();
+ // 设置参数
+ setParam();
+ // 设置音频来源为外部文件
+ mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-1");
+ // 也可以像以下这样直接设置音频文件路径识别(要求设置文件在sdcard上的全路径):
+ // mIat.setParameter(SpeechConstant.AUDIO_SOURCE, "-2");
+ // mIat.setParameter(SpeechConstant.ASR_SOURCE_PATH, "sdcard/XXX/XXX.pcm");
+ ret = mIat.startListening(mRecognizerListener);
+ if (ret != ErrorCode.SUCCESS) {
+ showTip("识别失败,错误码:" + ret + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ return;
+ }
+ try {
+ InputStream open = getAssets().open("iattest.wav");
+ byte[] buff = new byte[1280];
+ while (open.available() > 0) {
+ int read = open.read(buff);
+ mIat.writeAudio(buff, 0, read);
+ }
+ mIat.stopListening();
+ } catch (IOException e) {
+ mIat.cancel();
+ showTip("读取音频流失败");
+ }
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+ if (mIat != null) {
+ // 退出时释放连接
+ mIat.cancel();
+ mIat.destroy();
+ }
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IdentifyGroup/FaceIdentifyActivity.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IdentifyGroup/FaceIdentifyActivity.java
new file mode 100644
index 0000000..45a8b3a
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IdentifyGroup/FaceIdentifyActivity.java
@@ -0,0 +1,464 @@
+package com.iflytek.voicedemo.IdentifyGroup;
+
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.Intent;
+import android.database.Cursor;
+import android.graphics.Bitmap;
+import android.graphics.BitmapFactory;
+import android.graphics.BitmapFactory.Options;
+import android.graphics.Matrix;
+import android.media.ExifInterface;
+import android.media.MediaScannerConnection;
+import android.net.Uri;
+import android.os.Bundle;
+import android.provider.MediaStore;
+import android.util.Log;
+import android.view.Gravity;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.Window;
+import android.widget.ImageView;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.iflytek.cloud.ErrorCode;
+import com.iflytek.cloud.IdentityListener;
+import com.iflytek.cloud.IdentityResult;
+import com.iflytek.cloud.IdentityVerifier;
+import com.iflytek.cloud.InitListener;
+import com.iflytek.cloud.SpeechConstant;
+import com.iflytek.cloud.SpeechError;
+import com.iflytek.voicedemo.R;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+
+/**
+ * 人脸验证示例demo
+ *
+ * @author hjyu
+ * @date 2017/9/28.
+ * @see 讯飞开放平台
+ */
+public class FaceIdentifyActivity extends Activity implements OnClickListener {
+ private final static String TAG = FaceIdentifyActivity.class.getSimpleName();
+
+ // 用户输入的组ID
+ private String mGroupId;
+ // 身份鉴别对象
+ private IdentityVerifier mIdVerifier;
+
+ private TextView txt_groupid;
+ private ProgressDialog mProDialog;
+ private Toast mToast;
+
+ // 选择图片后返回
+ public static final int REQUEST_PICTURE_CHOOSE = 1;
+ // 拍照后返回
+ private final static int REQUEST_CAMERA_IMAGE = 2;
+ // 裁剪图片成功后返回
+ public static final int REQUEST_INTENT_CROP = 3;
+
+ private Bitmap mImageBitmap = null;
+ private byte[] mImageData = null;
+ private File mPictureFile;
+
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+ this.requestWindowFeature(Window.FEATURE_NO_TITLE);
+ setContentView(R.layout.activity_face_identify);
+
+ // 身份验证对象初始化
+ mGroupId = getIntent().getStringExtra("group_id");
+ // 对象初始化监听器
+ mIdVerifier = IdentityVerifier.createVerifier(FaceIdentifyActivity.this, new InitListener() {
+ @Override
+ public void onInit(int errorCode) {
+ if (ErrorCode.SUCCESS == errorCode) {
+ showTip("引擎初始化成功");
+ } else {
+ showTip("引擎初始化失败,错误码:" + errorCode + ",请点击网址https://www.xfyun.cn/document/error-code查询解决方案");
+ }
+ }
+ });
+
+ // 初始化界面
+ initUI();
+ }
+
+ private void initUI() {
+ findViewById(R.id.online_pick).setOnClickListener(FaceIdentifyActivity.this);
+ findViewById(R.id.online_camera).setOnClickListener(FaceIdentifyActivity.this);
+ findViewById(R.id.btn_identity).setOnClickListener(FaceIdentifyActivity.this);
+ txt_groupid = (TextView) findViewById(R.id.txt_groupid);
+ mProDialog = new ProgressDialog(FaceIdentifyActivity.this);
+ mProDialog.setCancelable(true);
+ mProDialog.setTitle("请稍候");
+ // cancel进度框时,取消正在进行的操作
+ mProDialog.setOnCancelListener(new OnCancelListener() {
+
+ @Override
+ public void onCancel(DialogInterface dialog) {
+ if (null != mIdVerifier) {
+ mIdVerifier.cancel();
+ }
+ }
+ });
+
+ mToast = Toast.makeText(FaceIdentifyActivity.this, "", Toast.LENGTH_SHORT);
+ mToast.setGravity(Gravity.BOTTOM | Gravity.CENTER_HORIZONTAL, 0, 0);
+
+ txt_groupid.setText(mGroupId);
+ }
+
+ /**
+ * 人脸鉴别监听器
+ */
+ private IdentityListener mSearchListener = new IdentityListener() {
+
+ @Override
+ public void onResult(IdentityResult result, boolean islast) {
+ Log.d(TAG, result.getResultString());
+
+ dismissProDialog();
+
+ handleResult(result);
+ }
+
+ @Override
+ public void onEvent(int eventType, int arg1, int arg2, Bundle obj) {
+ }
+
+ @Override
+ public void onError(SpeechError error) {
+ dismissProDialog();
+
+ showTip(error.getPlainDescription(true));
+ }
+
+ };
+
+ @Override
+ public void onClick(View view) {
+ if (null == mIdVerifier) {
+ // 创建单例失败,与 21001 错误为同样原因,参考 http://bbs.xfyun.cn/forum.php?mod=viewthread&tid=9688
+ showTip("创建对象失败,请确认 libmsc.so 放置正确,且有调用 createUtility 进行初始化");
+ return;
+ }
+
+ switch (view.getId()) {
+ case R.id.online_pick:
+ // 调用系统相册,完成选图
+ Intent intent = new Intent();
+ intent.setType("image/*");
+ intent.setAction(Intent.ACTION_PICK);
+ startActivityForResult(intent, REQUEST_PICTURE_CHOOSE);
+ break;
+
+ case R.id.online_camera:
+ // 设置相机拍照后照片保存路径
+ mPictureFile = new File(getExternalFilesDir("msc").getAbsolutePath(),
+ "picture" + System.currentTimeMillis() / 1000 + ".jpg");
+ // 启动拍照,并保存到临时文件
+ Intent mIntent = new Intent();
+ mIntent.setAction(MediaStore.ACTION_IMAGE_CAPTURE);
+ mIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(mPictureFile));
+ mIntent.putExtra(MediaStore.Images.Media.ORIENTATION, 0);
+ startActivityForResult(mIntent, REQUEST_CAMERA_IMAGE);
+ break;
+
+ case R.id.btn_identity:
+ if (null != mImageData) {
+ mProDialog.setMessage("鉴别中...");
+ mProDialog.show();
+ // 清空参数
+ mIdVerifier.setParameter(SpeechConstant.PARAMS, null);
+ // 设置业务场景
+ mIdVerifier.setParameter(SpeechConstant.MFV_SCENES, "ifr");
+ // 设置业务类型
+ mIdVerifier.setParameter(SpeechConstant.MFV_SST, "identify");
+ // 设置监听器,开始会话
+ mIdVerifier.startWorking(mSearchListener);
+
+ // 子业务执行参数,若无可以传空字符传
+ StringBuffer params = new StringBuffer();
+ params.append(",group_id=" + mGroupId + ",topc=3");
+ // 向子业务写入数据,人脸数据可以一次写入
+ mIdVerifier.writeData("ifr", params.toString(), mImageData, 0, mImageData.length);
+ // 写入完毕
+ mIdVerifier.stopWrite("ifr");
+ } else {
+ showTip("请选择图片后再鉴别");
+ }
+ break;
+ default:
+ break;
+ }
+ }
+
+ protected void handleResult(IdentityResult result) {
+ if (null == result) {
+ return;
+ }
+
+ try {
+ String resultStr = result.getResultString();
+ JSONObject resultJson = new JSONObject(resultStr);
+ if (ErrorCode.SUCCESS == resultJson.getInt("ret")) {
+ // 跳转到结果展示页面
+ Intent intent = new Intent(FaceIdentifyActivity.this, ResultIdentifyActivity.class);
+ intent.putExtra("result", resultStr);
+ startActivity(intent);
+ this.finish();
+ } else {
+ showTip("鉴别失败!");
+ }
+ } catch (JSONException e) {
+ e.printStackTrace();
+ }
+ }
+
+ @Override
+ protected void onActivityResult(int requestCode, int resultCode, Intent data) {
+ if (resultCode != RESULT_OK) {
+ return;
+ }
+
+ String fileSrc = null;
+ if (requestCode == REQUEST_PICTURE_CHOOSE) {
+ if ("file".equals(data.getData().getScheme())) {
+ // 有些低版本机型返回的Uri模式为file
+ fileSrc = data.getData().getPath();
+ } else {
+ // Uri模型为content
+ String[] proj = {MediaStore.Images.Media.DATA};
+ Cursor cursor = getContentResolver().query(data.getData(), proj,
+ null, null, null);
+ cursor.moveToFirst();
+ int idx = cursor.getColumnIndexOrThrow(MediaStore.Images.Media.DATA);
+ fileSrc = cursor.getString(idx);
+ cursor.close();
+ }
+ // 跳转到图片裁剪页面
+ cropPicture(this, Uri.fromFile(new File(fileSrc)));
+ } else if (requestCode == REQUEST_CAMERA_IMAGE) {
+ if (null == mPictureFile) {
+ showTip("拍照失败,请重试");
+ return;
+ }
+
+ fileSrc = mPictureFile.getAbsolutePath();
+ updateGallery(fileSrc);
+ // 跳转到图片裁剪页面
+ cropPicture(this, Uri.fromFile(new File(fileSrc)));
+ } else if (requestCode == REQUEST_INTENT_CROP) {
+
+ // 获取返回数据
+ Bitmap bmp = data.getParcelableExtra("data");
+
+ // 获取裁剪后图片保存路径
+ fileSrc = getImagePath();
+
+ // 若返回数据不为null,保存至本地,防止裁剪时未能正常保存
+ if (null != bmp) {
+ saveBitmapToFile(bmp);
+ }
+
+ // 获取图片的宽和高
+ Options options = new Options();
+ options.inJustDecodeBounds = true;
+ mImageBitmap = BitmapFactory.decodeFile(fileSrc, options);
+
+ // 压缩图片
+ options.inSampleSize = Math.max(1, (int) Math.ceil(Math.max(
+ (double) options.outWidth / 1024f,
+ (double) options.outHeight / 1024f)));
+ options.inJustDecodeBounds = false;
+ mImageBitmap = BitmapFactory.decodeFile(fileSrc, options);
+
+ // 若mImageBitmap为空则图片信息不能正常获取
+ if (null == mImageBitmap) {
+ showTip("图片信息无法正常获取!");
+ return;
+ }
+
+ // 部分手机会对图片做旋转,这里检测旋转角度
+ int degree = readPictureDegree(fileSrc);
+ if (degree != 0) {
+ // 把图片旋转为正的方向
+ mImageBitmap = rotateImage(degree, mImageBitmap);
+ }
+
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+
+ //可根据流量及网络状况对图片进行压缩
+ mImageBitmap.compress(Bitmap.CompressFormat.JPEG, 80, baos);
+ mImageData = baos.toByteArray();
+
+ ((ImageView) findViewById(R.id.online_img)).setImageBitmap(mImageBitmap);
+ }
+ }
+
+ @Override
+ public void finish() {
+ if (null != mProDialog) {
+ mProDialog.dismiss();
+ }
+ setResult(RESULT_OK);
+ super.finish();
+ }
+
+ @Override
+ protected void onDestroy() {
+ super.onDestroy();
+
+ if (null != mIdVerifier) {
+ mIdVerifier.destroy();
+ mIdVerifier = null;
+ }
+ }
+
+ /**
+ * 读取图片属性:旋转的角度
+ *
+ * @param path 图片绝对路径
+ * @return degree 旋转的角度
+ */
+ public static int readPictureDegree(String path) {
+ int degree = 0;
+ try {
+ ExifInterface exifInterface = new ExifInterface(path);
+ int orientation = exifInterface.getAttributeInt(
+ ExifInterface.TAG_ORIENTATION,
+ ExifInterface.ORIENTATION_NORMAL);
+ switch (orientation) {
+ case ExifInterface.ORIENTATION_ROTATE_90:
+ degree = 90;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_180:
+ degree = 180;
+ break;
+ case ExifInterface.ORIENTATION_ROTATE_270:
+ degree = 270;
+ break;
+ }
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ return degree;
+ }
+
+ private void updateGallery(String filename) {
+ MediaScannerConnection.scanFile(this, new String[]{filename}, null,
+ new MediaScannerConnection.OnScanCompletedListener() {
+
+ @Override
+ public void onScanCompleted(String path, Uri uri) {
+
+ }
+ });
+ }
+
+ /**
+ * 旋转图片
+ *
+ * @param angle
+ * @param bitmap
+ * @return Bitmap
+ */
+ public static Bitmap rotateImage(int angle, Bitmap bitmap) {
+ // 图片旋转矩阵
+ Matrix matrix = new Matrix();
+ matrix.postRotate(angle);
+ // 得到旋转后的图片
+ Bitmap resizedBitmap = Bitmap.createBitmap(bitmap, 0, 0,
+ bitmap.getWidth(), bitmap.getHeight(), matrix, true);
+ return resizedBitmap;
+ }
+
+ /**
+ * Toast弹出提示
+ *
+ * @param str
+ */
+ private void showTip(final String str) {
+ mToast.setText(str);
+ mToast.show();
+ }
+
+
+ /***
+ * 裁剪图片
+ * @param activity Activity
+ * @param uri 图片的Uri
+ */
+ public void cropPicture(Activity activity, Uri uri) {
+ Intent innerIntent = new Intent("com.android.camera.action.CROP");
+ innerIntent.setDataAndType(uri, "image/*");
+ innerIntent.putExtra("crop", "true");// 才能出剪辑的小方框,不然没有剪辑功能,只能选取图片
+ innerIntent.putExtra("aspectX", 1); // 放大缩小比例的X
+ innerIntent.putExtra("aspectY", 1);// 放大缩小比例的X 这里的比例为: 1:1
+ innerIntent.putExtra("outputX", 320); //这个是限制输出图片大小
+ innerIntent.putExtra("outputY", 320);
+ innerIntent.putExtra("return-data", true);
+ // 切图大小不足输出,无黑框
+ innerIntent.putExtra("scale", true);
+ innerIntent.putExtra("scaleUpIfNeeded", true);
+ innerIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new File(getImagePath())));
+ innerIntent.putExtra("outputFormat", Bitmap.CompressFormat.JPEG.toString());
+ activity.startActivityForResult(innerIntent, REQUEST_INTENT_CROP);
+ }
+
+ /**
+ * 设置保存图片路径
+ *
+ * @return
+ */
+ private String getImagePath() {
+ String path = getExternalFilesDir("msc_face").getAbsolutePath() + "/MFVDemo";
+ File folder = new File(path);
+ if (!folder.exists()) {
+ folder.mkdirs();
+ }
+ path += "/mfvtest.jpg";
+ return path;
+ }
+
+ /**
+ * 保存Bitmap至本地
+ *
+ * @param bmp
+ */
+ private void saveBitmapToFile(Bitmap bmp) {
+ String file_path = getImagePath();
+ File file = new File(file_path);
+ FileOutputStream fOut;
+ try {
+ fOut = new FileOutputStream(file);
+ bmp.compress(Bitmap.CompressFormat.JPEG, 85, fOut);
+ fOut.flush();
+ fOut.close();
+ } catch (FileNotFoundException e) {
+ e.printStackTrace();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+ }
+
+ private void dismissProDialog() {
+ if (null != mProDialog) {
+ mProDialog.dismiss();
+ }
+ }
+}
diff --git a/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IdentifyGroup/GroupManagerActivity.java b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IdentifyGroup/GroupManagerActivity.java
new file mode 100644
index 0000000..6d56e72
--- /dev/null
+++ b/src/讯飞SDK/sample/speechDemo/src/main/java/com/iflytek/voicedemo/IdentifyGroup/GroupManagerActivity.java
@@ -0,0 +1,534 @@
+package com.iflytek.voicedemo.IdentifyGroup;
+
+import android.annotation.SuppressLint;
+import android.app.Activity;
+import android.app.ProgressDialog;
+import android.content.Context;
+import android.content.DialogInterface;
+import android.content.DialogInterface.OnCancelListener;
+import android.content.Intent;
+import android.os.Bundle;
+import android.text.TextUtils;
+import android.util.Log;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.View.OnClickListener;
+import android.view.ViewGroup;
+import android.view.Window;
+import android.widget.AdapterView;
+import android.widget.BaseAdapter;
+import android.widget.Button;
+import android.widget.EditText;
+import android.widget.ListView;
+import android.widget.RelativeLayout;
+import android.widget.TextView;
+import android.widget.Toast;
+
+import com.iflytek.cloud.IdentityListener;
+import com.iflytek.cloud.IdentityResult;
+import com.iflytek.cloud.IdentityVerifier;
+import com.iflytek.cloud.SpeechConstant;
+import com.iflytek.cloud.SpeechError;
+import com.iflytek.voicedemo.R;
+
+import org.json.JSONException;
+import org.json.JSONObject;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Map;
+
+/**
+ * 声纹密码和人脸识别相关组操作
+ * 支持组创建/添加成员/查询组成员/删除成员/删除组/
+ *
+ * @author hjyu
+ * @date 2017/9/28.
+ * @see this#createGroup()
+ * @see this#joinGroup(String)
+ * @see //this#queryGroups()
+ * @see this#deleteGroup(String, boolean) ,第二个参数用于标示删除组成员or组
+ * @see 讯飞开放平台
+ */
+public class GroupManagerActivity extends Activity implements OnClickListener, AdapterView.OnItemClickListener {
+ private final static String TAG = GroupManagerActivity.class.getSimpleName();
+ // 身份验证对象
+ private IdentityVerifier mIdVerifier;
+ // 用户名信息
+ private TextView mUserNameText;
+
+ EditText etGroupId;
+ EditText etGroupName;
+ private Toast mToast;
+ MyAdapter adapter;
+ private ProgressDialog mProDialog;
+ String authId;
+ String mfv_type;
+ ArrayList