tetsu31415.log

androidなどのことを書き綴っていこうと思います。

TwemojiをAndroidで使えるようにしてみた

はじめに

先日、Twitter社が872種類の絵文字をオープンソース化し「Twemoji」としてGitHubに公開しました。

GItHubリポジトリにはWebページにTwemojiを表示させるスクリプトとTwemojiの絵文字データ(.png, .svg, .ai)が含まれています。
前者にはMITライセンスが、後者にはCC BY 4.0が適用されています。

今回はこの絵文字データを使ってAndroidで使用できる絵文字フォントを生成してみます。

カラー絵文字について

現在カラー絵文字の規格はバラバラで次のようなものがあげられます。

iOSOS Xで使われている。
sbixというテーブルを定義してPNG画像を埋め込んでいる。

Android4.4からNotoColorEmoji.ttfで使われている。
CBDT/CBLCというテーブルを定義してPNG画像を埋め込んでいる。
Appleのものとは違い、フォントのビルド方法が公開されている。

Windows8.1から使われている。
色を設定したアウトラインを重ねて描画する方式である。


今回作成するAndroidの絵文字はビルド方法がこちらに公開されており、国内携帯キャリアから4.4以降のAndroid端末ではこの方法でビルドされたカラーフォントがシステムにプリインストールされています。
例えば… auEmoji.ttf、DcmColorUniEmoji.ttf、SbmColorUniEmoji.ttf など。

環境

OS

必要なもの

OS Xに入っているpythonを使用しました。

  • FontTools

ttf(バイナリファイル)とttx(XMLファイル)を相互変換するツールです。
こちらのサイトを参考にAFDKOでインストールしました。

  • librsvg

svgを描画・変換するライブラリです。
今回、rsvg-convertコマンドを使ってsvgファイルをpngファイルに変換するために使います。
Macのパッケージ管理システム「brew」を使ってインストールします。
入っていない場合はこちらを参考にしてインストールします。

$ brew update && brew upgrade
$ brew install librsvg
$ ln -s /usr/local/bin/rsvg-convert /usr/local/bin/rsvg

参考: Converting SVG to PNG online and in your terminal | The blog of Max Glenister

その他にも必要な物があったかもしれません…

絵文字フォントの作成

Android4.4から搭載されているカラーフォント「NotoColorEmoji」のソースコード
Noto に公開されています。
Notoというのは「No Tofu(豆腐文字、すなわち□と表示される文字を取り除く)」という意味があります。
Notoはすべての言語をサポートすることを目指してGoogleオープンソースで開発しているフォントパッケージです。
そのパッケージにNotoColorEmojiが含まれています。

NotoColorEmojiのビルドはcolor_emoji フォルダに移動してmakeすると始まります。
※ これには、平面の国旗からウェーブさせた国旗画像を出力するプログラムなども含まれているのでビルドするには他にもライブラリを追加する必要がある可能性があります。(ライブラリを揃えてもなぜか自分の環境ではビルドがうまく行かなかったのでPythonコードを一部改変してなんとかビルドできました)

今回はそのような処理は必要ないので先ほどあげたライブラリでビルドができると思います。
https://code.google.com/p/color-emoji/ に3つのカラー絵文字のサンプルがあります。
FruityGirlとFunksterはPNGファイルがあるのでそれをビルドしています。
PhantomOpenEmojiはsvgで提供されているものを128x128のpngに変換してからビルドしています。
今回のTwemojiのビルドはPhantomOpenEmojiと同じようにsvgpngに変換してビルドをします。
※ Twemojiはpngでも提供されていますが16x16,36x36,72x72となっており現在必要な128x128のpngにはできないのでsvgから128x128のpngに変換します。


今回Twemojiのビルドに使用するツール一式をGitHubに上げました。
GitHub - tetsu31415/Twemoji4Android
ダウンロードした後、このディレクトリーで

$ make

するとsvgpngに変換し、Twemoji.ttfが作成されるようになっています。
また、ビルドされたttfフォントはttf/Twemoji4Android.ttfに入っているのでダウンロードしたい方はこちらからどうぞ。

注意点

  • 囲い文字や国旗表示に対応していますが数字や#が表示されません。

囲い文字とは
文字と囲いを並べることでそれを結合して一文字として扱う文字です。
同様に国旗表示も2つの国旗用アルファベットを組み合わせて1つの文字を作っています。
Android4.4と5.0のカラー絵文字を比較してみます。

f:id:tetsu31415:20141118011709p:plain

4.4では 日本の国旗が「JP」、1の囲い文字が「1□」のように表示されていますが、5.0では結合されて1つの文字になっているのがわかります。
※ちなみにAndroid4.1からのモノクロの絵文字フォントは囲い文字に対応しています。

f:id:tetsu31415:20141122010240p:plain

