由于Android具有良好的开源优势,可进行深度定制开发。 安卓系统市场应用比windows晚,虽然支持的应用不如windows系统多,但由于系统的免费开放性,众多软件厂商经过近几年的开发,已经有越来越多的应用加入进来,目前支持办公、教学、娱乐已经完全没有问题。因此,越来越多的行业接受并认可基于Android操作系统的设备。
目前市面上大多数工业控制设备开始采用Android系统了,然而这部分设备并没有搭载原生的NFC功能。随着近年来,NFC功能需求的兴起,很多行业需要一直可以支持Android系统的可接入Android设备并进行二次开发的 NFC读写器。因此, L3-U这款NFC读写器 应运而生。作为一款采用USB免驱 的NFC读写器,支持在windows、Android、linux等操作系统,免费提供基于上述各种系统的SDK,方便客户进行功能扩展和二次开发。
L3-U这款USB免驱动NFC读写器已经设计好了USB 驱动,用户在基于Android系统的设备上只有能获取USB HOST权限或者采用OTG传输就可以使用,无需安装额外驱动。如果你其它非标准的Android设备,需要提供设备我们进行编译驱动。以下为标准的具有USB HOST权限的设备接入NFC读写器的过程。供大家在进行NFC读写器二次开发过程中参考!
1、在项目中对AndroidManifest.xml文件进行配置,获取相关权限。
添加了这句代码,会使得在应用商店下载应用是过滤掉不支持NFC功能的设备。
这里声明了三种intent筛选条件,分别是action为
android.nfc.action.NDEF_DISCOVERED,
android.nfc.action.TECH_DISCOVERED,
android.nfc.action.TAG_DISCOVERED。
这一步可以帮助android系统内的NFC模块在扫描到一个NFC目标的时候寻找到我们的activity来进行交互。
android系统内的NFC模块在扫描到一个NFC目标后会通过以下几步来寻找到合适的处理NFC消息的activity。在这之前先介绍两个概念,1、Tag代表一个NFC目标,当android设备扫描到一个NFC目标的时候会将相关数据封装成一个Tag实例,通过Intent传递给合适的activity去做处理。2、TagTechnology表示NFC标签支持的技术,可以通过Tag的getTechList()获取。
Tag的分发步骤:
a、先看Tag中是否包含了系统支持的NDEF数据,如果包含则分发给注册了action为ACTION_NEDF_DISCOVERED的activity。
b、如果Tag中不包含系统支持的NDEF数据或者没有找到注册了action为ACTION_NDEF_DISCOVERED的activity,则NFC系统模块尝试分发给一个action为ACTION_TECH_DISCOVERED的activity。NFC系统模块在分发是首先分析NFC Tag支持的Tag Technology,然后寻找支持这类Tag Technology的activity,然后封装了Tag数据的Intent分发给对应的activity。
c、如果上面两种都不满足,则发送action为ACTION_TAG_DISCOVERED的intent
2、建立一个Activity页面,用于实现NFC读写的功能。NFC读写功能实现的代码如下:
package cc.lotusnfc;
import java.io.IOException;
import java.nio.charset.Charset;
import java.sql.Date;
import java.text.SimpleDateFormat;
import java.util.Arrays;
import cc.lotusnfc.R;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
import android.nfc.tech.NfcA;
import android.os.Bundle;
import android.os.Parcelable;
import android.annotation.SuppressLint;
import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.view.Menu;
import android.view.View;
import android.widget.Button;
import android.widget.EditText;
import android.widget.TextView;
import android.widget.Toast;
public class MainActivity extends Activity {
private TextView resultText;
private PendingIntent pendingIntent;
private IntentFilter[] mFilters;
private String[][] mTechLists;
private Button mJumpTagBtn;
private boolean isFirst = true;
private NfcAdapter m_NfcAdpater;
private EditText m_edtLog;
private Intent m_NfcIntent = null;
@Override
protected void onCreate(Bundle savedInstanceState) {
// 获取nfc适配器,判断设备是否支持NFC功能
m_NfcAdpater = NfcAdapter.getDefaultAdapter(this);
if (m_NfcAdpater == null) {
Toast.makeText(this, "Not Found NfcAdapter!", Toast.LENGTH_SHORT)
.show();
//finish();
//return;
} else if (!m_NfcAdpater.isEnabled()) {
Toast.makeText(this, "Please Enabled NfcAdapter",
Toast.LENGTH_SHORT).show();
//finish();
//return;
}
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
m_edtLog = (EditText) findViewById(R.id.edtLog);
m_edtLog.setText("");
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
ndef.addCategory("*/*");
mFilters = new IntentFilter[] { ndef };// 过滤器
mTechLists = new String[][] {
new String[] { MifareClassic.class.getName() },
new String[] { NfcA.class.getName() } };// 允许扫描的标签类型
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate the menu; this adds items to the action bar if it is present.
getMenuInflater().inflate(R.menu.main, menu);
return true;
}
@SuppressLint("NewApi")
@Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
m_NfcAdpater.enableForegroundDispatch(this, pendingIntent, mFilters,
mTechLists);
}
private NdefMessage createMessage(String text) {
NdefRecord[] record = new NdefRecord[1];
String lang = "en";
byte[] langBytes = lang.getBytes(Charset.forName("US-ASCII"));
byte[] textBytes = text.getBytes(Charset.forName("UTF-8"));
char status = (char) (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);
record[0] = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], data);
return new NdefMessage(record);
}
@Override
protected void onNewIntent(Intent intent) {
// TODO Auto-generated method stub
super.onNewIntent(intent);
m_NfcIntent = intent;
String strWriteText = "春眠不觉晓";
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef ndef = Ndef.get(tagFromIntent);
if (ndef != null) {
NdefMessage ndefMessage = createMessage(strWriteText);
try {
ndef.connect();
// READ
NdefMessage msg = ndef.getNdefMessage();
if(null == msg) return;
NdefRecord[] records = msg.getRecords();
// NdefMessage nmsg = (NdefMessage) msgs[0];
NdefRecord record = records[0];
String resultStr = "";
if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN) {
if (Arrays
.equals(record.getType(), NdefRecord.RTD_TEXT)) {
byte[] payload = record.getPayload();
if (payload == null)
return;
try {
String textEString = ((payload[0] & 0x80) == 0) ? "UTF-8"
: "UTF-16";
int languageCodeLength = payload[0] & 0x3f;
resultStr = new String(payload,
languageCodeLength + 1, payload.length
- languageCodeLength - 1,
textEString);
AddLog("Read:" + resultStr);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// WRITE
ndef.writeNdefMessage(ndefMessage);
AddLog("WRITE:" + strWriteText);
ndef.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
AddLog("IOException" );
} catch (FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
AddLog("FormatException" );
}
}
}
}
private void AddLog(String strLog) {
SimpleDateFormat formatter = new SimpleDateFormat("HH:mm:ss");
Date curDate = new Date(System.currentTimeMillis());// 获取当前时间
String strDate = formatter.format(curDate);
if (null == m_edtLog)
return;
String strLogs = m_edtLog.getText().toString().trim();
if (strLogs.equals("")) {
strLogs = strDate + " " + strLog;
} else {
strLogs += "\r\n" + strDate + " " + strLog;
}
m_edtLog.setText(strLogs);
}
public void OnClearLogListener(View arg0) {
if (null == m_edtLog)
return;
m_edtLog.setText("");
}
public void OnSetNfcListener(View arg0) {
startActivityForResult(new Intent(
android.provider.Settings.ACTION_WIRELESS_SETTINGS), 0);
}
public void OnTestListener(View arg0) {
String strWriteText = "春眠不觉晓";
if(null == m_NfcIntent) return;
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(m_NfcIntent.getAction())) {
Tag tagFromIntent = m_NfcIntent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef ndef = Ndef.get(tagFromIntent);
if (ndef != null) {
NdefMessage ndefMessage = createMessage(strWriteText);
try {
ndef.connect();
// READ
NdefMessage msg = ndef.getNdefMessage();
NdefRecord[] records = msg.getRecords();
// NdefMessage nmsg = (NdefMessage) msgs[0];
NdefRecord record = records[0];
String resultStr = "";
if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN) {
if (Arrays
.equals(record.getType(), NdefRecord.RTD_TEXT)) {
byte[] payload = record.getPayload();
if (payload == null)
return;
try {
String textEString = ((payload[0] & 0x80) == 0) ? "UTF-8"
: "UTF-16";
int languageCodeLength = payload[0] & 0x3f;
resultStr = new String(payload,
languageCodeLength + 1, payload.length
- languageCodeLength - 1,
textEString);
AddLog("Read:" + resultStr);
} catch (Exception e) {
e.printStackTrace();
}
}
}
// WRITE
ndef.writeNdefMessage(ndefMessage);
AddLog("WRITE:" + strWriteText);
ndef.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (FormatException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
}