ひだまりソケットは壊れない

ソフトウェア開発に関する話を書きます。 最近は主に Android アプリ、Windows アプリ (UWP アプリ)、Java 関係です。

まじめなことを書くつもりでやっています。 適当なことは 「一角獣は夜に啼く」 に書いています。

Unicode のサロゲートペアとは何か

こないだ同僚に Unicodeサロゲートペアについて説明する機会があって、それで Unicode の話をブログ記事に書きたくなったのでサロゲートペアについて書いておこうと思う。

この記事は Unicode Standard version 6.3.0 を見ながら書いた。

文字とコードポイント

抽象文字 (abstract character) を計算機上で扱うためには、符号化する必要がある。 Unicode では、文字の符号化のために使用できる整数の範囲を コード空間 (Codespace; 符号空間) と呼んでいる。 0 から 0x10FFFF がその範囲である。 そして、その空間に属する値を コードポイント (Code Point; 符号位置) と呼ぶ。

次の図は、抽象的な 「Å」 という文字と、対応する 符号化文字 (Encoded Character) を表現するコードポイントの関係を表すものである。 (Unicode Standard 6.2 より。) 下の図を見るとわかるように、1 つの抽象文字が複数の符号化文字に結び付けられることがある。 また、1 つの抽象文字が複数の符号化文字により構成されることもある。

f:id:nobuoka:20140604222944p:plain

Unicode コードポイントを参照する際は、「U+」 という接頭辞を付けて、16 進数表記の数字を続けて記述するのが Unicode Standard での表記法である。 また、符号化文字も単にコードポイントだけで参照することができる。

つまり、上の図における 00C5 という符号化文字を参照するために、「U+00C5」 という表記を使用できる。

なお、コードポイントは、必ずしも符号化文字に割り当てられているとは限らない。 (後で説明するが、サロゲートコードポイント (Surrogate Code Point) がその一例である。)

符号化文字と文字符号化形式

さて、上で述べたように Unicode 文字にはそれぞれコードポイントが与えられているわけであるが、そのコードポイントを計算機上でどのように表現するか、という意味でさらに符号化する必要がある。

Unicode Standard では、UTF-8UTF-16UTF-32 という 文字符号化形式 (Character Encoding Form) が提供されている。 それぞれ 8 ビット、16 ビット、32 ビットを 符号単位 (Code Unit) とする符号化方式である。

f:id:nobuoka:20140604234845p:plain

上の図は、いくつかのコードポイントが各文字符号化方式でどのように表現されるかを表した例である。 (Unicode Standard 6.2 より。)

任意のコードポイントは単一の 32 ビット符号単位で表現できるため、UTF-32 では常に 1 符号単位が 1 コードポイントを表す。 UTF-16 では、U+0000 から U+FFFF までのコードポイントは 1 符号単位で表現され、U+10000 以降のコードポイントは後述するサロゲートペアで表現される。 UTF-8 では、1 コードポイントを表現するために 1 個から 4 個の符号単位が使用される。

サロゲートペアについて

さて、いよいよ サロゲートペア (Surrogate Pair; 代用対) の説明を行う。 サロゲートペアとは、一言で言ってしまうと 16 ビット符号単位の組による単一の抽象文字の表現である。 UTF-16 でのみ用いられる。

UTF-16 は、16 ビットを符号単位とする文字符号化形式なので、任意のコードポイントを 1 符号単位で表現することができない。 16 ビットで表現可能な U+0000 から U+FFFF までのコードポイントについては、そのままコードポイントの数値を 16 ビットで表現するようになっている。 残りの U+10000 から U+10FFFF までのコードポイントは 16 ビットの符号単位の組で表現されるようになっていて、この組のことをサロゲートペアと呼ぶ。 例えば、先の図では U+10384 というコードポイントを表現するために、0xD800 と 0xDF84 の 2 つの符号単位の組が用いられていた。

