天天看點

Android之初識Emoji

在開發中突然需要傳Emoji,然而直接傳的話會報錯,而之前開發時又沒接觸夠Emoji,是以打算好好研究一下。

1.Emoji的形式

我想先列印出來看看Emoji是怎麼樣的,我就設斷,看看輸入Emoji之後的字元串是怎樣的,結果發生了十分有意思的事情。

在調試監聽的時候顯示的是豆腐塊

Android之初識Emoji

但是編譯器裡面又能顯示圖

Android之初識Emoji

再試試在Log中列印,直接就不顯示

Android之初識Emoji

做到這裡,已經不禁讓我懷疑人生,我發現我對String一無所知,瞬間真的有一種不知道要怎麼弄的感覺。

如果哪位大神知道,請告訴我為什麼String顯示Emoji時會這樣,謝謝。

雖然我不知道Emoji在String中到底是怎麼樣的,但是我可以用charAt()方法去檢視它的位址,發現charAt()後列印出這個(我用了另一個Emoji)

Android之初識Emoji

實在看不出,再試試charArray

Android之初識Emoji

CN是中國圖示的emoji

最後得到的結果是

Android之初識Emoji

看得出分割時一般會把一個表情分割成2個char,國旗分割成4個,還有一個的,也看不出什麼。

這什麼玩意,還是不知道,上網查了下,這個叫Unicode 編碼,這就很有意思了,那我就去看看編碼的一些基礎的知識。

2.編碼

我就算沒認真學過,都知道有個編碼叫utf-8,那它和Unicode 編碼有什麼關系呢。

1個位元組為8位,就是說1個位元組可以用8位二進制來表示。而8位二進制一共有256種情況,也就是2的8次方。

是以剛開始就出現了ASCII碼,它用每個情況表示一個符号,ASCII 碼一共定義了 128 個字元。

但是想想,世界上這麼多種符号,僅僅英文的話ASCII 碼是能解決,但是漢字都不止256種了,是以産生了Unicode 編碼,它就相當是ASCII 的一個擴充,但是,有會出現了一些問題,是以出現了UTF-8編碼(我這隻是簡單的說)就當是規範了Unicode 編碼。

是以Emoji得到的是Unicode編碼,那麼我就猜測一下為什麼在AS中有時出現亂碼,有時出現圖案,因為在debug中在編輯器裡面的是展示Unicode碼的,是以能正常顯示圖檔,而Logcat中的編碼方式是utf-8,是以顯示亂碼。

不管怎麼樣,關鍵是這個Edittext.toString()得到的String是不是有Emoji的啊

既然列印和打斷點不行,那我就隻能畫點時間搞個Demo了。

我做兩個Edittext和一個Button,點選按鈕時從第一個Edit擷取String然後顯示到第二個Edit

Android之初識Emoji

從結果可以看出,String裡面是有包含Emoji的隻是不能正常列印出來而已。

3.上傳到伺服器

既然能保證String含有Emoji,那麼下一步就是怎麼上傳到伺服器,直接把這個String上傳到伺服器是會報錯的。

(1)轉成Base64

先把字元串轉成Base64再上傳,這是我在網上看到的一篇文章,先測試下轉碼後再解碼能不能得到之前的形式。

btn.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                String str = edtUp.getText().toString();
                // 轉碼
                String str_count=  Base64.encodeToString(str.getBytes(),Base64.DEFAULT);
                // 解碼
                String str2 = new String(Base64.decode(str_count.getBytes(), Base64.DEFAULT));

                edtDown.setText(str2);
            }
        });
           
Android之初識Emoji

可以看出可以使用Base64轉碼和解碼是能成功得到Emoji的。轉之後就是一個字元串,資料是能儲存的,那接下來我就試試能不能把Emoji上傳到資料庫然後在傳回正常顯示。

測試中......測試内容保密......

最後得到結果并展示到textview

Android之初識Emoji

可以看出這樣的做成是可以的,就不用再寫什麼先轉換再拼接了。

4.屏蔽

直接上傳emoji會出錯,據說是因為

Android之初識Emoji

那這樣的話,解決這個的問題其實還是資料庫去改進,但是......你覺得你說一句“這個是背景的問題,你們來改”,背景人員就會改嗎?他隻會說“你們前端先想辦法解決一下。”沒錯,受欺負的永遠是前端,那怎麼辦,那我們隻好想辦法屏蔽咯。

(1)網上有很多判斷的方法,但是我真的不敢用,有些評論說某些不完整,搞得我都不知道哪些是能用的,哪些是判斷不完整的。

但是我又找不到其它解決的辦法,總覺得屏蔽真麻煩,最直接的辦法還是背景給改了,但是人家肯定不願意弄,那我就貼上代碼(真的很擔心這個判斷會不會又漏)

/**
     *  屏蔽emoji
     */
    public static String deleteEmoji(String str){
        StringBuffer sb = new StringBuffer();
        char[] charArray = str.toCharArray();
        for (int i = 0; i < charArray.length; i++) {
            if (!isEmojiCharacter(charArray[i])) {
                sb.append(charArray[i]);
            }
        }
        return sb.toString();
    }

/**
     *  todo 這是網上找的判斷區間,不知道完不完整,暫時先用
     * @param codePoint
     * @return
     */
    private static boolean isEmojiCharacter(char codePoint) {
        return !((codePoint == 0x0) ||
                (codePoint == 0x9) ||
                (codePoint == 0xA) ||
                (codePoint == 0xD) ||
                ((codePoint >= 0x20) && (codePoint <= 0xD7FF)) ||
                ((codePoint >= 0xE000) && (codePoint <= 0xFFFD)) ||
                ((codePoint >= 0x10000) && (codePoint <= 0x10FFFF)));
    }
           

這樣操作就能得到屏蔽表情的字元串。

5.總結

關于emoji我是第一次嘗試,這回主要做的任務是怎麼将emoji傳到背景并正常擷取顯示。表面上我是實作這個功能了,為什麼說是表面上呢,因為我傳的是Base64,如果真要這麼做的話,必須和所有端都統一,不然你傳Base64,其它端不解碼展示Base64那就很麻煩。

我想真正尋求的最優解是我這傳的是字元串,别的機子要是能正常顯示就顯示,不能正常顯示就隐藏,但是發現目前我還真不知道要怎麼弄,直接傳的String背景是無法接收的,好像是因為資料庫是3位而emoji大部分都是4位。

還有一點就是自己寫一個Emoji頁面來展示這個沒做,現在用的Emoji是輸入法提供的,但是有些APP會有自己弄的Emoji頁面,這個之後再說吧,總之這次最大的收獲就是基本認識了Emoji,有種一層迷霧散開的感覺,雖然并沒解決最根本的需求問題,但也不虧。

補充

1.開源架構

之後我又發現一個開源的emoji操作的架構

https://github.com/vdurmont/emoji-java

這個架構的API還是挺好了解的,就是那個判斷字元串中是否包含emoji的判斷沒用,但是可以用擷取emoji資料取長度來判斷

List<String> emojis =  EmojiParser.extractEmojis(str);
if (emojis.size() > 0) {
      ......
}
           
2.使用屏蔽的場景

上面我已經講了在資料庫不支援的情況怎麼上傳emoji,現在我打算補充下屏蔽emoji的使用場景。

(1)比如輸入名稱/标題等等這些場景如果輸入emoji的話,就好就是提示使用者無法輸入特殊符号(仿美團的做法)

(2)比如評論,回複這些長的内容輸入emoji而要屏蔽的話,可以在上傳時候删除掉其中的emoji,用我發的架構的做法就是

EmojiParser.removeAllEmojis(str)