微信公號開發之文本消息技巧:長度限制、換行和表情
微信公眾賬號文本消息的內容長度限制揭秘
相信不少朋友都遇到過這樣的問題:當發送的文本消息內容過長時,微信將不做任何響應。那么到底微信允許的文本消息的***長度是多少呢?我們又該如何計算文本的長度呢?為什么還有些人反應微信好像支持的文本消息***長度在1300多呢?這篇文章會徹底解除大家的疑問。
接口文檔中對消息長度限制為2048:
可以看到,接口文檔中寫的很明確:回復的消息內容長度不超過2048字節。那為什么很多人測試反應消息內容長度在1300多字節時,微信就不響應了呢?我想這問題應該在這部分人沒有搞清楚到底該如何計算文本的字節數。
如何正確計算文本所占字節數
計算文本(字符串)所占字節數,大家***個想到的應該就是String類的getBytes()方法,該方法返回的是字符串對應的字節數組,再計算數組的length就能夠得到字符串所占字節數。例如:
- public static void main(String []args) {
- // 運行結果:4
- System.out.println("柳峰".getBytes().length);
- }
上面的示例中計算了兩個中文所占的字節數為4,即一個漢字占2個字節。真的是這樣嗎?其實我們忽略了一個問題:對于不同的編碼方式,中文所占的字節數也不 一樣!這到底要怎么呢?在上面的例子中,我們并沒有指定編碼方式,那么會使用操作系統所默認的編碼方式。先來看我得出的三條結論:
1)如果上面的例子運行在默認編碼方式為ISO8859-1的操作系統平臺上,計算結果是2;
2)如果上面的例子運行在默認編碼方式為gb2312或gbk的操作系統平臺上,計算結果是4;
3)如果上面的例子運行在默認編碼方式為utf-8的操作系統平臺上,計算結果是6;
如果真的是這樣,是不是意味著String.getBytes()方法在我們的系統平臺上默認采用的是gb2312或gbk編碼方式呢?我們再來看一個例子:
- public static void main(String []args) throws UnsupportedEncodingException {
- // 運行結果:2
- System.out.println("柳峰".getBytes("ISO8859-1").length);
- // 運行結果:4
- System.out.println("柳峰".getBytes("GB2312").length);
- // 運行結果:4
- System.out.println("柳峰".getBytes("GBK").length);
- // 運行結果:6
- System.out.println("柳峰".getBytes("UTF-8").length);
- }
這個例子是不是很好地證明了我上面給出的三條結論呢?也就是說采用ISO8859-1編碼方式時,一個中/英文都只占一個字節;采用GB2312或GBK編碼方式時,一個中文占兩個字節;而采用UTF-8編碼方式時,一個中文占三個字節。
微信平臺采用的編碼方式及字符串所占字節數的計算
那么,在向微信服務器返回消息時,該采用什么編碼方式呢?當然是UTF-8,因為我們已經在doPost方法里采用了如下代碼來避免中文亂碼了:
- // 將請求、響應的編碼均設置為UTF-8(防止中文亂碼)
- request.setCharacterEncoding("UTF-8");
- response.setCharacterEncoding("UTF-8");
getMsgContent()方法返回的內容正是微信的文本消息最長能夠支持的,即采用UTF-8編碼方式時,文本消息內容最多支持2047個字節,也就是微信公眾平臺接口文檔里所說的回復的消息內容長度不超過2048字節,即使是等于2048字節也不行,你可以試著將getMsgContent()方法里的內容多加一個英文符號,這個時候微信就不響應了。
同時,我們也發現,如果采用gb2312編碼方式來計算getMsgContent()方法返回的文本所占字節數的結果是1365,這就是為什么很 多朋友都說微信的文本消息***長度好像只支持1300多字節,并不是接口文檔中所說的2048字節,其實是忽略了編碼方式,只是簡單的使用了String 類的getBytes()方法而不是getBytes("utf-8")方法去計算所占字節數。
Java中utf-8編碼方式時所占字節數的計算方法封裝
- /**
- * 計算采用utf-8編碼方式時字符串所占字節數
- *
- * @param content
- * @return
- */
- public static int getByteSize(String content) {
- int size = 0;
- if (null != content) {
- try {
- // 漢字采用utf-8編碼時占3個字節
- size = content.getBytes("utf-8").length;
- } catch (UnsupportedEncodingException e) {
- e.printStackTrace();
- }
- }
- return size;
- }
#p#
文本消息中換行符的使用
使用換行的好處及示例
使用換行的好處無非就是讓信息的呈現更加整齊、美觀和直觀,適當的在文本消息中使用換行符,會讓人看了之后感覺很舒服、清晰、明了。下面是公眾帳號xiaoqrobot的主菜單示例,就是合理地使用了換行符,看上去是不是很直觀、清爽呢?
如何在文本消息中使用換行符?
在微信公眾帳號的文本消息中,換行符仍然是“\n”,下面就通過代碼來講解xiaoqrobot的文本菜單是如何實現的?
- /**
- * xiaoqrobot的主菜單
- *
- * @return
- */
- public static String getMainMenu() {
- StringBuffer buffer = new StringBuffer();
- buffer.append("您好,我是小q,請回復數字選擇服務:").append("\n\n");
- buffer.append("1 天氣預報").append("\n");
- buffer.append("2 公交查詢").append("\n");
- buffer.append("3 周邊搜索").append("\n");
- buffer.append("4 歌曲點播").append("\n");
- buffer.append("5 經典游戲").append("\n");
- buffer.append("6 美女電臺").append("\n");
- buffer.append("7 人臉識別").append("\n");
- buffer.append("8 聊天嘮嗑").append("\n\n");
- buffer.append("回復“?”顯示此幫助菜單");
- return buffer.toString();
- }
怎么樣,實現起來是不是很簡單呢?
1)9-16行就是菜單項,菜單項之間都是用一個換行符分隔;
2)第8行、第16號末尾都使用了兩個換行符,這樣可以把菜單項與其他內容分隔開,更有層次感,看上去也會舒服、直觀一點。
#p#
QQ表情的發送與接收
我想大家對QQ表情一定不會陌生,一個個小頭像極大豐富了聊天的樂趣,使得聊天不再是簡單的文字敘述,還能夠配上喜、怒、哀、樂等表達人物心情的小圖片。本文重點要介紹的內容就是如何在微信公眾平臺使用QQ表情,即在微信公眾帳號開發模式下,如何發送QQ表情給用戶,以及如何識別用戶發來的是QQ表情。
QQ表情代碼表
首先需要明確的是:QQ表情雖然呈現為一張張動態的表情圖片,但在微信公眾平臺的消息接口中卻是屬于文本消息;也就是說當用戶向公眾帳號發送QQ表情時,公眾帳號后臺程序接收到的消息類型MsgType的值為text。只要上面這點能理解了,下面的工作就好開展了。
對于QQ表情,發送的是文本消息,而呈現出來卻是表情圖片,那么每一個QQ表情圖片一定會有與之相對應的表情代碼。下面是我已經整理好的微信公眾帳號中使用的QQ表情代碼對照表:
上面一共列出了105個QQ表情,每個表情都給出了與之相對應的文字代碼與符號代碼(也許這兩種叫法并不恰當),至于這兩種代碼怎么來的以及如何使用,下面馬上會講到。
用戶向公眾帳號發送QQ表情
在微信上使用公眾帳號時,如何發送QQ表情,我想這個很少有人不會的。在輸入框旁邊有一個笑臉的圖片按鈕,點擊它將會彈出表情選擇界面,可選擇的表情依次為“QQ表情”、“符號表情”和“動畫表情”。當我們點擊選擇了某個QQ表情后,發現在輸入框中會顯示該表情的文字代碼,這里是用一對中括號引起的,如下圖所示:
其實,當我們很熟悉要使用QQ表情的文字代碼時,也可以直接在輸入框中輸入表情的代碼,而不需要彈出表情選擇框。如下圖所示:
從上圖可以看出,在輸入框中輸入“[呲牙]”、“/呲牙”和“/::D”這三種代碼的作用一樣,都是發送呲牙的QQ表情。這個時候,大家再回過頭去看文章最開始的QQ表情代碼對照表,就明白是怎么回事了。
公眾帳號向用戶發送QQ表情
與用戶向公眾帳號發送QQ表情一樣,在開發模式下,公眾帳號也可以用同樣的表情代碼(文字代碼或符號代碼)向用戶回復QQ表情。代碼片段如下:
- // 文本消息
- if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
- // 回復文本消息
- 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("[難過] /難過 /::(");
- // 文本消息對象轉換成xml字符串
- respMessage = MessageUtil.textMessageToXml(textMessage);
- }
上面代碼片段的作用是:判斷發送的消息類型,如果是文本消息(MsgType=text),則回復三個難過的QQ表情給用戶。可以看出,不管是用戶發給公眾帳號,還是公眾帳號發給用戶,都可以使用QQ表情的文字代碼(如:[難過] /難過)和符號代碼(如 /::()。
公眾帳號識別用戶發送的QQ表情
在掌握了如何發送QQ表情后,我們再來看看公眾帳號如何識別用戶發送的是QQ表情。這是什么意思呢?當用戶向公眾帳號發送一個QQ表情,在后臺程序中接收到的會是什么值,我們又怎么知道這個值就是一個QQ表情。
其實,只要做個簡單的測試,比如:將接收到的文本消息輸出到日志中(可以用log4j或者System.out.print),不難發現:向公眾帳號發送一個QQ表情,在后臺程序中接收到的是QQ表情的符號代碼。
下面是我簡單封裝的一個方法,通過正則表達式實現的,用于判斷用戶發送的是否是單個QQ表情。
- /**
- * 判斷是否是QQ表情
- *
- * @param content
- * @return
- */
- public static boolean isQqFace(String content) {
- boolean result = false;
- // 判斷QQ表情的正則表達式
- 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;
- }
下面是方法的使用,實現了這樣一個簡單的功能:用戶發什么QQ表情給公眾帳號,公眾帳號就回復什么QQ表情給用戶(xiaoqrobot就是這么做的)。實現代碼如下:
- // 文本消息
- if (msgType.equals(MessageUtil.REQ_MESSAGE_TYPE_TEXT)) {
- // 文本消息內容
- String content = requestMap.get("Content");
- // 判斷用戶發送的是否是單個QQ表情
- if(XiaoqUtil.isQqFace(content)) {
- // 回復文本消息
- 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);
- // 用戶發什么QQ表情,就返回什么QQ表情
- textMessage.setContent(content);
- // 將文本消息對象轉換成xml字符串
- respMessage = MessageUtil.textMessageToXml(textMessage);
- }
- }
好了,關于微信公眾帳號中QQ表情的使用就介紹這么多。其實,我并不希望初學者上來只是簡單拷貝我貼出的代碼,實現了自己想要的功能就完事了,更希望初學的朋友能夠通過此文章學會一種思考問題和解決問題的方法。