上で 「U+0000 から U+FFFF までのコードポイントについては、コードポイントをそのまま 16 ビットで表現するようになっている」 と述べたが、それだとサロゲートペアのために使用できる符号単位がなくなってしまう。 そこで、Unicode では U+D800 から U+DFFF までのコードポイントをUnicode 文字に割り当てないようにし、0xD800 から 0xDFFF までの 16 ビット符号単位をサロゲートペアに使用できるようにしている。 これらのコードポイントはサロゲートコードポイントと呼ばれる。

つまり、より正確にいうと、UTF-16 では 「U+0000 から U+D7FF までと U+E000 から U+FFFF までのコードポイントについては 16 ビットの 1 符号単位であらわされ、U+10000 から U+10FFFF までのコードポイントは 2 つの符号単位の組で表現される」 ということになる。

文字符号化形式のためにコードポイントが使用されるのは奇妙な感じがするが、このような形になっているのは、もともと UTF-16 が固定長の文字符号化方式として設計されていたという歴史的な理由らしい。 (あんまり詳しくない。)

備考

U+0000 から U+FFFF までのコードポイント (文字符号化形式 UTF-16 において、単一の符号単位で表現できるコードポイント) は BMP コードポイント (BMP Code Point; BMP符号位置) と呼ばれる。 U+10000 から U+10FFFF までのコードポイントは 補助コードポイント (Supplementary Code Point; 補助符号位置) と呼ばれる。

ややこしいと思うこと

サロゲートペアはあくまで UTF-16 という文字符号化形式でのみ使用されるものであるが、UTF-16サロゲートペアが使用されるために U+D800 から U+DFFF のコードポイントがサロゲートコードポイントとして予約されていたりするあたりがややこしいと思う。 歴史的経緯...。

参考文献

ソフトウェア開発をするうえで最低限身につけておかなければならない文字エンコーディングに関する知識は次の書籍を読めば身につくと思う。 文字エンコーディング周りについて不安がある人は読むといい。

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

プログラマのための文字コード技術入門 (WEB+DB PRESS plus) (WEB+DB PRESS plusシリーズ)

Android アプリの Action bar に独自 View を設定する

ActionBar#setCustomView メソッド

Action bar に独自ビューを設定するには、ActionBar#setCustomView メソッドを使用する。

このメソッドを呼び出すだけでは独自ビューが表示されない。 独自ビューが表示されるようにするために、DISPLAY_SHOW_CUSTOM オプションを有効にする必要がある。 また、独自ビューを設定しただけでは、通常表示されるタイトル部分 (?) も合わせて表示されるので、タイトル部分を表示しないように設定する必要もある。 (詳しくは下に書いている例を参考のこと。)

API ドキュメントを見ると次のように書かれているので、この独自ビューは、独自のナビゲーションを実現するためのもののようである。

Set the action bar into custom navigation mode, supplying a view for custom navigation.

Custom navigation views appear between the application icon and any action buttons and may use any space available there. Common use cases for custom navigation views might include an auto-suggesting address bar for a browser or other navigation mechanisms that do not translate well to provided navigation modes.

下の例では DISPLAY_SHOW_CUSTOM オプションを有効にするために setDisplayOptions メソッドを使っているが、他のオプションの値もまとめて設定したい、という場合でなければ setDisplayShowCustomEnabled(boolean) メソッド を使った方が手軽で良さそう。


素の Activity クラスの API を使用

API level 11 以降であれば、以下のような感じで素の Activity のメソッドを呼び出して Action Bar に独自 View を設定できる。

// 必要な import 文
import android.app.ActionBar;

// android.app.Activity クラスを拡張した Activity の中で。

ActionBar actionBar = getActionBar();
// 通常表示されるタイトルを非表示にする。
actionBar.setDisplayShowTitleEnabled(false);
// 独自のビューを表示するように設定。
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
// 独自のビューを指定。 (ここではレイアウトリソースの ID を指定しているが、View オブジェクトを渡すこともできる。)
actionBar.setCustomView(R.layout.custom_actionbar);
Support Library の v7 AppCompat ライブラリを使用する場合

