91超碰碰碰碰久久久久久综合_超碰av人澡人澡人澡人澡人掠_国产黄大片在线观看画质优化_txt小说免费全本

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Emoji表情在Android JNI中的兼容性問題詳解

發布時間:2020-10-01 00:49:51 來源:腳本之家 閱讀:150 作者:Darkness463 欄目:移動開發

起因

最近遇到一個問題,把某個字符串計算MD5,之后把該字符串加密與MD5一起上傳到服務端,服務端解密后重新計算md5發現與上傳的MD5不一致,而出問題的字符串中無一例外都有Emoji表情。但我自己弄個帶表情的字符串上傳卻沒有什么問題。

最終確認這是在Android 5.1以下 jstring -> char數組 時出的問題。下面通過一個示例來還原這個過程。

事件還原

假設有一個字符串s,String s = "\uD83D\uDC8B"; ,對應表情💋。通過調用getBytes()方法,會看到對應的byte數組為[-16, -97, -110, -117] ,按16進制輸出為[f0, 9f, 92, 8b]

定義一個參數為String的native方法,public native String test(String str); ,在對應的C/C++代碼中,通過env->GetStringUTFChars獲取傳入的String對應的char數組,把char數組的每一個元素按16進制輸出。

在Android 7.1.2的測試機上,native層輸出的結果為[f0, 9f, 92, 8b] ,與Java的byte數組是一樣的,但是在Android 4.4.4的測試機上,輸出結果為[ed, a0, bd, ed, b2, 8b] 。從而導致加密后的結果不一樣。

服務端收到舊版Android的數據解密后得到[ed, a0, bd, ed, b2, 8b] ,計算MD5自然無法與[f0, 9f, 92, 8b]計算MD5一樣。

Unicode、UTF-8、UTF-16

可能有人不是很清楚上面那2種byte數組是怎么來的。首先我們要知道,UTF-8和UTF-16都是Unicode的實現。\uD83D\uDC8B其實是UTF-16大端的表現形式,對于大于0xFFFF(0x10000~0x10FFFF)的Unicode,轉換為UTF-16的步驟如下:

  1. 將Unicode減去0x10000,結果將是一個長度為20bit的值。
  2. 將第一步的20bit的高10bit與0xD800進行或運算,得到UTF-16的高位代理。
  3. 將第一步的20bit的低10bit與0xDC00進行或運算,得到UTF-16的低位代理。
  4. 高位代理+低位代理即Unicode對應的UTF-16的大端形式。

按照這個步驟反推:

  1. \uD83D\uDC8B的二進制位1101 1000 0011 1101 1101 1100 1000 1011,則高位代理為1101 1000 0011 1101,低位代理為1101 1100 1000 1011。
  2. 高位代理由高10bit與0xD800進行或運算得到,因此高10bit為00 0011 1101。
  3. 低位代理由低10bit與0xDC00進行或運算得到,因此低10bit為00 1000 1011。
  4. 所有20bit的值為0000 1111 0100 1000 1011。
  5. 加上0x10000,為0001 1111 0100 1000 1011,即0x1F48B。

所以,表情💋對應的Unicode為0x1F48B。

Emoji表情在Android JNI中的兼容性問題詳解

UTF-8的規則是,對于占N個字節的符號(N>1),第一個字節前N位都是1,N+1位是0,后面的字節前2位為10,然后把Unicode的二進制位填入空缺的二進制位中,空出的位置補0。因此,上面的Unicode 0x1F48B轉為UTF-8需要占4個字節,為:

11110 000
10 011111
10 010010
10 001011

即0xF09F928B,這也就是[f0, 9f, 92, 8b]這個byte數組的由來。

Emoji表情在Android JNI中的兼容性問題詳解

那么[ed, a0, bd, ed, b2, 8b]這個byte數組又是怎么來的呢?這是把\uD83D\uDC8B當成2個單獨的字符處理了,按照上面Unicode轉UTF-8的邏輯,Unicode 0xD83D轉為UTF-8為1110 1101 10 100000 10 111101,即0xEDA0BD,Unicode 0xDC8B轉為UTF-8為1110 1101 10 110010 10 001011,即0xEDB28B。

Emoji表情在Android JNI中的兼容性問題詳解

總結

以上就是這篇文章的全部內容了,希望本文的內容對大家的學習或者工作具有一定的參考學習價值,謝謝大家對億速云的支持。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

清水河县| 陵川县| 越西县| 将乐县| 松阳县| 长海县| 浮山县| 石渠县| 鹿邑县| 开封县| 杭锦旗| 江口县| 辉南县| 城口县| 西吉县| 定南县| 犍为县| 普陀区| 郑州市| 都江堰市| 多伦县| 泰宁县| 上饶市| 芦溪县| 台山市| 棋牌| 康马县| 凤冈县| 德昌县| 黎川县| 淳安县| 伽师县| 尼木县| 奉新县| 内丘县| 三台县| 阿荣旗| 夹江县| 乌鲁木齐县| 泌阳县| 渝北区|