Android NFCアプリケーション開発



NFC(近距離無線通信)は、短距離でデータを交換するための標準化された技術であり、シンプルで直感的な方法で2つの電子デバイス間の相互作用を可能にします。 たとえば、NFCを搭載したスマートフォンを使用すると、買い物をしたり、名刺を配ったり、割引クーポンをダウンロードしたりできます。 NFCの多くの新しいアプリケーションが間もなく見つかります。

この記事では、NFCを使用するテクノロジーと、今日それらを使用する方法について説明します。 また、AndroidアプリケーションでNFCを使用する方法も示しています。最後に、ソースコードを使用したNFCアプリケーションの2つの例があります。



NFCテクノロジーアーキテクチャ

NFCは、13.56 MHzの周波数と最大10 cmの作動距離を持つRFIDテクノロジーに基づいており、データ交換レートは最大424 kb / sです。 他の通信技術と比較して、NFCの主な利点は、その速度と使いやすさです。 次の図は、他の通信技術の中でもNFCの場所を示しています。







NFCテクノロジーには、NFCカードエミュレーション、ピアツーピアモード、読み取り/書き込みモードの3つのモードがあります。







エミュレーションモードでは、NFCカードは、独自のセキュリティモジュールを備えたチップRFIDカードに類似しているため、購入プロセスを保護できます。 ピアツーピアモードでは、名刺などの情報を他のNFCデバイスと共有できます。 NFC経由でWiFiまたはBluetooth接続を確立して、大量のデータを転送することもできます。 読み取り/書き込みモードは、NFCデバイスを使用してNFCタグを読み取りまたは変更するためのものです。

各モードについて、以下で詳しく説明します。



NFCカードエミュレーションモード

NFCモジュールは通常、NFCコントローラーとセキュリティエレメント(EB)の2つの部分で構成されています。 NFCコントローラーは通信を担当し、電子モジュールは機密情報の暗号化と復号化を担当します。







EBは、SWP(シングルワイヤプロトコル)バスまたはDCLB(デジタル非接触ブリッジ)を介してNFCコントローラーに接続されます。 NFC標準は、ホストとコントローラー間の論理インターフェイスを定義し、RFフィールドを通じて通信できるようにします。 EBは、組み込みアプリケーションまたはOSコンポーネントを使用して実装されます。







EBの実装には3つのオプションがあります。SIMカード、SDカード、またはNFCチップに埋め込むことができます。







CMCC(China Mobile Communication Corporation)、Vodafone、AT&Tなどの通信プロバイダーは、通常SIMカードソリューションを使用して、古いSIMカードをNFCを備えた新しいSIMカードに無料で交換することを加入者に奨励しています。



ピアツーピアモード

2つのNFCデバイスは、簡単に相互に直接やり取りして、小さなファイルを交換できます。 Bluetooth / WiFi接続を確立するには、特別な形式のXMLファイルを交換する必要があります。 このモードでは、EBは使用されません。



書き込み/読み取りモード

このモードでは、NFCデバイスはNFCタグを読み書きできます。 アプリケーションの良い例は、NFCを装備したスマートポスターから情報を読み取ることです。







Android NFC開発の概要

Androidは、android.nfcとandroid.nfc.techの2つのパッケージでNFCをサポートしています。

android.nfcの主なクラスは次のとおりです。

NfcManager:Androidデバイスは検出されたNFCアダプターを管理するために使用できますが、ほとんどのAndroidデバイスは1つのNFCアダプターのみをサポートするため、NfcManagerは通常getDefaultAdapterで呼び出されて特定のアダプターにアクセスします。

NfcAdapterは、PCのネットワークアダプターのようなNFCエージェントとして機能します。 これにより、電話機はNFCハードウェアにアクセスして、NFC接続を初期化します。

NDEF:NFC標準は、MIMEで始まり、URLなどの超短RTDドキュメントで終わる、さまざまなタイプのオブジェクトを保存および転送できるNFC Data Exchange Format(NDEF)と呼ばれる一般的なデータ形式を定義します。 NdefMessageとNdefRecordは、サンプルコードで使用されるNFCフォーラム定義のデータ形式用の2種類のNDEFです。

タグ:Androidデバイスは、ショートカット、カードなどの受動オブジェクトを検出すると、「ラベル」タイプのオブジェクトを作成し、ターゲットオブジェクトにさらに配置して、最終的に対応するプロセスに送信します。

android.nfc.techパッケージには、多くの重要なサブクラスも含まれています。 これらのサブクラスは、読み取りおよび書き込み操作を含むラベル関数へのアクセスを提供します。 使用されるテクノロジーのタイプに応じて、これらのクラスはNfcA、NfcB、NfcF、MifareClassicなどのさまざまなカテゴリに分類されます。

NFC対応電話がタグを検出すると、配信システムはターゲット情報のパケットを自動的に作成します。 このターゲット情報を処理できるアプリケーションが電話に複数ある場合、ユーザーにはリストから1つを選択するよう求めるウィンドウが表示されます。 ラベル配信システムは、NDEF_DISCOVERED、TECH_DISCOVERED、TAG_DISCOVEREDの3つのタイプのターゲット情報を優先度の降順で定義します。

ここでは、ターゲットフィルターを使用して、TECH_DISCOVEREDからACTION_TECH_DISCOVEREDまでのすべてのタイプの情報を処理します。 nfc_tech_filter.xmlファイルは、ラベルで定義されているすべてのタイプに使用されます。 詳細については、 Androidのドキュメントをご覧ください 。 次の図は、タグを検出する方法を示しています。







例1.タグの読み取り/書き込み用のNFCアプリケーションの開発。