v7 AppCompat ライブラリを使用する場合は次のような感じになる。 getActionBar() メソッド呼び出しが getSupportActionBar() メソッド呼び出しに変わったのと、ActionBar のパッケージが異なる以外は、同じコードになる。

// 必要な import 文
import android.support.v7.app.ActionBar;

// android.support.v7.app.ActionBarActivity クラスを拡張した Activity の中で。

ActionBar actionBar = getSupportActionBar();
// 通常表示されるタイトルを非表示にする。
actionBar.setDisplayShowTitleEnabled(false);
// 独自のビューを表示するように設定。
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
// 独自のビューを指定。 (ここではレイアウトリソースの ID を指定しているが、View オブジェクトを渡すこともできる。)
actionBar.setCustomView(R.layout.custom_actionbar);
ActionBarSherlock を使用する場合

ActionBarSherlock を使用する場合は次のような感じになる。 ActionBar のパッケージが異なる以外は、v7 AppCompat ライブラリのコードと同じ。

// 必要な import 文
import com.actionbarsherlock.app.ActionBar;

// com.actionbarsherlock.app.SherlockActivity クラスを拡張した Activity の中で。

ActionBar actionBar = getSupportActionBar();
// 通常表示されるタイトルを非表示にする。
actionBar.setDisplayShowTitleEnabled(false);
// 独自のビューを表示するように設定。
actionBar.setDisplayOptions(ActionBar.DISPLAY_SHOW_CUSTOM, ActionBar.DISPLAY_SHOW_CUSTOM);
// 独自のビューを指定。 (ここではレイアウトリソースの ID を指定しているが、View オブジェクトを渡すこともできる。)
actionBar.setCustomView(R.layout.custom_actionbar);

読んだ: Effective Android

Effective Android

Effective Android

  • 作者: TechBooster,小太刀御禄,出村成和,重田大助,西岡靖代,宮川大輔,柏本和俊,あんざいゆき,八木俊広,木村尭海,小林慎治,有山圭二,中西良明,わかめまさひろ,新井祐一,桝井草介,久郷達也,寺園聖文,shige0501,山下智樹,前田章博,秋葉ちひろ,末広尚義,中澤慧,日高正博,塚田翔也,井形圭介,中川幸哉,山崎誠,山下武志,なまそで,橋爪香織,さとうかずのり,l_b__,ゼロハチネット,長汐祐哉
  • 出版社/メーカー: インプレスジャパン
  • 発売日: 2014/01/17
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (7件) を見る

読みました。 タイトルからは 『Effective C++』 や 『Effective Java』 が連想されますね。 副題として 「アプリケーション開発を効率化する 39 のテクニック集」 と表紙に書かれています。

内容紹介

Androidの機能・端末バリエーションは年々巨大化しています。おぼろげな理解でも試行錯誤によってある程度のことが実現出来ますが、安定動作するアプリ、使っていて気持ちの良いアプリに仕上げる上では、依然きちんと理解する必要のあることが多く存在します。

本書は、Androidアプリ開発へ携わる著者総勢20名によるデザイン/開発上のポイント集です。

日々の開発中にぶつかった問題を掘り下げたもの、Androidソースコードを読み解くことで得られたもの、多くの端末サイズ/解像度へと対応する中で得られたもの、Googleサービス群と連携する中で得られたものなど、日々のアプリ開発を一歩先へと進めるヒントに満ちていることでしょう。

Effective Android - 達人出版会

上記内容紹介にかかれているように、本書は複数人によって書かれた書籍です。 もともと同人誌として発行されていたものなので、わりと各自が好きなことを書いてるようで、基本的には章ごとの体系だった流れのようなものはありません。 ある程度分野ごとに章はまとまっていますし、関連する章が前後に並んでいたりはしますが、基本的にはそれぞれの章を独立に読む、という感じの読み方になるでしょう。

