androidstudio基于bmob平台实现NFC读合法卡/非法卡、写卡功能
一、Java文件
package com.example.smartcommunityv2;
import androidx.annotation.RequiresApi;
import androidx.appcompat.app.AppCompatActivity;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.PendingIntent;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.nfc.tech.NfcA;
import android.os.Build;
import android.os.Bundle;
import android.os.Parcelable;
import android.provider.Settings;
import android.widget.EditText;
import android.widget.Toast;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;
import java.util.Locale;
import cn.bmob.v3.Bmob;
import cn.bmob.v3.BmobQuery;
import cn.bmob.v3.BmobUser;
import cn.bmob.v3.exception.BmobException;
import cn.bmob.v3.listener.QueryListener;
import cn.bmob.v3.listener.SaveListener;
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
public class realnfcmain extends AppCompatActivity {
private EditText nfcdata ;
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_realnfcmain);
Bmob.initialize(this, "992f7d755c2df83e885dade0f4d892c6");
// NfcUtils nfcUtils = new NfcUtils(this);
}
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
@Override
protected void onResume() {
super.onResume();
//设定intentfilter和tech-list。如果两个都为null就代表优先接收任何形式的TAG action。也就是说系统会主动发TAG intent。
if (mNfcAdapter != null) {
mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, mIntentFilter, mTechList);
}
}
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
@Override
protected void onPause() {
super.onPause();
if (mNfcAdapter != null) {
mNfcAdapter.disableForegroundDispatch(this);
}
}
@Override
protected void onDestroy() {
super.onDestroy();
mNfcAdapter = null;
}
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
readWrite(intent);
}
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
public void readWrite(Intent intent) {
nfcdata = findViewById(R.id.nfcdata);
String data2 = nfcdata.getText().toString();
try {
// 检测卡的id
String id = readNFCId(intent);
// NfcUtils中获取卡中数据的方法
String result = readNFCFromTag(intent);
BmobQuery bmobuser = new BmobQuery<>();
bmobuser.getObject(result, new QueryListener() {
@Override
public void done(BmobUser bmobuser, BmobException e) {
if (e == null) {
Toast.makeText(realnfcmain.this,"门禁已开",Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(realnfcmain.this,"警告,请使用合法卡",Toast.LENGTH_SHORT).show();
}
}
});
if(nfcdata.getText().toString().length() != 0){
// 往卡中写数据
writeNFCToTag(this,data2,intent);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
} catch (FormatException e) {
e.printStackTrace();
}
}
public static NfcAdapter mNfcAdapter;
public static IntentFilter[] mIntentFilter = null;
public static PendingIntent mPendingIntent = null;
public static String[][] mTechList = null;
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
public void NfcUtils(Activity activity) {
mNfcAdapter = NfcCheck(activity);
NfcInit(activity);
}
public static void readNFCFromTag() {
}
/**
* 检查NFC是否打开
*/
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
public NfcAdapter NfcCheck(Activity activity) {
NfcAdapter mNfcAdapter = NfcAdapter.getDefaultAdapter(activity);
if (mNfcAdapter == null) {
Toast.makeText(this,"设备不支持NFC功能!",Toast.LENGTH_SHORT).show();
return null;
} else {
if (!mNfcAdapter.isEnabled()) {
IsToSet(activity);
} else {
Toast.makeText(this,"NFC功能已打开!",Toast.LENGTH_SHORT).show();
}
}
return mNfcAdapter;
}
/**
* 初始化nfc设置
*/
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
public static void NfcInit(Activity activity) {
Intent intent = new Intent(activity, activity.getClass());
intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
mPendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);
//做一个IntentFilter过滤你想要的action 这里过滤的是ndef
IntentFilter filter = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
filter.addDataType("*/*");
} catch (IntentFilter.MalformedMimeTypeException e) {
e.printStackTrace();
}
mTechList = new String[][]{{MifareClassic.class.getName()},
{NfcA.class.getName()}};
//生成intentFilter
mIntentFilter = new IntentFilter[]{filter};
}
/**
* 读取NFC的数据
*/
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
public String readNFCFromTag(Intent intent) throws UnsupportedEncodingException {
Parcelable[] rawArray = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawArray != null) {
NdefMessage mNdefMsg = (NdefMessage) rawArray[0];
NdefRecord mNdefRecord = mNdefMsg.getRecords()[0];
if (mNdefRecord != null) {
return parseTextRecord(mNdefRecord);
}
}
return "";
}
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
public void writeNFCToTag(Context context, String data, Intent intent) throws IOException, FormatException {
NdefRecord ndefRecord = null;
ndefRecord=createTextRecord(data);
NdefRecord[] records = {ndefRecord};
NdefMessage ndefMessage = new NdefMessage(records);
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
Ndef ndef = Ndef.get(tag);
if(ndef==null){
NdefFormatable format = NdefFormatable.get(tag);
format.connect();
format.format(ndefMessage);
if(format.isConnected()){
format.close();
}
return;
}
ndef.connect();
if(!ndef.isWritable()){
Toast.makeText(this,"当前设备不支持写入",Toast.LENGTH_SHORT).show();
return;
}
//判断大小
ndef.writeNdefMessage(ndefMessage);
if(ndef.isConnected()){
ndef.close();
}
Toast.makeText(this,"读写完毕",Toast.LENGTH_SHORT).show();
}
/**
* 读取nfcID
*/
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD_MR1)
public static String readNFCId(Intent intent) throws UnsupportedEncodingException {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
String id = ByteArrayToHexString(tag.getId());
return id;
}
private static String ByteArrayToHexString(byte[] inarray) {
int i, j, in;
String[] hex = {"0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};
String out = "";
for (j = 0; j < inarray.length; ++j) {
in = (int) inarray[j] & 0xff;
i = (in >> 4) & 0x0f;
out += hex[i];
i = in & 0x0f;
out += hex[i];
}
return out;
}
private static void IsToSet(final Activity activity) {
AlertDialog.Builder builder = new AlertDialog.Builder(activity);
builder.setMessage("是否跳转到设置页面打开NFC功能");
builder.setTitle("提示");
builder.setPositiveButton("确认", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
goToSet(activity);
dialog.dismiss();
}
});
builder.setNegativeButton("取消", new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
dialog.dismiss();
}
});
builder.create().show();
}
private static void goToSet(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.BASE) {
// 进入设置系统应用权限界面
Intent intent = new Intent(Settings.ACTION_SETTINGS);
activity.startActivity(intent);
return;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {// 运行系统在5.x环境使用
// 进入设置系统应用权限界面
Intent intent = new Intent(Settings.ACTION_SETTINGS);
activity.startActivity(intent);
return;
}
}
/**
* 创建NDEF文本数据
* @param text
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
public static NdefRecord createTextRecord(String text) {
byte[] langBytes = Locale.CHINA.getLanguage().getBytes(Charset.forName("US-ASCII"));
Charset utfEncoding = Charset.forName("UTF-8");
//将文本转换为UTF-8格式
byte[] textBytes = text.getBytes(utfEncoding);
//设置状态字节编码最高位数为0
int utfBit = 0;
//定义状态字节
char status = (char) (utfBit + langBytes.length);
byte[] data = new byte[1 + langBytes.length + textBytes.length];
//设置第一个状态字节,先将状态码转换成字节
data[0] = (byte) status;
//设置语言编码,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1到langBytes.length的位置
System.arraycopy(langBytes, 0, data, 1, langBytes.length);
//设置文本字节,使用数组拷贝方法,从0开始拷贝到data中,拷贝到data的1 + langBytes.length
//到textBytes.length的位置
System.arraycopy(textBytes, 0, data, 1 + langBytes.length, textBytes.length);
//通过字节传入NdefRecord对象
//NdefRecord.RTD_TEXT:传入类型 读写
NdefRecord ndefRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], data);
return ndefRecord;
}
/**
* 解析NDEF文本数据,从第三个字节开始,后面的文本数据
* @param ndefRecord
* @return
*/
@RequiresApi(api = Build.VERSION_CODES.GINGERBREAD)
public String parseTextRecord(NdefRecord ndefRecord) {
/**
* 判断数据是否为NDEF格式
*/
//判断TNF
if (ndefRecord.getTnf() != NdefRecord.TNF_WELL_KNOWN) {
return null;
}
//判断可变的长度的类型
if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
return null;
}
try {
//获得字节数组,然后进行分析
byte[] payload = ndefRecord.getPayload();
//下面开始NDEF文本数据第一个字节,状态字节
//判断文本是基于UTF-8还是UTF-16的,取第一个字节"位与"上16进制的80,16进制的80也就是最高位是1,
//其他位都是0,所以进行"位与"运算后就会保留最高位
String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" : "UTF-16";
// LogUtils.e("parseTextRecord() textEncoding="+textEncoding);
//3f最高两位是0,第六位是1,所以进行"位与"运算后获得第六位
int languageCodeLength = payload[0] & 0x3f;
//下面开始NDEF文本数据第二个字节,语言编码
//获得语言编码
String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
// LogUtils.e("parseTextRecord() languageCode="+languageCode);
//下面开始NDEF文本数据后面的字节,解析出文本
String textRecord = new String(payload, languageCodeLength + 1,
payload.length - languageCodeLength - 1, textEncoding);
Toast.makeText(this,textRecord,Toast.LENGTH_LONG).show();
return textRecord;
} catch (Exception e) {
throw new IllegalArgumentException();
}
}
}
二、XML文件
三、配置
四、演示图片
读取合法卡
开启门
读取非法卡
无法开启门禁
写卡
再次读卡