NFCへの書き込み

NFCへの書き込み

NFCタグへの書き込み工程は

書き込み対象タグのタグ情報取得

書き込むタグ情報の作成

タグの書き込み判定

タグへ書き込み

となる

タグへ書き込む方法は、書き込み対象タグにより変わる

このため、事前にタグ情報取得をしている

タグ情報を読み込む理由は、2つ

1 書き込み対象タグが実在しているか?

2 書き込み対象タグのフォーマットの確認
これは、フォーマットにより書き込み方が異なるから

これらの取得したタグ情報は
インテントにふくまれるため

Intent.getParcelableExtra()のキーへ
NfcAdapter.EXTRA_TAG
を指定すれば取得できる

ソースにすると
Tag tag = Intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

UIDの取得

UIDの取得

タグはデータタイプにより読み込み方法が変わるが
UID取得は変わらない 

UIDの取得は、タグの読み込みがどういうものか知るキッカケとしては適している

NFCアプリでは、読み込んだタグに含まれるタグ情報は
インテントデータを介して受信する

このため、タグ情報を含んだインテントを
Activity上で受けとるには
onNewIntentクラスを使う

ただし、onNewIntentで受けとるインテントデータは
NFCデータだけではないから
インテントを受け取ったときに
NFCのインテントアクションか判定する必要がある

ソースにすると
protected void onNewIntent(Intent intent){
super.onNewIntent(intent);
String action = intent.getAction();

if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)){

という判定をする
.equals()を使うのはJavaではよくある
理由は、
Stringはクラスなので不等号比較ができないから

詳しくは、サーチマンさんのサイトの解説

条件式(if文)で文字列の比較はequals()メソッド
http://www.searchman.info/tips/2770.html
をみるとわかりやすい

今回のように
NFCのインテントアクションなら
インテント内にNFCのタグ情報が含まれているので
UIDを取得できる

UIDはバイト列で格納されていて
intent.getByteArrayExtra()
のキーに
NfcAdapter.EXTRA_IDを指定すれば取得できる

UIDは、バイト列での取得なので
UIDとして画面出力するには
16進数に変換しないとみてもわからない

ソースにすると
UID取得は
byte[] uid = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID);

UIDを文字列変換して表示するには
TextView txtuid =(TextView)findViewById(R.layout.txtuid);
txtuid.setText(NfcUtil.bytesToHex(uid));

OS versionごとに処理を分けるには

OS versionごとに処理を分けるには

Build.VERSION.SDK_INTを使うことで
アプリを実行している端末のOS versionを取得できる

そして、OS versionは
Build.VERSION_CODES.xxx
という形で定数として定められている

ちなみに、xxxには数値ではなく
Androidのversionを示すコードネームになる

1.6 ならDONUT ドーナツ

2.0 ならECLAIR エクレア
という感じになる

これを使い、もしAndroid OS versionごとに処理を分けたいのなら
Build.VERSION.SDK_INTの値を取得し
バージョンコードで条件式を作成すれば
処理を分けることができる

これは、NFC設定画面のリンクを作成するときに使える

ちなみに、Android 4.1は
Jelly_Beans つまりあめ玉になる

NFCの利用可否

NFCの利用可否

NFCアプリでは
端末のNFC搭載確認、
NFCが利用可能になっているか確認

非搭載ならもちろん使えないけど
搭載されていても、設定で無効になっていると使えない
これは、GPSとかBluetoothとかと同じ

NFC搭載されているか調べるには
NfcAdapterクラスのgetDefaultAdapter()を使えばいい

このgetDefaultAdapter()を使うことで
NFC搭載端末なら
NfcAdapterのインスタンスが生成されるけど
NFC非搭載端末ならnullが返ってくる

このため、返り値がnullなら
NFC非搭載端末と判断できる

ソースにすると
onCreate()の中へ記述するので

まずNFCインスタンス取得
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);

この返り値で、搭載か非搭載か判断できる

次に、NFCが利用可能になっているか確認する
これは、NfcAdapter.isEnabled()を使う

これは、単純に返り値がtrueとなっていればNFCが利用可能となる

ソースにすると
//NFC搭載かチェック
if(mNfcAdapter != null){

//NFCが有効かチェック
if(!mNfcAdapter.isEnabled()){

//NFCが無効なことをtoastで表示
Toast.makeText(getApplicationContext(), getString(R.string.error_nfc_disable),Toast.LENGTH_SHORT).show();
}

//NFC非搭載なので、ユーザーに通知
}else{
Toast.makeText(getApplicationContext(),getString(R.string.error_nfc_nosupported),Toast.LENGTH_SHORT).show();
}

実際に配布するアプリにするなら
これらのアプリの利用可能の判定に加えて
アプリのメニュー内にNFC設定画面に誘導するようなリンクを追加するなどユーザビリティも意識すること

NFC設定画面については
Android 4.0以下ならACTION_WIRELESS_SETTING
というインテントアクションを

Android 4.1以上なら
ACTION_NFC_SETTING
というインテントアクションを使い
startActivity()を呼び出すことで
NFC機能の設定画面を起動できる

ソースにすると
if(Build.VERSION_SDK_INT >= Build.VERSION_CODES.JELLY_BEANS){
//Android 4.1以上なら、直接NFC設定画面を呼び出すIntent アクションを使う
startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));

}else{
//Android 4.0以下ならwireless設定画面を呼び出すIntentアクションを使う
startActivity(new Intent(Settings.ACTION_WIRELESS_SETTINGS));
}

NFCインテント

NFCインテント

NFCインテントの種類は以下のようになる

ACTION_NDEF_DISCOVERED
NDEFペイロードが存在する場合実行される
MIME-TypeやURIスキームを指定することで、細かく設定することができる

ACTION_TECH_DISCOVERED
タグが見つかり、その中に含まれるNFCの種類に起因して発行される
NFCの種類は、xmlファイルを用意し
そこに指定したものがフィルター対象となる

ACTION_TAG_DISCOVERED
タグが見つかったときに発行される