NFC技术的基础应用

       There are two major uses cases when working with NDEF data and Android:
        1、Reading NDEF data from an NFC tag

       2、Beaming NDEF messages from one device to another with Android Beam™。

     在安卓系统的应用中,最主要的有两种应用场景,第一个就是读取NEC标签里面的NDEF格式的数据,第二个就是不同设备间的NDEF信息数据的操作。接下来就主要学习一下这两块的实际应用。

    首先学习一下基础知识:

    一、权限的声明:

<uses-permission android:name="android.permission.NFC" />
<uses-sdk android:minSdkVersion="10"/>
<uses-feature android:name="android.hardware.nfc" android:required="true" />
    二、检查设备是否支持NFC

    private NfcAdapter nfcAdapter;
    private PendingIntent pendingIntent;
    private IntentFilter[] filters;
    private String[][] techLists=null;

  private void checkNdef() {
        nfcAdapter=NfcAdapter.getDefaultAdapter(this);
        pendingIntent=PendingIntent.getActivity(MainActivity.this, 500, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_S         INGLE_TOP), 0);
        IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            filter.addDataType("*/*");
            filters=new IntentFilter[]{filter};
        } catch (IntentFilter.MalformedMimeTypeException e) {
            e.printStackTrace();
        }
        if (nfcAdapter==null){
            Toast.makeText(this,"不支持NFC功能",Toast.LENGTH_SHORT).show();
        }else{
            if (nfcAdapter.isEnabled()){
                Toast.makeText(this,"NFC功能已打开",Toast.LENGTH_SHORT).show();
                nfcAdapter.setNdefPushMessageCallback(this,this);
            }else{
                Intent intent= new Intent(Settings.ACTION_NFC_SETTINGS);
                startActivity(intent);
            }
        }
    }
    三、NFC调度方式:前台调度和标签调度

     所谓前台调度就是指我们直接在一个当前运行程序的Activity中显式的应用NFC;而标签调度就是指我们在我们的应用程序中配置好相关的Intent-filter,当设备接触到NFC标签的时候会调用有该配置的应用程序。

    前台调度方式:(Manifest文件下的配置不做任何调整,只是声明一个普通的Activity即可)