たとえば、1の囲い文字を使用するためには「1(U+0032)」と「囲い(U+20E3)」と「1の囲い文字(U+0032とU+20E3)」の3つの文字を定義する必要があります。
しかし、Twemojiの絵文字データには「1(U+0031)」や「囲い(U+20E3)」は存在しません。
今回は囲い文字を定義するために「1(U+0031)」や「囲い(U+20E3)」を空のグリフとして無理やり追加したので囲い文字に使っている数字(1から9および#)が表示されなくなります。予めご了承ください。

  • 4.4での表示が微妙

カラー絵文字の囲い文字・国旗表示の対応はAndroid5.0のNotoColorEmojiからですが、4.4でもこの5.0のカラー絵文字を読み込むことで囲い文字・国旗表示の対応が一応出来ました。

しかし、囲い文字・国旗が正常に表示できたのはTextView#setTypeface()で指定したときで、Android4.4の端末(LGL22)をroot化してsystemにフォントをインストールした場合は囲い文字・国旗が結合されませんでした。原因はわかっていません(詳しく調べていない)

おわりに

すこし問題点はありますが、無事TwemojiをAndroid向けのカラーフォントにビルドすることが出来ました。

なにかありましたら @tetsu31415 までお願いします。

auLTEのCellIDを収集してバンドとの関係性を調べてみた

はじめに

金沢駅から大阪駅までローカル線の旅をしてきたのでauLTEのCell IDを集めてきました。

Cell IDは基地局のセクターやバンド(周波数帯)ごとにユニークに割り当てられているようなので接続中のCell IDとバンドを紐付けすればバンドを確認できない端末でもCell IDを取得して間接的に接続しているバンドがわかるのではないかと思ったので収集してみました。

※GALAXY、一部のLG機種、iPhoneなどはメーカーが独自に実装したメニューを開くことで接続中のバンドを確認することができます。

収集方法

Cell ID取得方法

Android4.2から追加されたCellIdentityLte#getCi()で取得します。
AndroidManifestに以下の2つのパーミッションを追加して、
Activityを継承したクラス内にこんな感じで書くと取得出来ます。(適当ですいません)

<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
private TelephonyManager telephonyManager;

@Override
    protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    telephonyManager = (TelephonyManager)getSystemService(TELEPHONY_SERVICE);
}

@Override
protected void onResume() {
    super.onResume();
    telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_CELL_INFO);
}

@Override
protected void onPause() {
    super.onPause();
    telephonyManager.listen(phoneStateListener, PhoneStateListener.LISTEN_NONE);
}

PhoneStateListener phoneStateListener = new PhoneStateListener(){

    public void onCellInfoChanged(java.util.List<android.telephony.CellInfo> cellInfoList) {
        for (CellInfo cellInfo : cellInfoList) {
            if (cellInfo instanceof CellInfoLte) {
                CellInfoLte cellInfoLte = (CellInfoLte)cellInfo;
                CellIdentityLte cellIdentityLte= cellInfoLte.getCellIdentity();
                int ci = cellIdentityLte.getCi();
                Log.d("TestApp", "Cell ID is "+ci);
            }
        }
    };
};

また、CellIdentityLte#getCi()はリファレンスで次のように書いてあります。

public int getCi ()

Added in API level 17
Returns
28-bit Cell Identity, Integer.MAX_VALUE if unknown

というわけで28bitのCell IDが取得できるようです。

バンド取得方法

SCL22でダイアルから*#0011#を使ってサービスモードを起動してバンドを確認します。
SCL22はBand 1(2.1GHz), Band 11(1.5GHz), Band 18(800MHz)の3バンドに対応しています。
Band 41(2.5GHz)は対応端末を持っていなかったので収集できませんでした。

収集結果

250件ほどのCell IDとBandの組み合わせを収集できました。
Cell IDを昇順でソートしたものを一部を抜粋するとこのような感じです。
※ 左からCell IDの10進数、Cell IDの16進数、バンドとなっています。
f:id:tetsu31415:20141005181425p:plain

このようにバンドごとにCell IDが固まっているように見えます。

また、移動通信方法及び無線基地局
【0011】にはこう書かれています。

なお、E-CGIの下位28ビットは、Cell ID(図10に示す情報要素「Cell Identity」に設定されるCell Identityに対応)によって構成されており、ハンドオーバ先候補無線基地局が、無線基地局HeNBである場合、Cell IDは、Home eNB IDによって構成されており、ハンドオーバ先候補無線基地局が、無線基地局eNBである場合、Cell IDは、20ビット長のMacro eNB IDと8ビットの無線基地局HeNB配下のセルの識別情報とによって構成されている。

この取得した28bitは20bitと8bitに分けられるみたいです。
実際に収集したCell IDの下位8bitはすべて0x00から0x03の範囲に収まっていました。
この下位8bitはセクターごとに変わると考えて良さそうです。

北陸エリア編

金沢市街、金沢駅から敦賀駅にかけての区間のCell IDは0x3000000台になっていて
Cell IDを昇順でソートするとBand18,Band1,Band11の順に並びます。
北陸エリアで収集したCell IDのバンドごとの最小値、最大値は次のようになりました。
f:id:tetsu31415:20141005211623p:plain

この結果から0x3000000台がBand18, 0x3300000台がBand1,0x3400000台,0x3500000台がBand11というように上位8bitで判別できるかなという仮説を立てましたが関西エリアに入って調べるとそんなこともありませんでした…

関西エリア編

敦賀駅で乗換えし、滋賀県に入ってからはCell IDが0x5000000台になりました。
こちらも北陸エリアと同じようにCell IDを昇順でソートするとBand18,Band1,Band11の順に並んでいます。
関西エリアで収集したCell IDのバンドごとの最小値、最大値は次のようになりました。
f:id:tetsu31415:20141005212907p:plain

まとめ

今回収集したauLTEのCell IDについてまとめてみると…

  • Cell IDを収集して昇順でソートするとBand 18,Band 1,Band 11の順にバンドごとに固まって割り振られている。
  • Cell IDの各バンドの正確な区切りはどこかわからない。
  • エリアが変わるとCell IDが大きく変わる。

という感じになります。

今回集めたCell IDの各バンドごとの最小値と最大値の範囲内はそのバンドと判別しても良さそうな感じがします。

これを解明していくためには地道に広い範囲のCell IDを収集していくしかない気がします。

おまけ

今回の収集結果をもとにバンドを確認するサンプルを作るとこんな感じになりました。