现在很多手机已经配备了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. 用Vue.js和Webpack开发Web在线钢琴

    缘起 由于童心未泯,之前在手机上玩过钢琴模拟App,但是手机屏幕太小,始终觉得不过瘾.其实对于我这个连基本乐理都不懂的"乐盲"来说,就算给我一台真正的钢琴,我也玩不转.不过是图个新 ...

  2. Android支付接入(五):机锋网

    原地址:http://blog.csdn.net/simdanfeg/article/details/9012083 前边已经陆续跟大家走了一遍运营商和支付宝付费接入,今天跟大家一起看看机锋网的支付接 ...

  3. Ubuntu环境下手动配置openSSH

    配置openSSH 1.手动下载压缩文件(.tar.gz) zlib-1.2.7.tar.gz openssl-1.0.1j.tar.gz openssh-6.0p1.tar.gz 2.安装zlib ...

  4. codeforces #313 div1 E

    首先我们要注意到一个事情 如果一个灯塔向左覆盖,那么比他小的某个灯塔如果向左覆盖的端点大于当前塔向左覆盖的端点,他一定向右覆盖 对于当前灯塔向右覆盖也是同理 那么我们只需要记录当前覆盖到的端点就可以完 ...

  5. Servlet课程0424(二) 通过继承GenericServlet来开发Servlet

    //这是第二种开发servlet的方法(继承GernericServlet) package com.tsinghua; import javax.servlet.GenericServlet; im ...

  6. 用QT创建新风格: QStyle

    转贴: http://hi.baidu.com/yjj2008/blog/item/6cd4a1892ef0d4b60f2444a5.html 本文介绍了如何使用qt提供的接口来设计自己的GUI风格( ...

  7. Apache Tomcat下载、安装、配置图文教程

    本文已迁移到我的个人网站 http://www.wshunli.com 文章地址: http://www.wshunli.com/2016/03/19/Tomcat安装配置/ (整理截图.安装过程更加 ...

  8. linux 入门教程

    linux入门教程 搜索 Linux入门教程 前言 第一章 关于Linux的历史 第二章 图形界面还是命令窗口 第三章 Linux操作系统的安装 第四章 初步进入linux世界 第五章 Linux系统 ...

  9. [2015编程之美] 第一场C

    题目3 : 质数相关 时间限制:2000ms 单点时限:1000ms 内存限制:256MB 描述 两个数a和 b (a<b)被称为质数相关,是指a × p = b,这里p是一个质数.一个集合S被 ...

  10. 理解java reference

    Java世界泰山北斗级大作<Thinking In Java>切入Java就提出“Everything is Object”.在Java这个充满Object的世界中,reference是一 ...