public class MainActivity extends AppCompatActivity implements NfcAdapter.CreateNdefMessageCallback{
    private NfcAdapter nfcAdapter;
    private PendingIntent pendingIntent;
    private IntentFilter[] filters;
    private String[][] techLists=null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        checkNdef();
    }

    private void checkNdef() {
        nfcAdapter=NfcAdapter.getDefaultAdapter(this);
        pendingIntent=PendingIntent.getActivity(MainActivity.this, 500, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            filter.addDataType("*/*");
            filters=new IntentFilter[]{filter};
        } catch (IntentFilter.MalformedMimeTypeException e) {
            e.printStackTrace();
        }
        if (nfcAdapter==null){
            Toast.makeText(this,"不支持NFC功能",Toast.LENGTH_SHORT).show();
        }else{
            if (nfcAdapter.isEnabled()){
                Toast.makeText(this,"NFC功能已打开",Toast.LENGTH_SHORT).show();
                nfcAdapter.setNdefPushMessageCallback(this,this);
            }else{
                Intent intent= new Intent(Settings.ACTION_NFC_SETTINGS);
                startActivity(intent);
            }
        }
    }

    @Override
    protected void onResume() {
        super.onResume();
        //前台调度系统
        nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,filters,techLists);
    }

    @Override
    protected void onPause() {
        super.onPause();
        nfcAdapter.disableForegroundDispatch(MainActivity.this);
    }
}
    标签的调度系统:(此方式需要Manifest文件配置三种Intent过滤器,ACTION_NDEF_DISCOVERED、ACTION_TECH_SDISCOVERED、ACTION_TAG_DISCOVERED

           <!--NEDF_DISCOVERED-->
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED"></action>
                <category android:name="android.intent.category.DEFAULT"></category>
                <data android:mimeType="text/plain"></data>
            </intent-filter>
            <!--TECH_DISCOVERED-->
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED"></action>
            </intent-filter>
            <!--Define in the xml of resource-->
            <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/tech_list"></meta-data>
            <!--TAG_DISCOVERED-->
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED"></action>
            </intent-filter>
     tech_list.xml:

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

                                                                               读写模式

  NFC标签的读操作:

     基本步骤:

            第一:从intent里面获取到NDEFMessage;

            第二:解析数据

   文本的读操作:

        String action=intent.getAction();
        Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)){
            //第一步:获取NDEFMEssage
            NdefMessage[] messages=null;
            Parcelable[] rawMsgs=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMsgs !=null){
               messages = new NdefMessage[rawMsgs.length];
                for (int i = 0; i <messages.length ; i++) {
                    messages[i]= (NdefMessage) rawMsgs[i];
                }
            }else{
                byte[]empty=new byte[]{};
                NdefRecord ndefRecord=new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,empty,empty);
                NdefMessage ndefMessage=new NdefMessage(new NdefRecord[]{ndefRecord});
                messages = new NdefMessage[]{ndefMessage};
            }
            //第二步:解析文本数据
            if (messages !=null &&messages.length>0){
                for (int i = 0; i < messages.length; i++) {
                     int length=messages[i].getRecords().length;
                    NdefRecord[] records=messages[i].getRecords();
                    for (int j=0;j<length;j++){
                        for (NdefRecord ndefRecoder:records) {
                            //解析文本
                            if (isText){
                                //检查
                                Preconditions.checkArgument(Arrays.equals(ndefRecoder.getType(),NdefRecord.RTD_TEXT));
                                //获取payload内容
                                byte[] textPayload=ndefRecoder.getPayload();
                                //解析payload的第一个字节(包含编码格式,最高位为0的话,则为UTF-8;为1的话则为UTF-16)
                                Byte statuByte=ndefRecoder.getPayload()[0];
                                String textEncode;
                                if ((statuByte & 0x880)==0){
                                    textEncode="UTF-8";
                                }else{
                                    textEncode="UTF-16";
                                }
                                //获取language code,(通过第一个字节低五位,获取其长度)
                                int langLenth=statuByte&0x3F;
                                String langCode=new String(textPayload,1,langLenth,Charset.forName("UTF-8"));
                                try {
                                    //获取真实文本的数据
                                    String payloadText=new String(textPayload,langLenth+1,textPayload.length-langLenth-1,textEncode);
                                } catch (UnsupportedEncodingException e) {
                                    e.printStackTrace();
                                }
                            }
       Absolute_uri格式:

 String action=intent.getAction();
        Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)){
            //第一步:获取NDEFMEssage
            NdefMessage[] messages=null;
            Parcelable[] rawMsgs=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMsgs !=null){
               messages = new NdefMessage[rawMsgs.length];
                for (int i = 0; i <messages.length ; i++) {
                    messages[i]= (NdefMessage) rawMsgs[i];
                }
            }else{
                byte[]empty=new byte[]{};
                NdefRecord ndefRecord=new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,empty,empty);
                NdefMessage ndefMessage=new NdefMessage(new NdefRecord[]{ndefRecord});
                messages = new NdefMessage[]{ndefMessage};
            }
            //第二步:解析数据
            if (messages !=null &&messages.length>0){
                for (int i = 0; i < messages.length; i++) {
                     int length=messages[i].getRecords().length;
                    NdefRecord[] records=messages[i].getRecords();
                    for (int j=0;j<length;j++){
                        for (NdefRecord ndefRecoder:records) {
                              byte[] abPayload=ndefRecoder.getPayload();
                              Uri uri=Uri.parse(new String(abPayload,Charset.forName("UTF-8")));
      }
   } 
 }
}
   Well_know_Uri:

 String action=intent.getAction();
        Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)){
            //第一步:获取NDEFMEssage
            NdefMessage[] messages=null;
            Parcelable[] rawMsgs=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMsgs !=null){
               messages = new NdefMessage[rawMsgs.length];
                for (int i = 0; i <messages.length ; i++) {
                    messages[i]= (NdefMessage) rawMsgs[i];
                }
            }else{
                byte[]empty=new byte[]{};
                NdefRecord ndefRecord=new NdefRecord(NdefRecord.TNF_UNKNOWN,empty,empty,empty);
                NdefMessage ndefMessage=new NdefMessage(new NdefRecord[]{ndefRecord});
                messages = new NdefMessage[]{ndefMessage};
            }
            //第二步:解析数据
            if (messages !=null &&messages.length>0){
                for (int i = 0; i < messages.length; i++) {
                     int length=messages[i].getRecords().length;
                    NdefRecord[] records=messages[i].getRecords();
                    for (int j=0;j<length;j++){
                        for (NdefRecord ndefRecoder:records) {
                             Preconditions.checkArgument(Arrays.equals(ndefRecoder.getType(),NdefRecord.RTD_URI));
                             byte[] payload=ndefRecoder.getPayload();
                             String prefix=URI_PREFIX_MAP.get(payload[0]);
                             byte[] fullUri= Bytes.concat(prefix.getBytes(Charset.forName("UTF-8")), Arrays.copyOfRange(payload, 1, payload.length));
                             Uri uri=Uri.parse(new String(fullUri));
         }
      }
   }
}

     写操作:

  TNF_WELL_KNOWN with RTD_TEXT

   
<span style="color:rgba(0, 0, 0, 0.870588235294118);">  </span><span style="color:#333333;">public static NdefMessage writeText(String payload, Locale locale, boolean encodeInUtf8){
        byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
        Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
        byte[] textBytes = payload.getBytes(utfEncoding);
        int utfBit = encodeInUtf8 ? 0 : (1 << 7);
        char status = (char) (utfBit + langBytes.length);
        byte[] data = new byte[1 + langBytes.length + textBytes.length];
        data[0] = (byte) status;
        System.arraycopy(langBytes, 0, data, 1, langBytes.length);
        System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
        NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                NdefRecord.RTD_TEXT, new byte[0], data);
        return new NdefMessage(new NdefRecord[]{record});
    }</span>

   TNF_ABSOLUTE_URI

public static NdefMessage writeAbsoluteUri(String uri){
        NdefRecord uriRecord = new NdefRecord(
                NdefRecord.TNF_ABSOLUTE_URI ,
                uri.getBytes(Charset.forName("US-ASCII")),
                new byte[0], new byte[0]);
        return new NdefMessage(new NdefRecord[]{uriRecord});
    }

   TNF_WELL_KNOWN with RTD_URI

public static NdefMessage writeWellKnowUri(String uri){
    byte[] uriField = uri.getBytes(Charset.forName("US-ASCII"));
    byte[] payload = new byte[uriField.length + 1];              //add 1 for the URI Prefix
    payload[0] = 0x01;                                      //prefixes http://www. to the URI
    System.arraycopy(uriField, 0, payload, 1, uriField.length);  //appends URI to payload
    NdefRecord rtdUriRecord = new NdefRecord( NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], payload);
        return new NdefMessage(new NdefRecord[]{<span style="font-family: Roboto, sans-serif;">rtdUriRecord </span>});
    }<span style="font-size:18px;font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"><strong>      </strong>         </span><span style="font-size:14px;font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">            </span>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值