现在很多手机已经配备了NFC(Near Field Communication 近场通信)的功能,我就为此专门研究过,可以到本文末尾下载源代码。

Android官方资料:http://developer.android.com/guide/topics/connectivity/nfc/index.html

相关资料参考:http://blog.csdn.net/nicebooks/article/details/6223956

相关Android应用:https://play.google.com/store/apps/details?id=com.nxp.nfc.tagwriter

关于NFC的知识就不讲了,下面直接看代码,主要是读取、写入的功能。先自己新建一个Android工程,下面是用到的变量:

    private NfcAdapter mNfcAdapter;//NFC适配器,就是那个NFC读卡器
    PendingIntent mNfcPendingIntent;//用于截获系统Intent,因为系统检测到NFC卡片时会选择程序去响应
    IntentFilter[] mWriteTagFilters;//IntentFilter表示满足本程序响应的条件
    private boolean mWriteMode = false;//控制读写模式切换

还是建议看看官方资料,这样才能明白某些函数的意思。接下来,在onCreate函数里检测NFC:

        //获取默认NFC设备
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if (mNfcAdapter == null) {
            Toast.makeText(this, "该设备不支持NFC!", Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        //查看NFC是否开启
        if (!mNfcAdapter.isEnabled()){
            Toast.makeText(this, "请在系统设置中先启用NFC功能", Toast.LENGTH_LONG).show();
            finish();
            return;
        }

        mNfcPendingIntent = PendingIntent.getActivity(this, 0,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndefDetected.addDataType("text/plain");
        } catch (MalformedMimeTypeException e) {
            e.printStackTrace();
        }
        mWriteTagFilters = new IntentFilter[] { ndefDetected };

这里先检测手机是否支持NFC,finish()表示退出程序。最后,给上面变量赋值,添加截获的NFC数据类型为"text/plain",表示纯文本。

所以,如果NFC卡片存的是URL地址,我们的程序将无法截获,系统会用浏览器打开。当我们按下Home键,这时就无需截获系统Intent了,添加如下代码:

    @Override
    protected void onResume()
    {
        super.onResume();
        mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mWriteTagFilters, null);
    }

    @Override
    protected void onPause()
    {
        super.onPause();
        mNfcAdapter.disableForegroundNdefPush(this);
    }

手机发现了NFC Tag,如果我们已经添加了PendingIntent,并且满足我们的IntentFilter条件,就会触发一个如下事件:

    //必须的函数,截获系统itent,然后触发读取和写入操作
    @Override
    protected void onNewIntent(Intent intent)
    {
        if (!mWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
        {
            NdefMessage[] msgs = getNdefMessages(intent);
            String body = new String(msgs[0].getRecords()[0].getPayload());

            System.out.println("***读取数据***" + body);
            tagInfo.setText(body);
        }

        if (mWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))
        {
            Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            boolean writesuccess = writeTag(getNoteAsNdef(), detectedTag);
            System.out.println("***写入数据***");
            if (writesuccess){
                Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show();
            }
            else{
                Toast.makeText(this, "写入失败!", Toast.LENGTH_SHORT).show();
            }
        }
    }

系统检测到Tag时,会将其所有信息封装到Intent中,我们截获了它就可以读取了。如果要写入,需要构造NdefMessage信息才行。

上面代码中的getNoteAsNdef用来根据输入构造NdefMessage:

    //从输入框获取信息,然后构造NdefMessage用于写入
    private NdefMessage getNoteAsNdef()
    {
        byte[] textBytes = (inputText.getText().toString()).getBytes();
        NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "text/plain".getBytes(), new byte[] {}, textBytes);
        return new NdefMessage(new NdefRecord[] { textRecord });
    }

实际读取数据部分如下:

    //实际读取数据部分
    private NdefMessage[] getNdefMessages(Intent intent)
    {
        NdefMessage[] msgs = null;
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))
        {
            Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (rawMsgs != null)
            {
                msgs = new NdefMessage[rawMsgs.length];
                for (int i = 0; i < rawMsgs.length; i++)
                {
                    msgs[i] = (NdefMessage) rawMsgs[i];
                }
            } else
            {
                // Unknown tag type
                byte[] empty = new byte[] {};
                NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
                NdefMessage msg = new NdefMessage(new NdefRecord[] { record });
                msgs = new NdefMessage[] { msg };
            }
        } else
        {
            // Log.d(TAG, "Unknown intent.");
            finish();
        }
        return msgs;
    }

