You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

350 lines
12 KiB
Java

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

package com.rehome.dywoa;
import static com.rehome.dywoa.utils.NfcUtil.stringsToBytes;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.pm.ApplicationInfo;
import android.nfc.FormatException;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.IsoDep;
import android.nfc.tech.MifareClassic;
import android.nfc.tech.MifareUltralight;
import android.nfc.tech.Ndef;
import android.nfc.tech.NdefFormatable;
import android.nfc.tech.NfcA;
import android.nfc.tech.NfcB;
import android.nfc.tech.NfcF;
import android.nfc.tech.NfcV;
import android.os.Parcelable;
import android.text.TextUtils;
import android.util.Log;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import com.rehome.dywoa.utils.NfcUtil;
import org.json.JSONException;
import org.json.JSONObject;
import java.util.Arrays;
import java.util.Objects;
/**
* Description:
* 子类在onNewIntent方法中进行NFC标签相关操作。
* launchMode设置为singleTop或singelTask保证Activity的重用唯一
* 在onNewIntent方法中执行intent传递过来的Tag数据
* 将NFC标签卡靠近手机后部NFC标签卡可网上自行购买
*/
public class BaseNfcActivity extends AppCompatActivity {
private NfcAdapter nfcAdapter;
private String readResult = "";
private PendingIntent pendingIntent;
private IntentFilter[] mFilters;
private String[][] mTechLists;
private boolean isFirst = true;
private IntentFilter ndef;
Tag mTag;
Tag getTagHandle() {
return mTag;
}
/**
* 检测工作,判断设备的NFC支持情况
*
* @return
*/
private Boolean ifNFCUse() {
if (nfcAdapter == null) {
Toast.makeText(this, "设备不支持NFC", Toast.LENGTH_SHORT).show();
return false;
}
if (!nfcAdapter.isEnabled()) {
Toast.makeText(this, "请在系统设置中先启用NFC功能", Toast.LENGTH_SHORT).show();
return false;
}
return true;
}
/**
* 初始化过程
*/
public void initNFC() {
//NFC适配器所有的关于NFC的操作从该适配器进行
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (!ifNFCUse()) {
return;
}
//将被调用的Intent用于重复被Intent触发后将要执行的跳转
if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.S) {
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE | PendingIntent.FLAG_UPDATE_CURRENT);
} else {
pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_UPDATE_CURRENT);
}
//设定要过滤的标签动作这里只接收ACTION_NDEF_DISCOVERED类型
ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
ndef.addCategory("*/*");
mFilters = new IntentFilter[]{ndef};// 过滤器
mTechLists = new String[][]{new String[]{NfcA.class.getName()},
new String[]{NfcF.class.getName()},
new String[]{NfcB.class.getName()},
new String[]{NfcV.class.getName()},
new String[]{MifareClassic.class.getName()},
new String[]{MifareUltralight.class.getName()},
new String[]{IsoDep.class.getName()}};// 允许扫描的标签类型
if (isFirst) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent()
.getAction())) {
ndef = new IntentFilter();
if (readFromTag(getIntent())) {
Toast.makeText(this, readResult, Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "标签数据为空", Toast.LENGTH_SHORT).show();
}
}
isFirst = false;
}
}
private String ByteArrayToHexString(byte[] inarray) { //converts byte arrays to string
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;
}
@Override
protected void onPause() {
super.onPause();
if (nfcAdapter != null) {
nfcAdapter.disableForegroundDispatch(this);
}
}
/*
* 重写onResume回调函数的意义在于处理多次读取NFC标签时的情况
*/
@Override
protected void onResume() {
super.onResume();
//设置强制竖屏
// setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
// 前台分发系统,这里的作用在于第二次检测NFC标签时该应用有最高的捕获优先权.
if (nfcAdapter != null && pendingIntent != null && mFilters != null && mTechLists != null) {
nfcAdapter.enableForegroundDispatch(this, pendingIntent, mFilters,
mTechLists);
}
}
/*
* 有必要要了解onNewIntent回调函数的调用时机,请自行上网查询
*/
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()) ||
NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
String id = ByteArrayToHexString(Objects.requireNonNull(intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)));
if (readFromTag(intent)) {
// Toast.makeText(this, readResult, Toast.LENGTH_SHORT).show();
handleNfc(readResult, null);
} else {
Toast.makeText(this, "ID:" + id + " 标签数据为空", Toast.LENGTH_SHORT).show();
}
}
}
private JSONObject ndef2Html(Ndef ndef, Parcelable[] messages) {
return buildNdefJSON(ndef, messages);
}
JSONObject buildNdefJSON(Ndef ndef, Parcelable[] messages) {
JSONObject json = NfcUtil.ndefToJSON(ndef);
if (messages != null) {
try {
if (messages.length == 1) {
NdefMessage message = (NdefMessage) messages[0];
json.put("ndefMessage", NfcUtil.messageToJSON(message));
json.put("type", "NDEF");
}
} catch (JSONException e) {
Log.e("BaseNfcActivity", "Failed to convert ndefMessage into json", e);
}
}
return json;
}
public void getNdefMessage(Intent intent) {
synchronized (this) {
try {
String action = intent.getAction();
if (action != null) {
Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (detectedTag != null) {
mTag = detectedTag;
}
}
Ndef ndef = Ndef.get(getTagHandle());
Parcelable[] message = new NdefMessage[] {ndef.getNdefMessage()};
handleNfc(String.valueOf(ndef2Html(ndef, message)), null);
} catch (Exception exception) {
Log.d("BaseNfcActivity", exception.toString());
handleNfc(null, exception.toString());
}
}
}
/**
* 读取NFC标签数据的操作
*/
private boolean readFromTag(Intent intent) {
String action = intent.getAction();
if (action == null) {
return false;
}
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag == null) {
return false;
}
mTag = tag;
Ndef ndef;
switch (action) {
case NfcAdapter.ACTION_NDEF_DISCOVERED -> {
ndef = Ndef.get(tag);
Parcelable[] message = intent.getParcelableArrayExtra((NfcAdapter.EXTRA_NDEF_MESSAGES));
readResult = String.valueOf(ndef2Html(ndef, message));
}
case NfcAdapter.ACTION_TECH_DISCOVERED -> {
if (Arrays.asList(tag.getTechList()).contains(Ndef.class.getName())) {
ndef = Ndef.get(tag);
readResult = String.valueOf(ndef2Html(ndef, new NdefMessage[]{ndef.getCachedNdefMessage()}));
} else {
Log.i("app ACTION_TECH_DISCOVERED 2", String.valueOf(tag));
}
}
}
return readResult != null;
}
//处理NFC
public void handleNfc(String result, String errorMessage) {
//showToast(result);
//Toast.makeText(this, result, Toast.LENGTH_LONG).show();
}
public void showLog(String logText) {
if (isApkInDebug(BaseNfcActivity.this)) {
if(TextUtils.isEmpty(logText)){
Log.i("app", "logText is null");
}else{
Log.i("app", logText);
}
}
}
/**
* 判断当前应用是否是debug状态
*/
public static boolean isApkInDebug(Context context) {
try {
ApplicationInfo info = context.getApplicationInfo();
return (info.flags & ApplicationInfo.FLAG_DEBUGGABLE) != 0;
} catch (Exception e) {
return false;
}
}
/**
* 显示toast
*
* @param text
*/
public void showToast(String text) {
if (text != null && !text.trim().equals("")) {
Toast.makeText(this, text, Toast.LENGTH_SHORT).show();
}
}
/**
* 往标签写数据的方法
*/
public void writeNFCTag(String command) throws FormatException, JSONException {
if (mTag == null) {
return;
}
NdefMessage ndefMessage = new NdefMessage(stringsToBytes(command));
//转换成字节获得大小
int size = ndefMessage.toByteArray().length;
try {
//2.判断NFC标签的数据类型通过Ndef.get方法
Ndef ndef = Ndef.get(getTagHandle());
//判断是否为NDEF标签
if (ndef != null) {
ndef.connect();
//判断是否支持可写
if (!ndef.isWritable()) {
return;
}
//判断标签的容量是否够用
if (ndef.getMaxSize() < size) {
return;
}
//3.写入数据
ndef.writeNdefMessage(ndefMessage);
Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show();
ndef.close();
ndef.connect();
} else { //当我们买回来的NFC标签是没有格式化的或者没有分区的执行此步
//Ndef格式类
NdefFormatable format = NdefFormatable.get(mTag);
//判断是否获得了NdefFormatable对象有一些标签是只读的或者不允许格式化的
if (format != null) {
//连接
format.connect();
//格式化并将信息写入标签
format.format(ndefMessage);
Toast.makeText(this, "写入成功",
Toast.LENGTH_SHORT).show();
} else {
Toast.makeText(this, "写入失败", Toast.LENGTH_SHORT).show();
}
}
} catch (Exception e) {
}
}
}