android使用NFC的读模式

时间:2021-09-06 00:15:50

转自:http://blog.csdn.net/menghnhhuan/article/details/16968689

NFC读模式工作流程:NFC芯片轮询执行读模式、点对点和卡模式,当把卡片靠近手机的NFC天线的时候,NFC会识别到卡,然后
把卡对象装到intent里面,并发送广播NfcAdapter.ACTION_TECH_DISCOVERED,应用程序接到这个广播之后,通过
intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)来获取到卡对象,然后就可以对卡进行读写。

了解这个之后,我们就可以写自己的应用了。

两个步骤完成:

1.注册接受广播和过滤器

用静态的方式,在AndroidManifest.xml注册,这样子activity不在运行状态的时候也可以接受到广播。

[html] view plain copy print?android使用NFC的读模式android使用NFC的读模式
  1. <activity  
  2.     android:name="nfc.read.test.main"  
  3.     android:screenOrientation="portrait"  
  4.     android:label="@string/app_name" >  
  5.     <intent-filter>  
  6.         <action android:name="android.intent.action.MAIN" />  
  7.                 <category android:name="android.intent.category.LAUNCHER" />  
  8.     </intent-filter>  
  9.     <intent-filter>  
  10.                 <action android:name="android.nfc.action.TECH_DISCOVERED" />  
  11.     </intent-filter>  
  12.     <meta-data android:name="android.nfc.action.TECH_DISCOVERED"  
  13.                 android:resource="@xml/nfc_tech_filter" />  
  14.     <intent-filter>  
  15.         <action android:name="android.nfc.action.TAG_DISCOVERED" />  
  16.         <category android:name="android.intent.category.DEFAULT" />  
  17.     </intent-filter>  
  18. </activity>  

nfc_tech_filter.xml是过滤器,过滤哪些卡片

[html] view plain copy print?android使用NFC的读模式android使用NFC的读模式
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">  
  3.     <tech-list>  
  4.         <tech>android.nfc.tech.IsoDep</tech>  
  5.     </tech-list>  
  6.     <tech-list>  
  7.         <tech>android.nfc.tech.NfcV</tech>  
  8.     </tech-list>  
  9.     <tech-list>  
  10.         <tech>android.nfc.tech.NfcF</tech>  
  11.     </tech-list>  
  12. </resources>  
2.处理接收到的广播
继承activity的方法public void onNewIntent(Intent intent);
用Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);获取到tag,
把tag转换为IsoDep isodep = IsoDep.get(tag);
也可以把tag转换为MifareClassic mfc = MifareClassic.get(tag);
这个根据读到的tag类型的转换,tag的类型有很多,饭卡门禁卡这些一般是MifareClassic,非接触银行卡公交卡这些一般是IsoDep。
举个例子,下面是读取深圳通卡的余额:

[java] view plain copy print?android使用NFC的读模式android使用NFC的读模式
  1. @Override  
  2. public void onNewIntent(Intent intent) {  
  3.     super.onNewIntent(intent);        
  4.     // 1) Parse the intent and get the action that triggered this intent  
  5.     String action = intent.getAction();  
  6.     Log.d(TAG, "Discovered tag with intent: " + action);  
  7.     // 2) Check if it was triggered by a tag discovered interruption.  
  8.     if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {  
  9.         // 3) Get an instance of the TAG from the NfcAdapter  
  10.         Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);              
  11.         try  
  12.         {  
  13.             //Get an instance of the type A card from this TAG  
  14.             IsoDep isodep = IsoDep.get(tagFromIntent);  
  15.             isodep.connect();  
  16.             //select the card manager applet  
  17.             byte[] mf = { (byte'1', (byte'P',  
  18.                     (byte'A', (byte'Y', (byte'.', (byte'S', (byte'Y',  
  19.                     (byte'S', (byte'.', (byte'D', (byte'D', (byte'F',  
  20.                     (byte'0', (byte'1', };  
  21.             byte[] mfRsp = isodep.transceive(getSelectCommand(mf));  
  22.             Log.d(TAG, "mfRsp:" + HexToString(mfRsp));  
  23.             //select Main Application  
  24.             byte[] szt = { (byte'P', (byte'A', (byte'Y',  
  25.                     (byte'.', (byte'S', (byte'Z', (byte'T' };  
  26.             byte[] sztRsp = isodep.transceive(getSelectCommand(szt));  
  27.             Log.d(TAG, "sztRsp:" + HexToString(sztRsp));  
  28.                   
  29.             byte[] balance = { (byte0x80, (byte0x5C0x000x020x04};  
  30.             byte[] balanceRsp = isodep.transceive(balance);  
  31.             Log.d(TAG, "balanceRsp:" + HexToString(balanceRsp));  
  32.             if(balanceRsp!=null && balanceRsp.length>4)  
  33.             {  
  34.                         int cash = byteToInt(balanceRsp, 4);                      
  35.                         float ba = cash / 100.0f;  
  36.                         EditText result = (EditText) findViewById(R.id.block4);  
  37.                 result.setText("Balance:"+ba);  
  38.             }                 
  39.                 isodep.close();  
  40.         }catch(Exception e)  
  41.         {  
  42.             Log.e(TAG, "ERROR:" + e.getMessage());  
  43.         }  
  44.     }  
  45. }  
下面是读取MifareClassic的例子,使用的是默认密钥:

[html] view plain copy print?android使用NFC的读模式android使用NFC的读模式
  1. @Override  
  2. public void onNewIntent(Intent intent) {  
  3.     super.onNewIntent(intent);        
  4.     // 1) Parse the intent and get the action that triggered this intent  
  5.     String action = intent.getAction();  
  6.     Log.d(TAG, "Discovered tag with intent: " + action);  
  7.     // 2) Check if it was triggered by a tag discovered interruption.  
  8.     if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {  
  9.         // 3) Get an instance of the TAG from the NfcAdapter  
  10.         Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);      
  11.         try {  
  12.             //Get an instance of the Mifare classic card from this TAG  
  13.             MifareClassic mfc = MifareClassic.get(tagFromIntent);  
  14.             mfc.connect();  
  15.             Log.d(TAG, "sectorCount=" + mfc.getSectorCount());  
  16.   
  17.             int block = 4;  
  18.             EditText result = (EditText) findViewById(R.id.block4);  
  19.             //use default key to authenticate  
  20.             boolean auth = mfc.authenticateSectorWithKeyA(block / 4, MifareClassic.KEY_DEFAULT);  
  21.             if (auth)   
  22.             {  
  23.                 // read block  
  24.                 if (FunctionFlag == 0)   
  25.                 {  
  26.                     byte[] data = mfc.readBlock(block);  
  27.                     result.setText(HexToString(data));  
  28.                 }  
  29.                 // write block  
  30.                 else if (FunctionFlag == 1)   
  31.                 {  
  32.                     byte[] data = StringToHex(result.getText().toString());  
  33.                     mfc.writeBlock(block, data);  
  34.                 }  
  35.             }  
  36.             mfc.close();  
  37.         } catch (Exception e) {  
  38.             Log.e(TAG, "ERROR:" + e.getMessage());  
  39.         }  
  40.     }  
  41. }  

记得添加NFC的权限
[html] view plain copy print?android使用NFC的读模式android使用NFC的读模式
  1. <uses-permission android:name="android.permission.NFC" />  
源码下载地址,百度网盘:
链接:  http://pan.baidu.com/s/1Ectjo  密码: n3mk