微信公號(hào)開發(fā)之文本消息技巧:長(zhǎng)度限制、換行和表情
微信公眾賬號(hào)文本消息的內(nèi)容長(zhǎng)度限制揭秘
相信不少朋友都遇到過這樣的問題:當(dāng)發(fā)送的文本消息內(nèi)容過長(zhǎng)時(shí),微信將不做任何響應(yīng)。那么到底微信允許的文本消息的***長(zhǎng)度是多少呢?我們又該如何計(jì)算文本的長(zhǎng)度呢?為什么還有些人反應(yīng)微信好像支持的文本消息***長(zhǎng)度在1300多呢?這篇文章會(huì)徹底解除大家的疑問。
接口文檔中對(duì)消息長(zhǎng)度限制為2048:
可以看到,接口文檔中寫的很明確:回復(fù)的消息內(nèi)容長(zhǎng)度不超過2048字節(jié)。那為什么很多人測(cè)試反應(yīng)消息內(nèi)容長(zhǎng)度在1300多字節(jié)時(shí),微信就不響應(yīng)了呢?我想這問題應(yīng)該在這部分人沒有搞清楚到底該如何計(jì)算文本的字節(jié)數(shù)。
如何正確計(jì)算文本所占字節(jié)數(shù)
計(jì)算文本(字符串)所占字節(jié)數(shù),大家***個(gè)想到的應(yīng)該就是String類的getBytes()方法,該方法返回的是字符串對(duì)應(yīng)的字節(jié)數(shù)組,再計(jì)算數(shù)組的length就能夠得到字符串所占字節(jié)數(shù)。例如:
- public static void main(String []args) {
- // 運(yùn)行結(jié)果:4
- System.out.println("柳峰".getBytes().length);
- }
上面的示例中計(jì)算了兩個(gè)中文所占的字節(jié)數(shù)為4,即一個(gè)漢字占2個(gè)字節(jié)。真的是這樣嗎?其實(shí)我們忽略了一個(gè)問題:對(duì)于不同的編碼方式,中文所占的字節(jié)數(shù)也不 一樣!這到底要怎么呢?在上面的例子中,我們并沒有指定編碼方式,那么會(huì)使用操作系統(tǒng)所默認(rèn)的編碼方式。先來看我得出的三條結(jié)論:
1)如果上面的例子運(yùn)行在默認(rèn)編碼方式為ISO8859-1的操作系統(tǒng)平臺(tái)上,計(jì)算結(jié)果是2;
2)如果上面的例子運(yùn)行在默認(rèn)編碼方式為gb2312或gbk的操作系統(tǒng)平臺(tái)上,計(jì)算結(jié)果是4;
3)如果上面的例子運(yùn)行在默認(rèn)編碼方式為utf-8的操作系統(tǒng)平臺(tái)上,計(jì)算結(jié)果是6;
如果真的是這樣,是不是意味著String.getBytes()方法在我們的系統(tǒng)平臺(tái)上默認(rèn)采用的是gb2312或gbk編碼方式呢?我們?cè)賮砜匆粋€(gè)例子:
- public static void main(String []args) throws UnsupportedEncodingException {
- // 運(yùn)行結(jié)果:2
- System.out.println("柳峰".getBytes("ISO8859-1").length);
- // 運(yùn)行結(jié)果:4
- System.out.println("柳峰".getBytes("GB2312").length);
- // 運(yùn)行結(jié)果:4
- System.out.println("柳峰".getBytes("GBK").length);
- // 運(yùn)行結(jié)果:6
- System.out.println("柳峰".getBytes("UTF-8").length);
- }
這個(gè)例子是不是很好地證明了我上面給出的三條結(jié)論呢?也就是說采用ISO8859-1編碼方式時(shí),一個(gè)中/英文都只占一個(gè)字節(jié);采用GB2312或GBK編碼方式時(shí),一個(gè)中文占兩個(gè)字節(jié);而采用UTF-8編碼方式時(shí),一個(gè)中文占三個(gè)字節(jié)。
微信平臺(tái)采用的編碼方式及字符串所占字節(jié)數(shù)的計(jì)算
那么,在向微信服務(wù)器返回消息時(shí),該采用什么編碼方式呢?當(dāng)然是UTF-8,因?yàn)槲覀円呀?jīng)在doPost方法里采用了如下代碼來避免中文亂碼了:
- // 將請(qǐng)求、響應(yīng)的編碼均設(shè)置為UTF-8(防止中文亂碼)
- request.setCharacterEncoding("UTF-8");
- response.setCharacterEncoding("UTF-8");
getMsgContent()方法返回的內(nèi)容正是微信的文本消息最長(zhǎng)能夠支持的,即采用UTF-8編碼方式時(shí),文本消息內(nèi)容最多支持2047個(gè)字節(jié),也就是微信公眾平臺(tái)接口文檔里所說的回復(fù)的消息內(nèi)容長(zhǎng)度不超過2048字節(jié),即使是等于2048字節(jié)也不行,你可以試著將getMsgContent()方法里的內(nèi)容多加一個(gè)英文符號(hào),這個(gè)時(shí)候微信就不響應(yīng)了。
同時(shí),我們也發(fā)現(xiàn),如果采用gb2312編碼方式來計(jì)算getMsgContent()方法返回的文本所占字節(jié)數(shù)的結(jié)果是1365,這就是為什么很 多朋友都說微信的文本消息***長(zhǎng)度好像只支持1300多字節(jié),并不是接口文檔中所說的2048字節(jié),其實(shí)是忽略了編碼方式,只是簡(jiǎn)單的使用了String 類的getBytes()方法而不是getBytes("utf-8")方法去計(jì)算所占字節(jié)數(shù)。
Java中utf-8編碼方式時(shí)所占字節(jié)數(shù)的計(jì)算方法封裝
- /**
- * 計(jì)算采用utf-8編碼方式時(shí)字符串所占字節(jié)數(shù)
- *
- * @param content
- * @return
- */
- public static int getByteSize(String content) {
- int size = 0;
- if (null != content) {
- try {
- // 漢字采用utf-8編碼時(shí)占3個(gè)字節(jié)
- size = content.getBytes("utf-8").length;
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
- return size;
- }
#p#
文本消息中換行符的使用
使用換行的好處及示例
使用換行的好處無非就是讓信息的呈現(xiàn)更加整齊、美觀和直觀,適當(dāng)?shù)脑谖谋鞠⒅惺褂脫Q行符,會(huì)讓人看了之后感覺很舒服、清晰、明了。下面是公眾帳號(hào)xiaoqrobot的主菜單示例,就是合理地使用了換行符,看上去是不是很直觀、清爽呢?
如何在文本消息中使用換行符?
在微信公眾帳號(hào)的文本消息中,換行符仍然是“\n”,下面就通過代碼來講解xiaoqrobot的文本菜單是如何實(shí)現(xiàn)的?
- /**
- * xiaoqrobot的主菜單
- *
- * @return
- */
- public static String getMainMenu() {
- StringBuffer buffer = new StringBuffer();
- buffer.append("您好,我是小q,請(qǐng)回復(fù)數(shù)字選擇服務(wù):").append("\n\n");
- buffer.append("1 天氣預(yù)報(bào)").append("\n");
- buffer.append("2 公交查詢").append("\n");
- buffer.append("3 周邊搜索").append("\n");
- buffer.append("4 歌曲點(diǎn)播").append("\n");
- buffer.append("5 經(jīng)典游戲").append("\n");
- buffer.append("6 美女電臺(tái)").append("\n");
- buffer.append("7 人臉識(shí)別").append("\n");
- buffer.append("8 聊天嘮嗑").append("\n\n");
- buffer.append("回復(fù)“?”顯示此幫助菜單");
- return buffer.toString();
- }
怎么樣,實(shí)現(xiàn)起來是不是很簡(jiǎn)單呢?
1)9-16行就是菜單項(xiàng),菜單項(xiàng)之間都是用一個(gè)換行符分隔;
2)第8行、第16號(hào)末尾都使用了兩個(gè)換行符,這樣可以把菜單項(xiàng)與其他內(nèi)容分隔開,更有層次感,看上去也會(huì)舒服、直觀一點(diǎn)。
#p#
QQ表情的發(fā)送與接收
我想大家對(duì)QQ表情一定不會(huì)陌生,一個(gè)個(gè)小頭像極大豐富了聊天的樂趣,使得聊天不再是簡(jiǎn)單的文字?jǐn)⑹?,還能夠配上喜、怒、哀、樂等表達(dá)人物心情的小圖片。本文重點(diǎn)要介紹的內(nèi)容就是如何在微信公眾平臺(tái)使用QQ表情,即在微信公眾帳號(hào)開發(fā)模式下,如何發(fā)送QQ表情給用戶,以及如何識(shí)別用戶發(fā)來的是QQ表情。
QQ表情代碼表
首先需要明確的是:QQ表情雖然呈現(xiàn)為一張張動(dòng)態(tài)的表情圖片,但在微信公眾平臺(tái)的消息接口中卻是屬于文本消息;也就是說當(dāng)用戶向公眾帳號(hào)發(fā)送QQ表情時(shí),公眾帳號(hào)后臺(tái)程序接收到的消息類型MsgType的值為text。只要上面這點(diǎn)能理解了,下面的工作就好開展了。
對(duì)于QQ表情,發(fā)送的是文本消息,而呈現(xiàn)出來卻是表情圖片,那么每一個(gè)QQ表情圖片一定會(huì)有與之相對(duì)應(yīng)的表情代碼。下面是我已經(jīng)整理好的微信公眾帳號(hào)中使用的QQ表情代碼對(duì)照表:
上面一共列出了105個(gè)QQ表情,每個(gè)表情都給出了與之相對(duì)應(yīng)的文字代碼與符號(hào)代碼(也許這兩種叫法并不恰當(dāng)),至于這兩種代碼怎么來的以及如何使用,下面馬上會(huì)講到。
用戶向公眾帳號(hào)發(fā)送QQ表情
在微信上使用公眾帳號(hào)時(shí),如何發(fā)送QQ表情,我想這個(gè)很少有人不會(huì)的。在輸入框旁邊有一個(gè)笑臉的圖片按鈕,點(diǎn)擊它將會(huì)彈出表情選擇界面,可選擇的表情依次為“QQ表情”、“符號(hào)表情”和“動(dòng)畫表情”。當(dāng)我們點(diǎn)擊選擇了某個(gè)QQ表情后,發(fā)現(xiàn)在輸入框中會(huì)顯示該表情的文字代碼,這里是用一對(duì)中括號(hào)引起的,如下圖所示:
其實(shí),當(dāng)我們很熟悉要使用QQ表情的文字代碼時(shí),也可以直接在輸入框中輸入表情的代碼,而不需要彈出表情選擇框。如下圖所示:
從上圖可以看出,在輸入框中輸入“[呲牙]”、“/呲牙”和“/::D”這三種代碼的作用一樣,都是發(fā)送呲牙的QQ表情。這個(gè)時(shí)候,大家再回過頭去看文章最開始的QQ表情代碼對(duì)照表,就明白是怎么回事了。
公眾帳號(hào)向用戶發(fā)送QQ表情
與用戶向公眾帳號(hào)發(fā)送QQ表情一樣,在開發(fā)模式下,公眾帳號(hào)也可以用同樣的表情代碼(文字代碼或符號(hào)代碼)向用戶回復(fù)QQ表情。代碼片段如下:
- // 文本消息
- if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
- // 回復(fù)文本消息
- TextMessage textMessage = new TextMessage();
- textMessage.setToUserName(fromUserName);
- textMessage.setFromUserName(toUserName);
- textMessage.setCreateTime(new Date().getTime());
- textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
- textMessage.setFuncFlag(0);
- textMessage.setContent("[難過] /難過 /::(");
- // 文本消息對(duì)象轉(zhuǎn)換成xml字符串
- respMessage = MessageUtil.textMessageToXml(textMessage);
- }
上面代碼片段的作用是:判斷發(fā)送的消息類型,如果是文本消息(MsgType=text),則回復(fù)三個(gè)難過的QQ表情給用戶。可以看出,不管是用戶發(fā)給公眾帳號(hào),還是公眾帳號(hào)發(fā)給用戶,都可以使用QQ表情的文字代碼(如:[難過] /難過)和符號(hào)代碼(如 /::()。
公眾帳號(hào)識(shí)別用戶發(fā)送的QQ表情
在掌握了如何發(fā)送QQ表情后,我們?cè)賮砜纯垂妿ぬ?hào)如何識(shí)別用戶發(fā)送的是QQ表情。這是什么意思呢?當(dāng)用戶向公眾帳號(hào)發(fā)送一個(gè)QQ表情,在后臺(tái)程序中接收到的會(huì)是什么值,我們又怎么知道這個(gè)值就是一個(gè)QQ表情。
其實(shí),只要做個(gè)簡(jiǎn)單的測(cè)試,比如:將接收到的文本消息輸出到日志中(可以用log4j或者System.out.print),不難發(fā)現(xiàn):向公眾帳號(hào)發(fā)送一個(gè)QQ表情,在后臺(tái)程序中接收到的是QQ表情的符號(hào)代碼。
下面是我簡(jiǎn)單封裝的一個(gè)方法,通過正則表達(dá)式實(shí)現(xiàn)的,用于判斷用戶發(fā)送的是否是單個(gè)QQ表情。
- /**
- * 判斷是否是QQ表情
- *
- * @param content
- * @return
- */
- public static boolean isQqFace(String content) {
- boolean result = false;
- // 判斷QQ表情的正則表達(dá)式
- String qqfaceRegex = "/::\\)|/::~|/::B|/::\\||/:8-\\)|/::<|/::$|/::X|/::Z|/::'\\(|/::-\\||/::@|/::P|/::D|/::O|/::\\(|/::\\+|/:--b|/::Q|/::T|/:,@P|/:,@-D|/::d|/:,@o|/::g|/:\\|-\\)|/::!|/::L|/::>|/::,@|/:,@f|/::-S|/:\\?|/:,@x|/:,@@|/::8|/:,@!|/:!!!|/:xx|/:bye|/:wipe|/:dig|/:handclap|/:&-\\(|/:B-\\)|/:<@|/:@>|/::-O|/:>-\\||/:P-\\(|/::'\\||/:X-\\)|/::\\*|/:@x|/:8\\*|/:pd|/:<W>|/:beer|/:basketb|/:oo|/:coffee|/:eat|/:pig|/:rose|/:fade|/:showlove|/:heart|/:break|/:cake|/:li|/:bome|/:kn|/:footb|/:ladybug|/:shit|/:moon|/:sun|/:gift|/:hug|/:strong|/:weak|/:share|/:v|/:@\\)|/:jj|/:@@|/:bad|/:lvu|/:no|/:ok|/:love|/:<L>|/:jump|/:shake|/:<O>|/:circle|/:kotow|/:turn|/:skip|/:oY|/:#-0|/:hiphot|/:kiss|/:<&|/:&>";
- Pattern p = Pattern.compile(qqfaceRegex);
- Matcher m = p.matcher(content);
- if (m.matches()) {
- result = true;
- }
- return result;
- }
下面是方法的使用,實(shí)現(xiàn)了這樣一個(gè)簡(jiǎn)單的功能:用戶發(fā)什么QQ表情給公眾帳號(hào),公眾帳號(hào)就回復(fù)什么QQ表情給用戶(xiaoqrobot就是這么做的)。實(shí)現(xiàn)代碼如下:
- // 文本消息
- if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
- // 文本消息內(nèi)容
- String content = requestMap.get("Content");
- // 判斷用戶發(fā)送的是否是單個(gè)QQ表情
- if(XiaoqUtil.isQqFace(content)) {
- // 回復(fù)文本消息
- TextMessage textMessage = new TextMessage();
- textMessage.setToUserName(fromUserName);
- textMessage.setFromUserName(toUserName);
- textMessage.setCreateTime(new Date().getTime());
- textMessage.setMsgType(MessageUtil.RESP_MESSAGE_TYPE_TEXT);
- textMessage.setFuncFlag(0);
- // 用戶發(fā)什么QQ表情,就返回什么QQ表情
- textMessage.setContent(content);
- // 將文本消息對(duì)象轉(zhuǎn)換成xml字符串
- respMessage = MessageUtil.textMessageToXml(textMessage);
- }
- }
好了,關(guān)于微信公眾帳號(hào)中QQ表情的使用就介紹這么多。其實(shí),我并不希望初學(xué)者上來只是簡(jiǎn)單拷貝我貼出的代碼,實(shí)現(xiàn)了自己想要的功能就完事了,更希望初學(xué)的朋友能夠通過此文章學(xué)會(huì)一種思考問題和解決問題的方法。