Android NFC基础开发教程

NFC 的功能和他是做什么用的我就不多废话了,请自行百度。

1.首先,你要知道你的设备是支持NFC的 并且此功能已经被打开。

并且你要在你的AndroidManifest.xml中开通NFC权限。

//开通权限

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

  // 设置在应用商店上过滤掉没有nfc功能的设备
        <uses-feature android:name="android.hardware.nfc" android:required="true" />

 //设置最小sdk支持版本为10
       <uses-sdk android:minSdkVersion="10"/>



2.当你的设备靠近NFC标签或者别的NFC设备的时候,系统会发出一个intent

来确定,那个应用区处理这个标签信息。

如果你需要做这样一个应用,那么你的AndroidManifest.xml文件中,就必须给

你想要的组件的多添加Intent-filter 并添加指定的Action name

系统给的ACTION  name有三个 他们分别是。

ACTION_NDEF_DISCOVERED:当系统检测到tag中含有NDEF格式的数据时,且系统中有activity声明可以接受包含NDEF数据的Intent的时候,系统会优先发出这个action的intent。


ACTION_TECH_DISCOVERED:当没有任何一个activity声明自己可以响应ACTION_NDEF_DISCOVERED时,系统会尝试发出TECH的intent.即便你的tag中所包含的数据是NDEF的,但是如果这个数据的MIME type或URI不能和任何一个activity所声明的想吻合,系统也一样会尝试发出tech格式的intent,而不是NDEF.

ACTION_TAG_DISCOVERED:当系统发现前两个intent在系统中无人会接受的时候,就只好发这个默认的TAG类型的


有了这样三个Action name 就可以保证在你设备连接nfc标签时,你的应用

有权利去连接这个标签并进行读写。


官方的图解:




在代码中,比如在一个Activity的intent拦截器中加入如下代码

1:过滤ACTION_NDEF_DISCOVERED:
   
<intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>


 
2:过滤ACTION_TUCH_DISCOVERED:

    //一般我们会以这个拦截器为基准,来拦截不同种类的标签

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

     //这个data 标识拦截的类型 ,这里标示无格式文本类型,这个数据定义的越准确。

     // 你拦截的效果才越准确
  <data android:mimeType="text/plain" />
     </intent-filter>



3:过滤ACTION_TAG_DISCOVERED:

  //这个一般用不到,可以忽略
      <intent-filter>
           <action android:name="android.nfc.action.ACTION_TAG_DISCOVERED"/>
           <category android:name="android.intent.category.DEFAULT"/>
      </intent-filter>


接下来我们来介绍,如何以ACTION_TUCH_DISCOVERED基准来设置拦截机器。

在介绍之前,你需要先了解,NFC标签是由不同标准的。

下面是标准列表

<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>


你使用的标签设备是支持哪些标准的,一定要在 tech-List中穿件一个他的集合 或者他集合的子集。

哦、对,对于这个拦截文件你需要重新创建一个xml资源文件。

下面是一个我项目完整的拦截文件,这个文件只能

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    

    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>

</resources>

那么我们怎么应用呢,下面附上我的主配置文件

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.myapplication" >
    <!--NFC 权限 -->
    <uses-permission android:name="android.permission.NFC"/>
    <uses-feature android:name="android.hardware.nfc" android:required="true" />
    <uses-sdk android:minSdkVersion="10"/>
    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
            <!-- NFC 过滤器-->
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED" />
            </intent-filter>
<span style="white-space:pre">	</span>    <span style="color:#ff0000;"><strong>//引入拦截配置文件</strong></span>
            <meta-data
                android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />

        </activity>
    </application>

</manifest>

3.从Activity中获取数据

 上文中介绍了,具备NFC功能的手机在靠近NFC标签的时候,系统会发出intent。而我们的数据应该如何获取呢?  
  
