Android
Android Dev Phone 1ファームウェアアップデート
こんにちは。久富といいます。
株式会社ゆめみには「大人の自由研究」という制度がありまして、勤務時間の10%を自分の好きな研究に使っても良い制度があります。私はその制度でAndroidを触ってみようと思い、色々と試行錯誤しているところです。
今回の私の記事は、Android Dev Phone 1のファームウェアアップデートの実際をお伝えしようと思います。
ご存知かと思いますが、Androidというプラットフォーム自体の現時点(2009/03/25)での最新バージョンは1.1です。ところが2009年1月頃に輸入した手元のAndroid Dev Phone 1のバージョンは1.0になっています。今回はこれを無事に1.1にアップデートさせることに挑戦してみます。
なぜファームウェアをアップデートしなければならないか、ですが、GoogleやHTCのサイトにも書かれているとおり、テストのためというのが一番大きな理由です。Android 1.1のAPIを使って開発したアプリケーションはAndroid 1.1が載った端末でテストしなければなりません。さらに、Android 1.0向けに開発した場合、Android 1.0でも1.1でも動くかどうかを確認する必要があります。それらのファームウェアの数だけ端末を用意するのは現実的でないので、ひとつの端末のファームウェアを書き換えてテストすれば良い、というわけです。今までの日本の端末のアプリ開発ではこのような柔軟なファームの書き換えはサポートされていなかったように思います。こんなところにもAndroidがオープンな一面が現れていると思います。
その他、端末にいろんなことを試していてにっちもさっちもいかなくなったときなど、こうやってファームを書き直せば必ず直ります。これはアプリを開発する立場の者にとってとっても助かります。環境依存のトラブルなどを切り分けることができるからです。
具体的な方法はHTCのサイトに載っていますのでそれに従って行います。なお、以降の作業はAndroid SDKがインストールされていることを前提に進めます。まだAndroid SDKをインストールしていない方は、Googleのページを参考に入れてみてください。リクエストが多ければインストールの方法も記事にします。ご感想を是非コメント欄にご記入ください。
HTCのサイトよりバイナリを落とす
まずはHTCのサイトよりバイナリを落としましょう。サイトにてリンクが設定されている以下の3ファイルを落としてください。
- fastboot
- signed-dream_devphone-img-130444.zip
- ota-radio-1_22_14_11.zip
fastbootはお使いのマシンのOSにあったものを落としてください。Androidのソースを自前でコンパイルしている人は、すでに<ビルドしたディレクトリ>/out/host/<プラットフォーム>/bin/に入っていると思います。
無線のファームウェアを更新する
HTCのサイトには繰り返し、「Androidのシステム・イメージのバージョンは無線のファームウェアと相互に依存しているので、システム・イメージをバージョンアップしたければ、必ず無線のファームウェアも同じバージョンにすること」と書いてあります。指示通り、無線のファームを入れましょう。
- Android Dev PhoneにSDカードが入っていることを確認します。普通は買った当初から1GBのmicroSDカードが最初から入っていると思いますが、念のため確認しましょう。

- 端末をUSBでつなぎます。
- adbで端末を確認します。コマンドラインからadb devicesと打ちます。

- adbでイメージを転送します。コマンドラインからadb push イメージファイル名 /sdcard/update.zipと打ちます。転送には数分かかるようで、しばらく待ちましょう。