次の例は、NFCタグの読み取り/書き込み機能を示しています。 NFCハードウェアにアクセスし、NFC情報を正しく処理するには、AndroidManifest.xmlファイルでこれらの位置を宣言します。



<uses-permission android:name="android.permission.NFC" />
      
      





アプリケーションがサポートする必要があるSDKの最小バージョンは10です。AndroidManifest.xmlファイルで宣言してください



 <uses-sdk android:minSdkVersion="10"/> In the onCreate function,you can apply the NfcAdapter: public void onCreate(Bundle savedInstanceState) { …… adapter = NfcAdapter.getDefaultAdapter(this); …… }
      
      





次のターゲット呼び出しは、読み取り機能を示しています。 システムのブロードキャストメッセージがNfcAdapter.ACTION_TAG_DISCOVEREDの場合、情報を読んで表示できます。



 @Override protected void onNewIntent(Intent intent){ if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){ mytag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // get the detected tag Parcelable[] msgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefRecord firstRecord = ((NdefMessage)msgs[0]).getRecords()[0]; byte[] payload = firstRecord.getPayload(); int payloadLength = payload.length; int langLength = payload[0]; int textLength = payloadLength - langLength - 1; byte[] text = new byte[textLength]; System.arraycopy(payload, 1+langLength, text, 0, textLength); Toast.makeText(this, this.getString(R.string.ok_detection)+new String(text), Toast.LENGTH_LONG).show(); } }
      
      





次のコードは、書き込み機能を示しています。 mytagの値を決定する前に、ラベルが定義されていることを確認してから、データを入力してください。



  If (mytag==Null){ …… } else{ …… write(message.getText().toString(),mytag); …… } private void write(String text, Tag tag) throws IOException, FormatException { NdefRecord[] records = { createRecord(text) }; NdefMessage message = new NdefMessage(records); // Get an instance of Ndef for the tag. Ndef ndef = Ndef.get(tag); // Enable I/O ndef.connect(); // Write the message ndef.writeNdefMessage(message); // Close the connection ndef.close(); }
      
      





読んだ情報に応じて、タスクの開始、リンクのフォローなど、追加のアクションを実行できます。



例2. MifareClassicカードを使用したNFCアプリケーションの開発

この例では、MifareClassicカードと対応するラベルタイプを読み取りに使用します。 MifareClassicカードは、個人識別、バスのチケットなど、さまざまなニーズに広く使用されています。 従来のMifareClassicマップでは、ストレージエリアは16のゾーンに分割され、各ゾーンに4つのブロックがあり、各ブロックは16バイトのデータを格納できます。

ゾーンの最後のブロックはトレーラーと呼ばれ、通常はローカルの読み取り/書き込みキーを保存するために使用されます。 MifareClassic.KEY_DEFAULTの値に応じて、デフォルトで00またはFFで詰まっている2つのキー、それぞれ6バイト長のAとBが含まれます。

Mifareカードに書き込むには、まず、正しいキー値(保護の役割を果たす)が必要です。また、認証に成功する必要があります。



 <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="org.reno" android:versionCode="1" android:versionName="1.0" > <uses-permission android:name="android.permission.NFC" /> <uses-sdk android:minSdkVersion="14" /> <uses-feature android:name="android.hardware.nfc" android:required="true" /> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name="org.reno.Beam" android:label="@string/app_name" android:launchMode="singleTop" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> </activity> </application> </manifest>
      
      





res / xml / nfc_tech_filter.xml:



  <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <tech>android.nfc.tech.MifareClassic</tech> </tech-list> </resources>
      
      





MifareClassicカードの読み取り方法の例:



  private void processIntent(Intent intent) { Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); for (String tech : tagFromIntent.getTechList()) { System.out.println(tech); } boolean auth = false; MifareClassic mfc = MifareClassic.get(tagFromIntent); try { String metaInfo = ""; //Enable I/O operations to the tag from this TagTechnology object. mfc.connect(); int type = mfc.getType(); int sectorCount = mfc.getSectorCount(); String typeS = ""; switch (type) { case MifareClassic.TYPE_CLASSIC: typeS = "TYPE_CLASSIC"; break; case MifareClassic.TYPE_PLUS: typeS = "TYPE_PLUS"; break; case MifareClassic.TYPE_PRO: typeS = "TYPE_PRO"; break; case MifareClassic.TYPE_UNKNOWN: typeS = "TYPE_UNKNOWN"; break; } metaInfo += "Card type:" + typeS + "n with" + sectorCount + " Sectorsn, " + mfc.getBlockCount() + " BlocksnStorage Space: " + mfc.getSize() + "Bn"; for (int j = 0; j < sectorCount; j++) { //Authenticate a sector with key A. auth = mfc.authenticateSectorWithKeyA(j, MifareClassic.KEY_DEFAULT); int bCount; int bIndex; if (auth) { metaInfo += "Sector " + j + ": Verified successfullyn"; bCount = mfc.getBlockCountInSector(j); bIndex = mfc.sectorToBlock(j); for (int i = 0; i < bCount; i++) { byte[] data = mfc.readBlock(bIndex); metaInfo += "Block " + bIndex + " : " + bytesToHexString(data) + "n"; bIndex++; } } else { metaInfo += "Sector " + j + ": Verified failuren"; } } promt.setText(metaInfo); } catch (Exception e) { e.printStackTrace(); } }
      
      





著者について

Songyue WangとLiang Zhangは、Intel Software and Service Groupのエンジニアであり、Androidを含むモバイルアプリケーションを開発し、x86プラットフォーム向けに最適化します。



All Articles