我们需要在Activity 的 

    protected void onResume() {
        super.onResume();
    }
 
            protected void onNewIntent(Intent intent) {
          super.onNewIntent();
               }
  在这两个方法中捕获intent才是最为合适的。
 onResume()方法捕捉intent,onNewIntent()用来处理。
 具体不解释 多看看ACtivity生命周期就会懂得。         

 而对NFC功能获取Intent的方法有多种     

  下面我们需要了解一中被谷歌官方重视的NFC格式NDEF格 式。  这是google参考nfc论坛而提出和支持的格式
   def格式,就是数据被包裹在一个 NdefMessage 里,而同时一个NdefMessage里面又可以包含多个              NdefRecord.
   当然你也应该还记得,nfc的tag里面是可以不包含Ndef数据的,他也可以包含android.nfc.tech所定义的多种标签。
    Google推荐开发人员使用ndef格式的数据来处理android相关的nfc格式数据。

    这里的NDEF 对应的就是上文中的ACTION_NDEF_DISCOVERED,使用它来拦截。
    使用这个tag  在代码中是这样体现的,

     if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
        //处理该intent
        // tag_NDEF(getIntent())   
      }
      
   同理 :如果你只想用你的拦截器android.nfc.tech 那么就应该这样写,
    
    if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(getIntent().getAction())) {
        //处理该intent
        // tag_TECH(getIntent())   
      }

      我们先介绍如何在NDEF 格式下进行读 
   private void writeNdefTag(Intent in){
        Tag tag = in.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        Ndef ndef = Ndef.get(tag);
        try {
//这一句别丢了,读nfc标签的时候不需要这句,因为那时数据直接就在intent中。
            ndef.connect(); 
//构造一个合适的NdefMessage。你可以看到代码里用了NdefRecord数组,只不过这个数组里只有一个record
            NdefMessage ndefMsg = new NdefMessage(new NdefRecord[]{createRecord()});
            ndef.writeNdefMessage(ndefMsg);
        } catch (IOException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        } catch (FormatException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
    }
       private NdefRecord createRecord(){
//               return new NdefRecord(NdefRecord.TNF_ABSOLUTE_URI,
//                       "http://www.baidu.com".getBytes(Charset.forName("US-ASCII")),
//                       new byte[0], new byte[0]);
                        
               return new NdefRecord(
                       NdefRecord.TNF_MIME_MEDIA ,
                       "application/com.android.TestNfc".getBytes(Charset.forName("US-ASCII")),
                       new byte[0],  "com.android.yufeimusic".getBytes(Charset.forName("US-ASCII")));
    }


 
   
 
TECH 的读写就简单得多 读,则就是在拦截的时候拦截方式不同则就可以,请大家举一反三。
最后要介绍下NFC的前台拦截机制。
什么叫nfc的前台拦截机制?就是说当我们已经打开我们的应用的时候,那么通过这个前台发布系统的设置,我们可以让我们已经启动的activity拥有更高的优先级来依据我们在代码中定义的标准来过滤和处理intent,而不是让别的声明了intent filter的activity来干扰,甚至连自己声明在androidManifest中的intent filter都不会来干扰。也就是说foreground Dispatch的优先级大于intent filter。
简单说就是在你的Activity 展现页面会独占nfc标签,标签不会被其应用和系统拦截所响应。
这个不需要再.xml里面设置链接器配置。
摘自:sdk的 \sdk\samples\android-20\legacy\ApiDemos
这里面都是谷歌给的demo 希望大家参考

/**
 * An example of how to use the NFC foreground dispatch APIs. This will intercept any MIME data
 * based NDEF dispatch as well as all dispatched for NfcF tags.
 */
public class ForegroundDispatch extends Activity {
    private NfcAdapter mAdapter;
    private PendingIntent mPendingIntent;
    private IntentFilter[] mFilters;
    private String[][] mTechLists;
    private TextView mText;
    private int mCount = 0;

    @Override
    public void onCreate(Bundle savedState) {
        super.onCreate(savedState);

        setContentView(R.layout.foreground_dispatch);
        mText = (TextView) findViewById(R.id.text);
        mText.setText("Scan a tag");

        mAdapter = NfcAdapter.getDefaultAdapter(this);

        // Create a generic PendingIntent that will be deliver to this activity. The NFC stack
        // will fill in the intent with the details of the discovered tag before delivering to
        // this activity.
        mPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        // Setup an intent filter for all MIME based dispatches
        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndef.addDataType("*/*");
        } catch (MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        }
        mFilters = new IntentFilter[] {
                ndef,
        };

        // Setup a tech list for all NfcF tags
        mTechLists = new String[][] { new String[] { NfcF.class.getName() } };
    }

    @Override
    public void onResume() {
        super.onResume();
        if (mAdapter != null) mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters,
                mTechLists);
    }

    @Override
    public void onNewIntent(Intent intent) {
        Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
        mText.setText("Discovered tag " + ++mCount + " with intent: " + intent);
    }

    @Override
    public void onPause() {
        super.onPause();
        if (mAdapter != null) mAdapter.disableForegroundDispatch(this);
    }
}





  








评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值