カード UI の実現の仕方や、カード UI にアニメーションを付ける方法、といったすぐに使える UI 上のチップスもあれば、Eclipse の設定ファイルの話や Gradle の話といった開発環境周りの話、SQLiteNFC といったミドルウェア (?) 的な話、便利ライブラリの紹介、それから NDK などのプラットフォーム周りの話といった感じで、内容は多岐にわたっています。

以前、Maven Central Repository への AAR パッケージのアップロード方法を書きましたが、それと同様の内容も本書に収録されてました。

さらには、Git についての話や Java 7、Java 8 の話も書かれています。 Git については、write-tree コマンドや rev-parse コマンドといったマニアックなコマンドが紹介されていて、普段 Git を使っている人でも 「ほえー」 ってなるかもしれません *1Java 7 の話については、API level 19 以降では Java 7 の構文をフルで使えるようになった *2 といったことが書かれていて、そういうことを知らない人にはいろいろ得るところがあると思いますし、Java 8 についてもいろいろ書かれていて勉強になります *3

感想

内容が多岐にわたっており、また、結構マニアックな話題も多いので、いろいろ視野が広がって良かったです。 たとえば、NFC タグの話や SQLiteDatabase の WAL の話、オーディオ周りの話などは 「へー」 という感じで読みました。 普段業務で Android アプリを開発していたり、個人で Android アプリを開発している人で、自分が普段関わらないようなところも含めてチップス集を読みたい、という気持ちがあれば本書はオススメです。 すぐさま業務に活かせるようなチップスもありますし (そうでないものもあります)、読み物としても興味深く読めるでしょう。

一方で、体系だった章立てになっていないという点や、全体的に誰しもにすぐ役立つ情報が多くないという点から、一通り Android アプリ開発できるようになった人に 「とりあえず読め!」 って感じで薦められる本ではないです。 あえてこういうことを書くのは、『Efefctive C++』 や 『Effective Java』 とタイトルが似てるからです *4

読み物的な感じで Android アプリに関して視野を広げたい、って人にお勧めです。

EFFECTIVE JAVA 第2版 (The Java Series)

EFFECTIVE JAVA 第2版 (The Java Series)

『Effective Java』 もお薦めです。

*1:私はなりました。

*2:あくまで構文であり、Java SE 7 のすべての Java API が使えるわけではありません。 まあこれは以前の Java 6 サポートの時からそうでしたが。

*3:Java 8 は今の Android アプリ開発では全く使えないので、Android アプリ開発には活かせませんが。

*4:これらの本は、一通り C++Java を書けるようになった人に 「とりあえず読め!」 って感じで薦められる本です。

Annotations Support Library が Android Studio 0.5.5 でサポートされた

Annotations Support Library の概要

ちゃんとしたドキュメントが見当たらないのですが、 *1 Android Support library のリビジョン 19.1.0 から、新たに Annotations Support Library が追加されました。 このライブラリは、その名のとおり Android アプリ開発時に用いることができるアノテーションの集まりです。 例えば、@NonNull@Nullable といったアノテーションが含まれています。

さらに、Android Studio ではバージョン 0.5.5 からこれらのアノテーションをサポートしており、アノテーションを使うことでいろいろと警告を出してくれるようになっています。

Support for the new annotations which shipped with the most recent version of the support library, such as @NonNull and @Nullable, as well as annotations to declare resource types and valid constants. Add a dependency on com.android.support:support-annotations:+ to use these in your projects. In the upcoming 0.10.x version of the Android Gradle plugin, the plugin will extract these annotations into your libraries' AAR files such that clients of your library can get the same resource type checks as is shown above for the SDK APIs.

Android Studio 0.5.5 Released - Android Tools Project Site

Android Support library については前に記事を書きましたので、合わせて参照ください。

Support Annotation についての公式的なドキュメントは次のページをご覧ください。

Annotations Support Library の使い方