- 端末をリカバリーモードで再起動します。ホームボタン(電話かけるボタンの右、白い家のアイコン)を押しながら端末を再起動します。
- !マークが出たら、altキーと小文字のl(エル)を同時に押します。
- 次にaltキーと小文字のsを同時に押します。
- 次にホームボタン(電話かけるボタンの右、白い家のアイコン)とバックボタン(電話切るボタンの左、左上に戻る矢印のボタン)を同時に押します。
- 端末が再起動して、イメージが書き込まれます。
文書で書くとどの段階でどれぐらいの時間がかかるのか分かりづらいので、動画にしました。
システム・イメージを転送する
次に、システムイメージを転送してインストールしましょう。
- 端末をfastbootモードで起動します。バックボタン(電話切るボタンの左、左上に戻る矢印のボタン)を押しながら起動します。
- コマンドラインで$ fastboot update システムイメージのファイル名.zip -wと叩きます。
なお、Windows側でAndroidを過去にUSBマス・ストレージ・クラスのデバイスとして扱った場合、fastbootが端末を見つけられません。この場合、デバイスマネージャーでUSBハブの下にあるUSBマス・ストレージ・クラスの端末を削除して、新たにデバイスドライバをSDK同梱のものに更新してください。
端末はきれいさっぱり初期化されていますので、またSIMカードを入れてセットアップが必要です。ネットワークにmoperaをお使いの場合は、Setting > Wireless Controls > Mobile Network > Access Point Names にてメニューよりNew APNを選び、あとは最初に設定したときと同じようにAPNにmopera.netと入力し、ID・パスワードを入力すればokです。
それではまたお会いしましょう!
Android アプリケーションが使用する API バージョンの指定
こんにちは。久富です。
連休中にアプリをなんか作りたいなぁ、と思っていたのですがついに一行も書くことなく連休が終わってしまいました。あぁ、身体がもう一つほしい! そんな事を思いながら会社のメールをチェックすると、連休中にAndroid Marketからメールが届いていまして、そこに興味深いことが書いてありました。簡単にまとめますと以下のようになります。
Androidで稼働している端末それぞれは、Androidプラットフォームのいろいろなバージョンで動いています。それらをサポートするにはマニフェストファイルにて最低限必要なAPIのバージョンを示すことが必要です。今すでにAndroidMarketに上げているアプリにはこの作業は必要ないですが、今後新規に公開するアプリやバージョンアップするアプリにはこの作業を行う必要があります。たとえばAndroid1.5APIを使ったアプリであればminSdkVersionを3と示す必要があります。こうすることでAndroidMarketは古いバージョンで稼働している端末にはそのアプリを表示しなくなります。
なるほど、1.5のAPIを使ってアプリを書いても1.1の端末では動かないですものね。この後メールでは各国での最新バージョンの普及具合を随時連絡するとありました。まぁでも、今のところ1.1で作ったほうがいいよ、的なことも書いてありました。この辺りは作る側で判断していくしかなさそうですね。
さて、1.5で動くというのを示すのにminSdkVersion=3であれば、1.1はどうなのでしょうか?またその書き方は?これはメールの文中にあったURL(http://developer.android.com/guide/publishing/versioning.html#minsdkversion)の飛び先の一番最後に書いてありました。これまたざっくりとまとめてみます。
アプリが稼働するために最低限必要なバージョンを示すには、<manifest>の子供に<uses-sdk>エレメントを追加し、android:minSdkVesionを属性として定義します。より詳しくは1.1のバージョン・ノートを参照のこと。
なるほど、1.1のバージョンノートを見たほうがよさそうですね。ここにはズバリそのものが書いてあります。
<manifest> ... <uses-sdk android:minSdkVersion="2" /> ... </manifest>
というわけで、1.1で動くなら上記の一行をマニフェストに追加して、1.5で動くならバージョンを3として追加すればよいわけですね。
次回、実際にAndroidMarketにアプリを公開するときに、ちゃんと指定通りの端末で提供されて古いバージョンの端末では非表示になるかを、前回ご紹介した端末のAPIバージョンの入れ替えも併用して確かめてみようと思います(なんかアプリ書かなきゃ)。
それではまた!
Android端末Xperia タッチ&トライ(起動時間の動画有り)
大変ご無沙汰しております。久富です。2010年春にdocomoから出るAndroid端末であるXperiaの製品発表会があったので、参加してきました。残念ながら途中からの参加でしたので、いきなり実機レポートから入りたいと思います。ケータイで撮影しているため、影が出ている写真で申し訳ありません。

まずは外観参照。Android Dev PhoneとXperia、そしてiPhoneと並べてみました。画面の大きさに注目してください。Xperiaの画面は大きくてきれいですが、この写真で見るほど「でか!」という印象は実機ではありません。使いやすくよくまとまっており、手持ちした感じもしっくりなじみます。ソニーが近未来の電話を作ったらこうなる、そんな質感のパッケージングでした。

つぎにウィジェットを追加してみようと思ったのですが、このあたりで期待していたものと違うことに気付きます。「Android標準インターフェースとあんまり変わってない……。」私の思い込みかもしれませんが、XperiaはかなりUIにこだわった端末である、との触れ込みだったような記憶があります。実際は、確かに変わっているUIもありますが、もとのままのUIもあります。この写真を見ていただいてもわかるとおり、ウィジェットの時計のデザインは変わってますが、Android Marketのアイコンは両者とも同じです。この二台とも、Android 1.6が入っています。

次に電話をかけています。ここでXperia独特の部分に気付きます。「電話をかける」ボタンと「電話を切る」ボタンが、ハードウェアボタンでなくソフトウェアボタンになっています。Android Dev Phoneはハードウェアボタンの「電話を切る」ボタンで画面ロックがかかり液晶の電源が切れるようになっているので、それに慣れているとちょっと戸惑いますね。

これはアプリ一覧を表示したところです。Xperiaはアイコンが縦5列並びます。でも、他のアイコンは今までと似たり寄ったりなので戸惑うことなく操作できます。アプリ一覧を出す操作も、Notificationを呼び出す操作も、Android Dev Phoneと全く同じです。
次に、起動時間を測定してみました。圧倒的に速いです。でも、使用感はそれほど変わりません。重いアプリとか動かしたら違うのかもしれませんね。
Xperiaには他にもMediascape、Timescapeというアプリが搭載されておりますが、今回はAndroid端末としてどうだろう?という観点からいろいろと触ってみました。そして思ったことは「普通のAndroid端末じゃん」ってことです。ハードウェア・ソフトウェア両方のボタンデザインなど確かに洗練されていますが、基本的な使い方は他の端末と変わることがないですね。アプリ開発者の視点からすると、画面のピクセル数が多いことは考慮したほうがいい感じです。特にゲームなど作られる場合は、Xperiaと他の端末とで動作確認したほうが確実かと思いました。それではまた!
Android で LINQ を実現!
はじめに
こんにちは。お久しぶりですね。hiroです。
昨今の、オブジェクト指向の考え方の普及に伴い、プログラマの誰もがオブジェクト指向言語を用いてソフトウェアを開発するようになりました。しかし同時にリレーショナルデータベースや、といった、オブジェクト指向では表されていないデータ構造へのアクセスが容易ではない事が課題として挙がっています。
この「Collection Context」ライブラリでは、これらの非オブジェクト指向なデータ構造を持つデータソースを、オブジェクト指向言語であるJava言語でいかに容易に扱うかをテーマに、コレクション操作が容易になるようなを提供しています。
1.JavaにLINQのエッセンスを
Microsoft社の.NET Frameworkでは、C# 3.0およびVisual Basic 9.0よりサポートされたLINQ式およびLINQ関連ライブラリのAPIセットによってコレクション操作を容易にしています。特にC#、VB言語においては、言語に統合されたクエリ式が記述できるように言語機能が拡張されています。これにより、メモリ上のオブジェクト、データベース上のオブジェクト、XMLなどがほぼ同一のクエリ記法によって操作が可能です。このように、.NET FrameworkはAPIが徐々にモダンに置き換わります。
一方、Javaにはこのような言語拡張はありません。コレクション関連のAPIも、Java Collection Frameworkがジェネリクスに対応したJ2SE 5.0以降、これといった拡張もありません。また、データベースアクセスはJDBCとして不動、XML操作はStAXがJava 6で加わりましたが、これらを横断して「データの集合」という概念で扱えるフレームワークやライブラリはありません。
最近、Javaには新しいプラットフォームが増えました。Androidです。Androidで採用されているJavaは、正確にはSun Microsystems社のJavaではありませんが、Java SEの主要なAPIをサポートし、さらにAndroidに特化したAPIを提供しています。このプラットフォーム上においても、コレクション操作に関するライブラリはかつてのJavaのままです。
ということで、「JavaにLINQのエッセンスを」をテーマに、モダンなコレクション操作機能を提供するためのライブラリ、それが「Collection Context」です。
2..NET FrameworkのLINQとの違い
.NET FrameworkのLINQの実装は、LINQプロバイダと呼ばれるプロバイダによって機能が提供されるようになっています。メモリ上のオブジェクト用LINQプロバイダ、データベース向けLINQプロバイダ、XML向けLINQプロバイダといった調子です。Collection Contextもこの概念に則っています。
違いは、Javaにクエリ式を記述できる言語拡張が無いという点と、ラムダ式が無いという点です。LINQは専用の文法を使用しても、メソッドをコールしても利用できます。Collection Contextは、Java向けの専用の文法が無いため、メソッドをコールして使用します。
3.Collection Contextのライブラリセットとプラットフォーム
Collection Contextは単一のライブラリではありません。現在、以下の2種類にて分かれています。
(1)Collection Contextのフレームワーク部分
Collection Contextの名を表す根幹です。コレクション操作の文脈(処理の流れ)をAPIで提供します。
また、XML文字列を簡単に操作するための、DOMに類似した(ただし、別のアプローチからの)モダンなXML関連APIを提供します。このAPIは各プラットフォームで用意されている標準のパーサを使用するように作られており、パーサ自体は含んでいません。
(2)プラットフォームのAPIによるリソースマネジメントの実装
実際に、プラットフォームで扱えるリソースをマネジメントするためのAPIが準備されています。2010年10月現在、Androidプラットフォーム向けの実装が準備されており、このプラットフォーム上では以下のリソースがCollection Context上で扱えるようになります。
- SQLiteデータベース
- JSONオブジェクト
- XML(org.xmlpull.v1パッケージに含まれるプル型パーサと、SAXパーサの両方)
- メモリ上のオブジェクト
※ダウンロードしてご利用いただけるjarファイルは、このAndroid 1.6以降でご利用頂けるもので、上記(1), (2)のすべてをワンパッケージにしています。
4.CollectionContext<T>クラスの基礎
まずはじめに、Collection Contextを用いたXML処理の例を以下に示します。これは、AndroidプラットフォームにおいてXMLデータをJavaのオブジェクトに変換しています。
String uri = "http://www.example.com/example-resource"; Iterable<Person> persons = XElement .from(uri, new XmlSaxParserWrapper(), "UTF-8") .descendants("person") .where(new F1<XElement, Boolean>() { public Boolean f(XElement node) { return node.attribute("person-id").intValue() > 10; }}) .select(new F1<XElement, Person>() { public Person f(XElement node) { Person person = new Person(); person.setID(node.attribute("id").longValue()); person.setName(node.element("name").stringValue()); person.setAddress(node.element("address").stringValue()); person.setBirthday(node.element("birthday").dateTimeValue("yyyy-MM-dd")); return person; }});
XElementクラスのstaticメソッドfrom()に、XMLのURIと、XMLパーサのインスタンス、XMLの文字コードを指定し、XMLをパースする方法を指定するところから記述が始まっています。次のdesendants()メソッドは、ルートタグの次の階層の「person」という名称のタグ情報をコレクション化するメソッドです。 そのコレクションにwhere()メソッドにてフィルタ条件を指定しています。少し見にくいかもしれませんが、関数を表すオブジェクトが匿名クラスとして実装されています。さらに、select()メソッドにて射影操作を指定しています。XElementのオブジェクトであるnodeをPersonクラスのオブジェクトに変換しています。select()メソッドが返すインスタンスはjava.lang.Iterable型を実装しています。従ってpersonsオブジェクトは拡張for文で逐次参照が可能です。
このように、Collection Contextフレームワークを用いると、ネットワーク処理とXMLパース処理における各種リソースのマネジメントが自動化されます。これによって、プログラマはデータの変換処理を容易に記述でき、この処理の前後のビジネスロジックの記述に専念できます。
上記where()メソッドやselect()メソッドはCollectionContext<T>クラスのメソッドです。CollectionContext<T>クラスは、Collection Contextフレームワークの中核をなすクラスで、配列やIterable<S>を実装するオブジェクトに対するフィルタ処理や射影処理等をメソッドチェーン方式で記述できる機能を提供します。
CollectionContext<T>クラスにもstaticなfrom()メソッドが用意されており、配列やIterable<T>を実装するオブジェクトをCollectionContext<T>オブジェクトに変換することができます。
CollectionContext<T>クラスで指定できる機能とメソッドは以下の通りです。
- from():既存の配列やIterable<T>で表されるコレクションをCollectionContext<T>オブジェクトに変換する。
- where():フィルタを指定する。指定されたオブジェクトは遅延実行される。
- select():射影を指定する。このメソッドで返されるCollectionContextは、射影後のコレクションを表す。遅延実行される。
- comparator()、orderByAsc()、orderByDesc():ソート条件を指定する。遅延実行される。
- foreach():コレクションに上記フィルタ条件、ソート条件を適用しながら1件毎に、指定された処理ルーチンをコールする。メソッドが呼ばれた時点で即時実行される。
- first():コレクションにフィルタ条件、ソート条件を適用し、最初の1件を取得する。オーバーライドされたメソッドに、射影を行うことができるタイプもある。即時実行される。
- appendTo():既存のList<T>オブジェクトで表されるコレクションの末尾に、このCollectionContext<T>オブジェクトで表されるコレクションをコピーする。フィルタおよびソート条件が適用される。即時実行される。
- toList():内包するコレクションにフィルタおよびソート条件が適用され、List<T>オブジェクトを生成する。即時実行される。
つまり、CollectionContext<T>クラスのみを用いてコレクション操作を行う場合、from()メソッドの取りうるタイプの都合上、メモリ上のコレクションか、独自にIterable<S>を実装したクラスのオブジェクトを指定する必要があります。逆に、このインターフェイスに則ったクラスを作成することで、Collection Contextフレームワークがサポートしていないリソース経由でデータを取得し、コレクション操作を行うことも可能です。
また、CollectionContext<T>クラスは、Iterable<T>インターフェイスを実装しています。従って、このクラスのオブジェクトは直接、拡張for文で使用できます。
5.CollectionContext<T>オブジェクトを生成できる各クラス
CollectionContext<T>オブジェクトを生成できるのは、自身のfrom()メソッドだけではありません。上記(1)の末尾でも述べられているように、Iterable<S>を実装したクラスのオブジェクトを生成できるクラスも以下のように提供されています。ただし、2010年10月現在、これらが稼働するのはAndroidプラットフォームの、バージョン1.6以上のみです。
(1)XML中のデータをコレクション化するXElementクラス
サンプルコードは既出のとおりです。
(2)SQLiteデータベースの参照処理を生成するSQLiteContextBuilderクラス
Androidプラットフォームには、組込データベースとして、SQLiteが採用されており、プラットフォームの標準APIとしても実装されています。ただし、このAPIはJDBCではありません。独自に実装されたAPIとなっています。
Collection Contextフレームワークでは、SQLite関連クラスとして、DatabaseCursorIterableクラスと、SQLiteContextBuilderクラスが標準で提供されています。DatabaseCursorIterableはIterableを実装しているため、CollectionContext<T>クラスのfrom()メソッドで使用できます。しかし、通常はSQLiteContextBuilderを使用し、メソッドチェーンの記法を用いて「簡単に」データベースの参照コードを記述します。これにより、コードがより宣言型に近づき、バグも潜みにくくなります。
CollectionContext<Shop> shops = SQLiteContextBuilder
.newBuilder(new SQLiteOpenHelperImpl())
.query( "SELECT " +
" ID, " +
" SHOP_ID, " +
" NAME, " +
" LATITUDE, " +
" LONGITUDE, " +
" URL " +
"FROM " +
" SHOP " +
"WHERE " +
" ? <= REGISTERED AND " +
" REGISTERED < ? "
registeredBegin, registeredEnd)
.contextToRead()
.select(new F1<Cursor, Shop>() { public Shop f(Cursor cursor) {
Shop result = new Shop();
result.id = cursor.getInt(0);
result.shopID = cursor.getInt(1);
result.name = cursor.getString(2);
result.latitude = cursor.getDouble(3);
result.longitude = cursor.getDouble(4);
result.url = cursor.getString(5);
return result;
}});
このコードでは、query()メソッドでSQL文とパラメータを指定しています。contextToRead()メソッドをコールすると、それ以降はCollectionContextクラスのメソッドとなります。select()メソッドを使い、CursorオブジェクトからShopオブジェクトへ射影しています。最終的に得られる値はCollectionContextオブジェクトです。
(3)JSON文字列を処理するorg.json.JSONObjectクラスをコレクションとみなすJSONObjectIterableクラス
最近は、Web上のAPIのデータ送受信の表現として、JSONを用いることも多くなってきました。Facebookは特に、全般的にJSONでデータをやり取りし、ソーシャルグラフを操作します。AndroidプラットフォームにもJSONを操作するAPIが用意されています。これをCollectionContext<T>オブジェクトに変換している例が以下の例です。
String result = facebook.request(url, parameters, method);
CollectionContext<FacebookFriend> friends = JSONObjectIterable
.from(result, "data")
.select(new F1<JSONObject, FacebookFriend>() {
public FacebookFriend f(JSONObject friend) {
FacebookFriend result = new FacebookFriend();
result.facebookID = friend.optString("id");
result.name = friend.optString("name");
return result;
}});
「友達」を表すJSONObject “friend”を、FacebookFriendクラスのオブジェクトに変換しています。JSONObjectIterableクラスのfrom()メソッドは、JSON文字列をJSONObjectに変換する処理を行い、CollectionContextを生成します。そして、select()メソッドで射影を行い、得られるのはCollectionContextオブジェクトです。
(4)内部イテレータの表現を外部イテレータへ変換するOuterIterable<T>クラス
OuterIterable<T>クラスは特殊用途を想定しています。通常、CollectionContext<T>オブジェクトを生成するためには、from()メソッドにIterable<T>オブジェクトを渡すのですが、場合によってはIterable<T>を実装したクラスを作成しなければならない場合があります。この実装が外部イテレータの表現を強いられるため、扱うリソースによっては実装が容易でないケースもあります。
例えば、ストリームから文字列を行単位で入力し、その文字列を1行単位で参照できるIterableを実装すると、以下のようになります。
public class OuterIterableImpl implements Iterable<String>, Iterator<String> { private boolean initialized = false; private String filePath = null; private BufferedReader reader = null; private String next = null; public OuterIterableImpl1(String filePath) { this.filePath = filePath; } @Override public Iterator<String> iterator() { return this; } private void initialize() throws IOException { this.reader = new BufferedReader(new InputStreamReader( new FileInputStream(this.filePath))); } private void dispose() { try { this.reader.close(); } catch (IOException ex) { // something to do } } @Override public boolean hasNext() { if (!this.initialized) { try { initialize(); } catch (IOException ex) { return false; } } try { String nextLine = this.reader.readLine(); if (nextLine != null) { this.next = nextLine; return true; } else { dispose(); return false; } } catch (IOException ex) { dispose(); return false; } } @Override public String next() { return this.next; } @Override public void remove() { throw new UnsupportedOperationException(); } }
非常に長い上、ストリームというリソースを扱うライフサイクルがメソッド間で分離され、メンテナンスが容易でなくなります。一方、context.OuterIterable<T>を使用してIterableを実装すると以下のようになります。
public class OuterIterableImpl2 extends OuterIterable<String> { private String filePath = null; public OuterIterableImpl2(String filePath) { this.filePath = filePath; } @Override protected void iterate() { BufferedReader reader = null; try { reader = new BufferedReader( new InputStreamReader( new FileInputStream(this.filePath))); } catch (IOException ex) { return; } try { String nextLine = reader.readLine(); while (nextLine != null) { yield(nextLine); } } catch (IOException ex) { // something to do } finally { try { reader.close(); } catch (IOException ex) { } } } }
特徴はyield()メソッドにあります。このメソッドへ文字列を指定することで、このIterableオブジェクトは指定された順番で文字列を取り出すことができます。このOuterIterable<T>オブジェクトをCollectionContext<T>クラスのfrom()メソッドに指定することで、ストリームから得た文字列のコレクションにフィルタをかけたり射影したりできるようになります。
6.Collection Contextフレームワークのご利用にあたって
このCollection Contextフレームワークは、当社実験サイト「YUMEMI Labs」からダウンロードしてご利用頂けます。ただし、自己責任でご利用ください。当社はいかなる損害も補償できませんのであしからずご了承ください。
初期リリースはバイナリのみの配布とさせていただきます。オープンソース化は今後検討いたします。
開発用ドキュメントは、この「ゆめ技」の記事と、javadocです。ご意見・ご要望・ご質問のすべてにお答えできるかどうかは分かりませんが、皆さんのご意見・ご要望がこのフレームワークの成長を加速させる原動力であることは確かです。また、頂いたご質問を元に、ゆめ技の記事を書いていこうと考えています。どうぞよろしくお願いします。
■アプリケーション開発と実行に必要なライブラリファイルのダウンロードCollectionContextAndroid1.0.0.jar
■アプリケーションの開発時に参照するドキュメントファイルをダウンロードCollectionContextAndroid1.0.0_javadoc.zip
AndroidのNFC機能でFeliCaの読み書きをする
初めまして、ちきん(mokemokechicken)です。 今回は、NexusSを使って、FeliCaデータの読み書きをするAndroidアプリを作ったのでそのご紹介をします。
AndroidOSの2.3から NFC(Near Field Communication)用のAPIがサポートされるようになりました。 NFCの特徴についてはこの@ITの記事が参考になります。
NFCの通信規格は、日本で普及しているFeliCaの通信規格を含んでいるので、大抵のNFCリーダー・ライターで物理的にはFeliCaにアクセスすることがでそうですが、 現在の標準NFC APIでは、NDEFデータ以外にアクセスはできません(IDmは取得できますが)。
しかし、先人たちの努力によって遂に隠しClassを通して、FeliCaのコマンドを発行できるようになり、そのソースコードが公開されました。
ちょうどその時、kouさんがNexusSを調達されており、Android,NFC,FeliCaについて遊ぶ・・ぢゃなくて調査することになりました。
その結果、NexusSと隠しClassによって、FeliCaに対して以下の操作ができることがわかりました。
- システムコード一覧の取得: システムコードは、アプリケーション毎に定義されたシステム領域です。
- サービスコード一覧の取得: サービスコードは、システム領域内の「ファイル識別子」のようなもの?です。
- サービスコード内のデータの読みこみ: 但し、非暗号化領域に限ります。
- サービスコード内のデータの書きこみ: 但し、非暗号化&書込み可能領域に限ります。
ですが、どのFeliCaカードがどういう領域を持っているか調べたり、書込み可能領域を編集できるのは、今後色々役に立ちそうなので、今回アプリを作ってみました。
続きを読む "AndroidのNFC機能でFeliCaの読み書きをする" »
Android2.3.2(rooted)→2.3.3 への手動Update & root化失敗による起動不能からの復旧メモ・・・
はじめに
こんにちは、ちきん(mokemokechicken)です。
NexusS の2.3.3のOTAが始まりましたが、root化しているので、ちゃんと適用されるかわからないので、手動でやってみました。
2.3.3へのUpdateは無事上手くいったのですが、再度のRoot化で見事にハマりました。
私のようなAndroid初心者の方も多いと思われ、こういう失敗の共有もそれなりに有意義だと思ったので、その顛末を公開しておきたいと思います。
メモベースなので、乱文乱筆すみません。
UpdateとRoot化
NexusS 2.3.2(rooted) -> 2.3.3 への手動Update
Update前の環境
NexsusS&Android2.3.2で- oem unlock
- root化(boot.superboot.img という 2.3.2専用のimgを入れた。そしてこれが後々仇になる・・・)
- ClockworkMod(=CWM) 3.0.0.5 導入済み
NexusSによるNFC調査: getTechList 編
こんにちは、ちきん(mokemokechicken)です。
さて、私のNexusSでもやっとAPI10が利用可能になったので、現在色々調査中なのですが、
今回は、 getTechList() という「AndroidがNFC系カードをどのような種別として認識するか」という結果について簡単にメモしておきます。
getTechList()の結果
android.nfc.Tag#getTechList()は、 Android端末がNFC系カードを発見したIntentに含まれるTagインスタンスのメソッドで、
Tag tag = (Tag)intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String[] techList = tag.getTechList();などで取得できる値です。
この techList に入る値は、 android.nfc.tech の TagTechnology を ImplementしたClassの(fully-qualifiedな)名前になります。
続きを読む "NexusSによるNFC調査: getTechList 編" »
Android NFCとNexusSで MifareClassic を読み書きする(前編)
こんにちは、ちきんです。
前回のエントリで「MifareClassicにNdefFormatableで書きこむとどうなるのか?」という疑問がありましたので、調査を続けていきます。
今回は準備として MifareClassic カードに読み書きをしたり、データのバックアップやリストアを実装してみました。
しかし、その過程でいつものようにトラブルが発生し、 解決のためにMifareClassicの仕様を調べてみたところ、
MifareClassicは後戻りできない書込みもできてしまうことなども判明しましたので、その辺りを共有したいと思います。
何せこのカードは私物の保育園の入館証なので、再起不能にしてしまったかと色々冷や汗物語はありましたが、
無駄に長くなるので、なるべく要点を記述していきたいと思います。
Android NFCとNexusSで MifareClassic を読み書きする(中編)
こんにちは、ちきんです。
前回に続き、 MifareClassicの話です。
今回は、 NdefFormatable を使って、 MifareClassic にデータを書き込めるか調査しました。
結果は、 (おそらく)検証に用いたカードの問題で「中途半端に書込みが成功」というものでした。きっとまっさらなカードなら成功したのではないかと思います。
色々興味深いこともいくつかわかったので、以下、その状況について説明していきます。
Android NFCとNexusSで MifareClassic を読み書きする(後編)
こんにちは、ちきんです。今回も引き続きMifareClassicの話です。
今回は、入手した真っさらな MifareClassic(Mifare Standard)のカードに NdefFormatable#format() をしたところ、
NDEF_DISCOVERED で intentが発生したり、Ndef の instanceが使えるようになりましたのでその辺りのお話と、
MifareClassicシリーズ最終回ということでMifareClassicに関するまとめをしてみたいと思います。