实际写入部分如下:

    //实际写入数据部分
    boolean writeTag(NdefMessage message, Tag tag)
    {
        int size = message.toByteArray().length;

        try
        {
            Ndef ndef = Ndef.get(tag);
            if (ndef != null)
            {
                ndef.connect();

                if (!ndef.isWritable())
                {
                    System.out.println("Tag is read-only.");
                    return false;
                }
                if (ndef.getMaxSize() < size)
                {
                    System.out.println("Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size + " bytes.");
                    return false;
                }

                ndef.writeNdefMessage(message);
                System.out.println("****写入数据成功***");

                return true;
            } else
            {
                NdefFormatable format = NdefFormatable.get(tag);
                if (format != null)
                {
                    try
                    {
                        format.connect();
                        format.format(message);
                        System.out.println("**Formatted tag and wrote message**");
                        return true;
                    } catch (IOException e)
                    {
                        System.out.println("==Failed to format tag.==");
                        return false;
                    }
                } else
                {
                    System.out.println("Tag doesn't support NDEF.");
                    return false;
                }
            }
        } catch (Exception e)
        {
            System.out.println("!!写入数据失败!!");
        }
        return false;
    }

上面的写入、读取部分都不是很简洁,因为要兼容到android 2.3(API 10)的版本,Android 4.0以上提供了比较简单的读写方式,可以参考下面的文章:

http://shanetully.com/2012/12/writing-custom-data-to-nfc-tags-with-android-example/

如果你需要这样的功能,比如检测到文本时便启动你的程序,你可以在配置文件里设置,查看官方文档即可,我这里没有这样的需求。

最后,打开AndroidManifest.xml文件,添加如下代码用于开启NFC权限。注意,我的源代码

    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="14" />
    <uses-permission android:name="android.permission.NFC" />

Android下NFC的简单使用的更多相关文章

  1. Android下实现一个简单的计算器源码

    下面的内容是关于Android下实现一个简单的计算器的内容. import android.app.Activity; import android.os.Bundle;import android. ...

  2. Android训练课程(Android Training) - NFC基础

    NFC 基础 本文档介绍了在Android上的基本的NFC任务.它说明了如何发送和接收的NDEF消息(NDEF messages)的形式的表单里包含的NFC数据(NFC data),并介绍Androi ...

  3. Android下利用Bitmap切割图片

    在自己自定义的一个组件中由于需要用图片显示数字编号,而当前图片就只有一张,上面有0-9是个数字,于是不得不考虑将其中一个个的数字切割下来,需要显示什么数字,只需要组合一下就好了. 下面是程序的关键代码 ...

  4. android 下滤镜效果的实现

    android 下滤镜效果的实现 滤镜过滤颜色已实现,简单版本可通过下面代码的3个参数实现黑白.红.绿...等7种过滤(RGB的7种组合). 理论上讲可以过滤为任意颜色.调整混合结果的比值就行了. p ...

  5. android下的数据存储

    android下数据存储的几种方式:(简单讨论) 1.文件 举例:登陆时“记住密码” 因为是基于Linux系统,直接建文件,文件会出现在项目工程:而手机登陆时,应该把文件放在手机里,通常数据放在dat ...

  6. android下身份验证方式调用webservice

    在企业开发领域,webservice还是经常被用到的服务体系,因为他对安全事务支持都比较好. 有时候,我们就需要在android下调用后端的webservice服务,因为在内部网络环境下,所有需要ba ...

  7. [原创]Android中LocationManager的简单使用,获取当前位置

    Android中LocationManager的提供了一系列方法来地理位置相关的问题,包括查询上一个已知位置:注册/注销来自某个 LocationProvider的周期性的位置更新:以及注册/注销接近 ...

  8. Android 下用 Pull 解析和生成 XML

    Java 中是可以用 SAX 和 DOM 解析 XML  的,虽然在 Android 下也可以用这2中方式,但是还是推荐用 Pull.Pull 使用简单,效率相对高,Android 下是集成了 Pul ...

  9. Android下Affinities和Task

    源文链接:http://appmem.com/archives/405 本文参考了官方Dev Guide文档,简单介绍Android下的affinities和任务(task). 1.Activity和 ...

随机推荐

  1. 安装ADT Cannot complete the install because one or more required items could not be found.

    点击进行安装,将会弹出 错误提示是: Cannot complete the install because one or more required items could not be found ...

  2. tomcat context 配置 项目部署

    将tomcat/conf/server.xml文件打开, 在</Host>标签之前添加: <Context path = "" docBase = "F ...

  3. SaaS系列介绍之十: SaaS的商业模式

    1 引言 赚钱之道很多,但是找不到赚钱的种子,便成不了事业家.作为职业软件人,我们都寻求使用一种有效而经济的过程来建造一个能够工作的,有用的产品.                            ...

  4. c# 可访问性级别

    使用访问修饰符 public.protected.internal 或 private 可以为成员指定以下声明的访问级别之一.   声明的可访问性 含义 public 访问不受限制. protecte ...

  5. 在Ubuntu 12.04安装和设置SSH服务

    1.安装 Ubuntu缺省安装了openssh-client,所以在这里就不安装了,如果你的系统没有安装的话,再用apt-get安装上即可. 安装ssh-server sudo apt-get ins ...

  6. Python爬虫和情感分析简介

    摘要 这篇短文的目的是分享我这几天里从头开始学习Python爬虫技术的经验,并展示对爬取的文本进行情感分析(文本分类)的一些挖掘结果. 不同于其他专注爬虫技术的介绍,这里首先阐述爬取网络数据动机,接着 ...

  7. uyouo[]常棒的一篇关于innnodb next-key lock的文章

    何登成的 MySQL 加锁处理分析 Innodb锁机制:Next-Key Lock 浅谈

  8. bzoj2595

    一开始看是插头dp,后来发现还有一个叫斯坦纳树的东西 什么叫斯坦纳树,就是使给定点连通开销和最小的树(可以包含多余的点) 到这张平面图上,我们不难想到用dp来解决,设f[x,y,S]表示连通集合为S, ...

  9. nginx.conf配置

    在此记录下Nginx服务器nginx.conf的配置文件说明, 部分注释收集与网络. #运行用户 user www-data; #启动进程,通常设置成和cpu的数量相等 worker_processe ...

  10. ASP.NET MVC:通过 FileResult 向 浏览器 发送文件

    在 Controller 中我们可以使用 FileResult 向客户端发送文件. FileResult FileResult 是一个抽象类,继承自 ActionResult.在 System.Web ...