ビルドシステムに Gradle を使っている場合についての説明です。

Android SDK Manager で 「Android Support Repository」 (リビジョン 5 以上) をインストールしたうえで、build.gradle に次のように記述することで Annotations Support Library を使用できます。

dependencies {
    compile 'com.android.support:support-annotations:22.2.0' // バージョン番号は必要に応じて変更してください。
}

使用できるアノテーション紹介

どういうアノテーションがあるのかを紹介します。 バージョン 19.1.0 時点での情報ですので、新しいバージョンでは使用できるアノテーションが増えているかもしれません。

@NonNull@Nullable

これらは、メソッドの返り値が null になりうるかどうかや、メソッドのパラメータとして null を許容するかどうか、といったことを表すのに用いられます。

    private void displayName(@NonNull String name) {
        // ...
    }

例えば、引数として null を許容しないメソッドを定義する場合、上のように @NonNull アノテーションを用いて null を許容しないことを表現できます。

そして、そのように定義されたメソッドの呼び出し時に null を引数として渡すようなコードを書くと、Android Studio 上で次のように警告が表示されます。

f:id:nobuoka:20140510013210p:plain

私は null になりうる変数には xxxOrNull みたいな名前を付けるといった命名規則などで null 周りのバグを減らすように気を付けたりしているのですが、アノテーションIDE によるサポートがあると便利で良さそうですね。

どの種類のリソースを参照するための int 値なのかを示すアノテーション

Android アプリで使用する各種リソースは int 値で参照されます。 どの種類のリソースでも同じ int 型で表されるので、Drawable のリソース ID を受け取るメソッドに、Drawable 以外のリソースの ID を渡すといったことや、そもそもリソースの ID でない単なる数値を渡すといったことも (コード上は) 可能です。

Annotations Support Library には、どの種類のリソースの ID なのかを示すためのアノテーションも含まれています。 例えば、Drawable リソースであることを示すアノテーション@DrawableRes アノテーション です。

    private void receiveDrawableRes(@DrawableRes int resId) {
        // ...
    }

例えば、引数として Drawable リソースの ID を受け取るメソッドを定義する場合、上のように @DrawableRes アノテーションを付けて、引数が Drawable リソースの ID であることを示せます。

このメソッドに Drawable 以外のリソースの ID を渡すと、次のように Android Studio がエラー表示してくれます。

f:id:nobuoka:20140510014441p:plain

@DrawableRes アノテーションの他にも、@AnimRes@ColorRes@StringRes といった、各種リソースに対応したアノテーションが存在します。

@IntDef@StringDef

定数として定義したいくつかの int 型 (あるいは String 型) の値のうちのいずれかを引数として受け取るメソッドを書きたい、ということがままあります。 そんなときに便利なのがこれらのアノテーションです。

普通にメソッドを定義すると、任意の int 値を受け取れるようになってしまいますが、これらのアノテーションを用いて独自のアノテーションを定義することで、メソッドが指定の定数のみを受け取ることを示すことができます。

@IntDef アノテーションを用いて、独自のアノテーション (@NavigationMode アノテーション) を定義する例は次のような感じです。

    @IntDef({NAVIGATION_MODE_STANDARD, NAVIGATION_MODE_LIST, NAVIGATION_MODE_TABS})
    public @interface NavigationMode {}
    public static final int NAVIGATION_MODE_STANDARD = 0;
    public static final int NAVIGATION_MODE_LIST = 1;
    public static final int NAVIGATION_MODE_TABS = 2;

そして、上で定義されたアノテーションを使い、NAVIGATION_MODE_STANDARDNAVIGATION_MODE_LISTNAVIGATION_MODE_TABS のいずれかの値を受け取るメソッドであることを次のように示せます。

    private void navigate(@NavigationMode int navMode) {
        // ...
    }

呼び出し時には定数を使って値を指定しないと、次のようにエラーが表示されます。

f:id:nobuoka:20140510021304p:plain

