fred-ye / summary

my blog
43 stars 9 forks source link

[Android][NFC start] #13

Open fred-ye opened 10 years ago

fred-ye commented 10 years ago

1.什么是NFC? NFC(Near Field Communication) 是一种短距离的无线通讯技术。通常要求设备之间的距离要小于4cm.其数据的传输速度在106kbit/s到848kbit/s。和其它的无线技术(Bluetooth, WiFi)不一样的是NFC的功耗更低,NFC通讯的发生不一定要求接收者和发起者都是带电的。如利用手机读取公交卡中的余额。一个具有NFC硬件的android设备,当屏幕处于非锁定状态的时候,都会扮演一个发起者的角色,当检测到一个NFC tag的时候,便会调用相应的Activity去处理。

  1. Android中关于NFC的两个包 2.1. android.nfc包中的几个类:NfcManger, NfcAdapter, NdefMessage, NdefRecord, Tag.

NfcManager 可以获得该android设备的NFC adapters. 而大多数的android设备都只会有一个NFC adapter, 所以多数情况下,我们只需要调用getDefaultAdapater(Context)方法便可以获得 adapter. NfcAdapter: NfcAdapter中封装了intent.可以通过NfcAdapter获得intent中的数据。 NdefMessage: NDEF是一个数据结构用来在NFC tags中高效的存储数据。如文本,URL, 或其它的 MIME类型。NdefMessage是一个用来传递、读取数据的容器。一个NdefMessage对象包含了0个或多个NdefRecords. NDEF message中定义第一个NDEF record用来负责传递tag到activity. Tag: Tag代表了一个被动的NFC taget.如公交卡之类的东东。当一个tag被检测到,一个Tag对象也就创建了,并且封装到intent中,NFC分发系统会将这个intent送到相应的Activity进行处理。调用Tag的getTechList()方法可以检测到这个Tag所支持的technology.

2.2 android.nfc.tech包,该包中包含了对tag进行属性查询,IO操作的类。TagTechnology, NfcA, NfcB, NfcF,NfcVIsoDep等。[看API吧]

3.开发一个NFC的应用: 3.1 权限的声明:

<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />

3.2 对于处理NFC的Activity的配置:

<intent-filter>
  <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
  <data android:mimeType="mime/type" />
</intent-filter>

<intent-filter>
  <action android:name="android.nfc.action.TECH_DISCOVERED"/>
  <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter.xml" />
</intent-filter>

<intent-filter>
  <action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>

3.3关于Tag的分发系统: 在高版本的android API中,有一个很好的图画出了Tag分发的流程,无奈Google最近都是访问不了。只有从电脑里找一个低版本的看看。

当一个android设备检测到一个NFC tag时,系统会去寻找最合适的Activity来handle这个intent.而不会问用户去选取某个应用程序。因为当设备在检测NFC tag时,设备与NFC tag 之间的距离非常近,如果让用户再去选择程序,用户很容易移动手机,导致距离拉长,连接中断。Android平台提供了两种机制让用户的Activity正确响应某个NFC tag: 采用 intent 分发系统,和 前台activity 分发系统。

intent分发系统会检查所有activity的 intent filter 和数据类型,通过这种方式来定位响应的activity.如果多个Activity定义了相同的intent filter 和 data, 系统将会让用户选择某一个。

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <data android:mimeType="text/plain" />
</intent-filter>
<activity>
.....
 <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>

则需要在xml中(对应于上面的 nfc_tech_filter)进行定义,如下:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
        <tech>android.nfc.tech.NfcA</tech>        
        <tech>android.nfc.tech.NfcB</tech>
        <tech>android.nfc.tech.NfcF</tech>
        <tech>android.nfc.tech.NfcV</tech>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NdefFormatable</tech>
        <tech>android.nfc.tech.MifareClassic</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

一个Demo:

  1. AndroidManifest.xml文件:
 <activity
     android:name="com.example.testnfc.MainActivity"
     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" />

     <intent-filter>
         <action android:name="android.nfc.action.TAG_DISCOVERED" />

         <category android:name="android.intent.category.DEFAULT" />
     </intent-filter>

 </activity>

2.nfc_tech_filter.xml

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcV</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcF</tech>
    </tech-list>
</resources>
  1. 一个Activity
public class MainActivity extends Activity {
    NfcAdapter nfcAdapter;  
    TextView promt;  

    public static final String TAG = "MainActivity";
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        promt = (TextView) findViewById(R.id.promt);  
        // 获取默认的NFC控制器  
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);  
        if (nfcAdapter == null) {  
            promt.setText("设备不支持NFC!");  
            finish();  
            return;  
        }  
        if (!nfcAdapter.isEnabled()) {  
            promt.setText("请在系统设置中先启用NFC功能!");  
            finish();  
            return;  
        }  
    }
    @Override
    protected void onResume() {
        super.onResume();
        Log.i("onResume","------------" + getIntent().getAction());
      //得到是否检测到ACTION_TECH_DISCOVERED触发  
        if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(getIntent().getAction())) {  

           //取出封装在intent中的TAG  
            Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);  
            Log.i("tagFromIntent","---------" + tag.toString());
        }          
    }
}

采用武汉市公交卡进行测试,发现对于这种卡采用的tech是 [android.nfc.tech.IsoDep, android.nfc.tech.NfcA] // TBD