Android NFC开发之写入NDEF格式Uri数据

首先在AndroidManifest.xml文件中添加如下配置






创建一个NFC处理的基类

public class BaseNfcActivity extends AppCompatActivity {
    private NfcAdapter mNfcAdapter;
    private PendingIntent mPendingIntent;

    @Override
    protected void onStart() {
        super.onStart();
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        // 用于感应到NFC时启动该Activity
        // 这里建议将处理NFC的子类的launchMode设置成singleTop模式,这样感应到标签时就会回调onNewIntent,而不会重复打开页面
        mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()), 0);
    }
    /**
     * 获得焦点,按钮可以点击
     */
    @Override
    public void onResume() {
        super.onResume();
        // 设置当该页面处于前台时,NFC标签会直接交给该页面处理
        if (mNfcAdapter != null) {
            mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
        }
    }
    /**
     * 暂停Activity,界面获取焦点,按钮可以点击
     */
    @Override
    public void onPause() {
        super.onPause();
        // 当页面不可见时,NFC标签不交给当前页面处理
        if (mNfcAdapter != null) {
            mNfcAdapter.disableForegroundDispatch(this);
        }
    }
}

再创建一个Uri前缀查询解析的类

public class UriPrefixMap {
    public static final Map URI_PREFIX_MAP = new HashMap();
    static {
        URI_PREFIX_MAP.put((byte) 0x00, "");
        URI_PREFIX_MAP.put((byte) 0x01, "http://www.");
        URI_PREFIX_MAP.put((byte) 0x02, "https://www.");
        URI_PREFIX_MAP.put((byte) 0x03, "http://");
        URI_PREFIX_MAP.put((byte) 0x04, "https://");
        URI_PREFIX_MAP.put((byte) 0x05, "tel:");
        URI_PREFIX_MAP.put((byte) 0x06, "mailto:");
        URI_PREFIX_MAP.put((byte) 0x07, "ftp://anonymous:anonymous@");
        URI_PREFIX_MAP.put((byte) 0x08, "ftp://ftp.");
        URI_PREFIX_MAP.put((byte) 0x09, "ftps://");
        URI_PREFIX_MAP.put((byte) 0x0A, "sftp://");
        URI_PREFIX_MAP.put((byte) 0x0B, "smb://");
        URI_PREFIX_MAP.put((byte) 0x0C, "nfs://");
        URI_PREFIX_MAP.put((byte) 0x0D, "ftp://");
        URI_PREFIX_MAP.put((byte) 0x0E, "dav://");
        URI_PREFIX_MAP.put((byte) 0x0F, "news:");
        URI_PREFIX_MAP.put((byte) 0x10, "telnet://");
        URI_PREFIX_MAP.put((byte) 0x11, "imap:");
        URI_PREFIX_MAP.put((byte) 0x12, "rtsp://");
        URI_PREFIX_MAP.put((byte) 0x13, "urn:");
        URI_PREFIX_MAP.put((byte) 0x14, "pop:");
        URI_PREFIX_MAP.put((byte) 0x15, "sip:");
        URI_PREFIX_MAP.put((byte) 0x16, "sips:");
        URI_PREFIX_MAP.put((byte) 0x17, "tftp:");
        URI_PREFIX_MAP.put((byte) 0x18, "btspp://");
        URI_PREFIX_MAP.put((byte) 0x19, "btl2cap://");
        URI_PREFIX_MAP.put((byte) 0x1A, "btgoep://");
        URI_PREFIX_MAP.put((byte) 0x1B, "tcpobex://");
        URI_PREFIX_MAP.put((byte) 0x1C, "irdaobex://");
        URI_PREFIX_MAP.put((byte) 0x1D, "file://");
        URI_PREFIX_MAP.put((byte) 0x1E, "urn:epc:id:");
        URI_PREFIX_MAP.put((byte) 0x1F, "urn:epc:tag:");
        URI_PREFIX_MAP.put((byte) 0x20, "urn:epc:pat:");
        URI_PREFIX_MAP.put((byte) 0x21, "urn:epc:raw:");
        URI_PREFIX_MAP.put((byte) 0x22, "urn:epc:");
        URI_PREFIX_MAP.put((byte) 0x23, "urn:nfc:");
    }
}

然后创建一个NFC写标的类WriteTagUriActivity,继承BaseNfcActivity

public class WriteTagUriActivity extends BaseNfcActivity {

    private TextView mContent;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_write_tag_uri);

        mContent = findViewById(R.id.content);
    }
    public void onNewIntent(Intent intent) {
        String content = mContent.getText().toString().trim();
        if (TextUtils.isEmpty(content)) {
            Toast.makeText(this, "请输入待写入的数据", Toast.LENGTH_SHORT).show();
            return;
        }
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        NdefMessage msg = new NdefMessage(new NdefRecord[]{createRecord(content)});
        boolean result = writeTag(msg, tag);
        if (result){
            Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show();
        } else {
            Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show();
        }
    }

    public static NdefRecord createRecord(String uriStr) {
        byte prefix = 0;
        for (Byte b : UriPrefixMap.URI_PREFIX_MAP.keySet()) {
            String prefixStr = UriPrefixMap.URI_PREFIX_MAP.get(b).toLowerCase();
            if (uriStr.toLowerCase().startsWith(prefixStr)) {
                prefix = b; // 前缀
                uriStr = uriStr.substring(prefixStr.length()); // 剩余内容
                break;
            }
        }
        byte[] data = new byte[1 + uriStr.length()];
        data[0] = prefix; // 第一个字节为前缀识别码
        System.arraycopy(uriStr.getBytes(), 0, data, 1, uriStr.length());
        // 注意写Uri格式数据,前两个参数固定为NdefRecord.TNF_WELL_KNOWN和NdefRecord.RTD_URI
        NdefRecord record = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0], data);
        return record;
    }

    public static boolean writeTag(NdefMessage msg, Tag tag) {
        try {
            int size = msg.toByteArray().length;
            Ndef ndef = Ndef.get(tag);
            if (ndef == null) {
                return false;
            }
            ndef.connect();
            if (!ndef.isWritable()) {
                return false;
            }
            if (ndef.getMaxSize() < size) {
                return false;
            }
            ndef.writeNdefMessage(msg);
            return true;
        } catch (Exception e) {
            e.printStackTrace();
        }
        return false;
    }
}

布局文件很简单,就一个输入框输入自定义写入的内容



    

最后记得把WriteTagUriActivity的启动模式设置成singleTop


    
        
        
    

测试

  1. 首先准备一台支持NFC功能的手机,打开我们写好的应用,在输入框中输入要写入的内容,比如https://www.himmy.cn
  2. 准备一张NFC标签,靠近手机NFC读取区域(一般在背部)
  3. 写标成功后会提示“写入成功”

你可能感兴趣的:(NFC)