まとめ

Android Support library のリビジョン 19.1.0 で Annotations Support Library が追加され、Android Studio 0.5.5 でそれらのアノテーションがサポートされました。

著しく開発効率が上がったり、本質的な機能の向上があるわけではなく、あくまで開発の補助に使用できるものではありますが、地味に便利だと思います。 せっかく Android Studio でこのようなアノテーションがサポートされたのですから使っていきましょう!

Effective Android

Effective Android

  • 作者: TechBooster,小太刀御禄,出村成和,重田大助,西岡靖代,宮川大輔,柏本和俊,あんざいゆき,八木俊広,木村尭海,小林慎治,有山圭二,中西良明,わかめまさひろ,新井祐一,桝井草介,久郷達也,寺園聖文,shige0501,山下智樹,前田章博,秋葉ちひろ,末広尚義,中澤慧,日高正博,塚田翔也,井形圭介,中川幸哉,山崎誠,山下武志,なまそで,橋爪香織,さとうかずのり,l_b__,ゼロハチネット,長汐祐哉
  • 出版社/メーカー: インプレスジャパン
  • 発売日: 2014/01/17
  • メディア: 単行本(ソフトカバー)
  • この商品を含むブログ (8件) を見る

変更履歴

  • 2015-06-13 : 「support-annotations ライブラリ」 と記述していたのを 「Annotations Support Library」 に変更。

*1:最近公式的なドキュメントも書かれました。

読んだ: 高速スケーラブル検索エンジン ElasticSearch Server

高速スケーラブル検索エンジン ElasticSearch Server

高速スケーラブル検索エンジン ElasticSearch Server

2014 年 3 月末に発売された Elasticsearch の本を読み終えました。 私が知る限り、現在のところ唯一の日本語で書かれた Elasticsearch に関する書籍です。 書籍の題では 「ElasticSearch」 という表記が使われていますが、これはバージョン 0.90.x 系までの表記で、バージョン 1.0 からは 「Elasticsearch」 (s が小文字) という表記になっているようです。

本書は、ElasticSearch 0.90.11 を対象として書かれていますが、基本的にはバージョン 1.0 以降でも通用します。

対象読者、全体的な内容

本書の序文にも書かれているように、全文検索の初心者、あるいは Elasticsearch の初心者向けの書籍です。

Elasticsearch とは何か、どうやって使用するのか、という最初の一歩の部分からはじまり、データのインデキシングの方法や検索クエリの組み立て方といった検索機能全般について、クラスタ監視やシャードとレプリカの配置制御といったインフラ寄りの話、それからプラグインについての話など、Elasticsearch の基礎的なことが網羅的に記述されています。

コマンドラインから curl コマンドを実行することができて、JSON を知っている、というぐらいの知識さえあれば、本書を読み進めていくことができると思います。

感想

私自身は去年 (2013 年) から Elasticsearch を使っていました。 去年の段階では本書も発売されていませんでしたし、他に良い書籍もありませんでしたので、公式サイトのリファレンスを見て学んでいました。

しかしながら、主にクエリ DSL について調べていたという理由や、英語であるためざっと流し読みするということが難しかったという理由などもあり、公式リファレンスだけでは網羅的な Elasticsearch の知識を得ることができていませんでした。

そんなわけなので私はそこそこ公式リファレンスの知識を持った状態で本書を読み始めたのですが、初心者向けに書かれているだけあって本書の方が公式リファレンスよりもわかりやすく書かれているように思いました。 (日本語だからというのもあるとは思いますが。) 訳も読みやすくて、基本的にはよくわからなくて困るということもないでしょう。

(ただ、下の部分だけはいまだによくわかっていません。 そのうちちゃんと調べます...。)

本書を最初から最後まで読むことで、Elasticsearch の基礎について網羅的に学べました。 これから Elasticsearch を使うから基礎的なことを網羅的に学びたい、という人は本書を読むといいと思います!