读取nfc数据和写入数据
This commit is contained in:
@@ -5,11 +5,13 @@
|
||||
<!--NFC权限-->
|
||||
<uses-permission android:name="android.permission.NFC" />
|
||||
<!--声明只有带NFC的手机才可以下载-->
|
||||
<uses-feature android:name="android.hardware.nfc" android:required="true" />
|
||||
|
||||
<uses-feature
|
||||
android:name="android.hardware.nfc"
|
||||
android:required="true" />
|
||||
|
||||
|
||||
<application
|
||||
android:name=".base.BaseApplication"
|
||||
android:allowBackup="true"
|
||||
android:icon="@mipmap/ic_launcher"
|
||||
android:label="@string/app_name"
|
||||
@@ -24,28 +26,39 @@
|
||||
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
</intent-filter>
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activity.nfc.NfcActivity"
|
||||
android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" />
|
||||
</intent-filter>
|
||||
<intent-filter>
|
||||
<action android:name="android.nfc.action.TECH_DISCOVERED" />
|
||||
<category android:name="android.intent.category.DEFAULT" />
|
||||
<data android:mimeType="text/plain" /> <!-- 指定数据类型 -->
|
||||
</intent-filter>
|
||||
|
||||
<meta-data
|
||||
android:name="android.nfc.action.TECH_DISCOVERED"
|
||||
android:resource="@xml/nfc_tech_filter" />
|
||||
</activity>
|
||||
|
||||
<activity
|
||||
android:name=".activity.nfc.NfcActivity"
|
||||
android:exported="true"
|
||||
android:launchMode="singleTop">
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <action android:name="android.nfc.action.NDEF_DISCOVERED" />-->
|
||||
<!-- <category android:name="android.intent.category.DEFAULT" />-->
|
||||
<!-- <data android:mimeType="text/plain" />-->
|
||||
<!-- </intent-filter>-->
|
||||
<!-- <intent-filter>-->
|
||||
<!-- <action android:name="android.nfc.action.TECH_DISCOVERED" />-->
|
||||
<!-- </intent-filter>-->
|
||||
|
||||
<!-- <meta-data-->
|
||||
<!-- android:name="android.nfc.action.TECH_DISCOVERED"-->
|
||||
<!-- android:resource="@xml/nfc_tech_filter" />-->
|
||||
</activity>
|
||||
|
||||
<service
|
||||
android:name="com.google.android.accessibility.selecttospeak.SelectToSpeakService"
|
||||
android:label="@string/accessibility_service_label"
|
||||
android:exported="true"
|
||||
android:label="@string/accessibility_service_label"
|
||||
android:permission="android.permission.BIND_ACCESSIBILITY_SERVICE">
|
||||
|
||||
<!-- android:priority="10000" 可提高服务在设置中的权重,排在前面 -->
|
||||
@@ -58,7 +71,12 @@
|
||||
android:resource="@xml/accessibility_service_config" />
|
||||
</service>
|
||||
|
||||
|
||||
<meta-data
|
||||
android:name="design_width_in_dp"
|
||||
android:value="360" />
|
||||
<meta-data
|
||||
android:name="design_height_in_dp"
|
||||
android:value="640" />
|
||||
</application>
|
||||
|
||||
</manifest>
|
||||
@@ -1,16 +1,127 @@
|
||||
package com.ttstd.elderlyassistant.activity.main;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.app.PendingIntent;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.content.IntentFilter;
|
||||
import android.nfc.NdefMessage;
|
||||
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.NfcF;
|
||||
import android.os.Bundle;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
|
||||
import com.ttstd.elderlyassistant.R;
|
||||
import com.ttstd.elderlyassistant.activity.nfc.NfcActivity;
|
||||
import com.ttstd.elderlyassistant.databinding.ActivityMainBinding;
|
||||
|
||||
public class MainActivity extends AppCompatActivity {
|
||||
private static final String TAG = "MainActivity";
|
||||
|
||||
private ActivityMainBinding mBinding;
|
||||
|
||||
private NfcManager mNfcManager;
|
||||
private NfcAdapter mNfcAdapter;
|
||||
private Tag mTag;
|
||||
private PendingIntent pendingIntent;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_main);
|
||||
// setContentView(R.layout.activity_main);
|
||||
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_main);
|
||||
mBinding.setClick(new BtnClick());
|
||||
|
||||
|
||||
mNfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE);
|
||||
if (mNfcManager == null) {
|
||||
// 设备不支持 NFC
|
||||
Toast.makeText(this, "设备不支持 NFC", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
mNfcAdapter = mNfcManager.getDefaultAdapter();
|
||||
if (mNfcAdapter == null) {
|
||||
// 设备不支持 NFC
|
||||
Toast.makeText(this, "设备不支持 NFC", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
// 创建 PendingIntent 捕获 NFC 事件
|
||||
pendingIntent = PendingIntent.getActivity(
|
||||
this, 0,
|
||||
new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
|
||||
PendingIntent.FLAG_IMMUTABLE
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onResume() {
|
||||
super.onResume();
|
||||
if (mNfcAdapter != null) {
|
||||
// 指定处理 TECH_DISCOVERED 类型标签
|
||||
IntentFilter[] filters = new IntentFilter[]{
|
||||
new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
|
||||
};
|
||||
String[][] techLists = new String[][]{
|
||||
{NfcF.class.getName(), MifareClassic.class.getName()}
|
||||
};
|
||||
mNfcAdapter.enableForegroundDispatch(this, pendingIntent, filters, techLists);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onPause() {
|
||||
super.onPause();
|
||||
if (mNfcAdapter != null) {
|
||||
mNfcAdapter.disableForegroundDispatch(this);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
Log.e(TAG, "onNewIntent: ");
|
||||
if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
|
||||
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
|
||||
if (tag != null) {
|
||||
// 获取 NFC ID (16 进制格式)
|
||||
byte[] idBytes = tag.getId();
|
||||
String tagId = bytesToHex(idBytes);
|
||||
|
||||
// 读取 NDEF 数据(如为文本标签)
|
||||
Ndef ndef = Ndef.get(tag);
|
||||
if (ndef != null) {
|
||||
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
|
||||
if (ndefMessage != null) {
|
||||
String payload = new String(ndefMessage.getRecords()[0].getPayload());
|
||||
Log.e(TAG, "onNewIntent: payload = " + payload);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 字节数组转 Hex 字符串
|
||||
private String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02X", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
public class BtnClick {
|
||||
public void wirteTag(View view) {
|
||||
startActivity(new Intent(MainActivity.this, NfcActivity.class));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,64 +1,183 @@
|
||||
package com.ttstd.elderlyassistant.activity.nfc;
|
||||
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
import android.nfc.NdefMessage;
|
||||
import android.nfc.NdefRecord;
|
||||
import android.nfc.NfcAdapter;
|
||||
import android.nfc.NfcManager;
|
||||
import android.nfc.Tag;
|
||||
import android.nfc.tech.Ndef;
|
||||
import android.os.Bundle;
|
||||
import android.os.Parcelable;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Log;
|
||||
import android.view.View;
|
||||
import android.widget.Toast;
|
||||
|
||||
import com.ttstd.elderlyassistant.R;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.databinding.DataBindingUtil;
|
||||
|
||||
import com.hjq.toast.Toaster;
|
||||
import com.ttstd.elderlyassistant.R;
|
||||
import com.ttstd.elderlyassistant.bean.Contact;
|
||||
import com.ttstd.elderlyassistant.databinding.ActivityNfcBinding;
|
||||
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.util.Arrays;
|
||||
import java.util.Locale;
|
||||
|
||||
import com.ttstd.elderlyassistant.gson.GsonUtils;
|
||||
|
||||
public class NfcActivity extends AppCompatActivity {
|
||||
private static final String TAG = "NfcActivity";
|
||||
|
||||
private ActivityNfcBinding mBinding;
|
||||
|
||||
private NfcManager mNfcManager;
|
||||
private NfcAdapter mNfcAdapter;
|
||||
private Tag mTag;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
setContentView(R.layout.activity_nfc);
|
||||
mBinding = DataBindingUtil.setContentView(this, R.layout.activity_nfc);
|
||||
// setContentView(R.layout.activity_nfc);
|
||||
mBinding.setClick(new BtnClick());
|
||||
|
||||
NfcManager manager = (NfcManager) getSystemService(Context.NFC_SERVICE);
|
||||
NfcAdapter nfcAdapter = manager.getDefaultAdapter();
|
||||
|
||||
if (nfcAdapter == null) {
|
||||
mNfcManager = (NfcManager) getSystemService(Context.NFC_SERVICE);
|
||||
if (mNfcManager == null) {
|
||||
// 设备不支持 NFC
|
||||
Toast.makeText(this, "设备不支持 NFC", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
mNfcAdapter = mNfcManager.getDefaultAdapter();
|
||||
if (mNfcAdapter == null) {
|
||||
// 设备不支持 NFC
|
||||
Toast.makeText(this, "设备不支持 NFC", Toast.LENGTH_SHORT).show();
|
||||
finish();
|
||||
}
|
||||
|
||||
Intent intent = getIntent();
|
||||
getMessageFromIntent(intent);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onNewIntent(Intent intent) {
|
||||
super.onNewIntent(intent);
|
||||
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
|
||||
Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
|
||||
if (rawMessages != null) {
|
||||
NdefMessage[] messages = new NdefMessage[rawMessages.length];
|
||||
for (int i = 0; i < rawMessages.length; i++) {
|
||||
messages[i] = (NdefMessage) rawMessages[i];
|
||||
getMessageFromIntent(intent);
|
||||
}
|
||||
|
||||
private void getMessageFromIntent(Intent intent) {
|
||||
String action = intent.getAction();
|
||||
Log.e(TAG, "getMessageFromIntent: action = " + action);
|
||||
switch (action) {
|
||||
case NfcAdapter.ACTION_NDEF_DISCOVERED:
|
||||
Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
|
||||
if (rawMessages != null) {
|
||||
NdefMessage[] messages = new NdefMessage[rawMessages.length];
|
||||
for (int i = 0; i < rawMessages.length; i++) {
|
||||
messages[i] = (NdefMessage) rawMessages[i];
|
||||
}
|
||||
// 处理 NDEF 消息
|
||||
processNdefMessages(messages);
|
||||
}
|
||||
// 处理 NDEF 消息
|
||||
processNdefMessages(messages);
|
||||
}
|
||||
break;
|
||||
case NfcAdapter.ACTION_TECH_DISCOVERED:
|
||||
mTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
|
||||
if (mTag != null) {
|
||||
// 获取 NFC ID (16 进制格式)
|
||||
byte[] idBytes = mTag.getId();
|
||||
String tagId = bytesToHex(idBytes);
|
||||
Log.e(TAG, "getMessageFromIntent: tagId = " + tagId);
|
||||
// 读取 NDEF 数据(如为文本标签)
|
||||
Ndef ndef = Ndef.get(mTag);
|
||||
if (ndef != null) {
|
||||
NdefMessage ndefMessage = ndef.getCachedNdefMessage();
|
||||
if (ndefMessage != null) {
|
||||
String payload = new String(ndefMessage.getRecords()[0].getPayload());
|
||||
Log.e(TAG, "getMessageFromIntent: payload = " + payload);
|
||||
} else {
|
||||
Log.e(TAG, "getMessageFromIntent: ndefMessage is null");
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// 字节数组转 Hex 字符串
|
||||
private String bytesToHex(byte[] bytes) {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
for (byte b : bytes) {
|
||||
sb.append(String.format("%02X", b));
|
||||
}
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
private void processNdefMessages(NdefMessage[] messages) {
|
||||
for (NdefMessage message : messages) {
|
||||
for (NdefRecord record : message.getRecords()) {
|
||||
if (record.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) {
|
||||
// 处理文本记录
|
||||
String text = new String(record.getPayload());
|
||||
Toast.makeText(this, "NFC 数据: " + text, Toast.LENGTH_SHORT).show();
|
||||
Toaster.show("NFC 数据: " + text);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void writeTag(String text, Tag tag) {
|
||||
try {
|
||||
NdefRecord record = createTextRecord(text, Locale.ENGLISH);
|
||||
NdefMessage message = new NdefMessage(new NdefRecord[]{record});
|
||||
|
||||
Ndef ndef = Ndef.get(tag);
|
||||
if (ndef != null) {
|
||||
ndef.connect();
|
||||
ndef.writeNdefMessage(message);
|
||||
Toaster.show("写入成功: ");
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Toaster.show("写入失败: " + e.getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
// 创建 NDEF 文本记录
|
||||
private NdefRecord createTextRecord(String text, Locale locale) {
|
||||
byte[] langBytes = locale.getLanguage().getBytes(StandardCharsets.US_ASCII);
|
||||
byte[] textBytes = text.getBytes(StandardCharsets.UTF_8);
|
||||
|
||||
byte[] payload = new byte[1 + langBytes.length + textBytes.length];
|
||||
payload[0] = (byte) langBytes.length; // 状态字节
|
||||
System.arraycopy(langBytes, 0, payload, 1, langBytes.length);
|
||||
System.arraycopy(textBytes, 0, payload, 1 + langBytes.length, textBytes.length);
|
||||
|
||||
return new NdefRecord(
|
||||
NdefRecord.TNF_WELL_KNOWN,
|
||||
NdefRecord.RTD_TEXT,
|
||||
new byte[0],
|
||||
payload
|
||||
);
|
||||
}
|
||||
|
||||
public class BtnClick {
|
||||
public void write(View view) {
|
||||
String name = mBinding.etName.getText().toString();
|
||||
String phone = mBinding.etPhone.getText().toString();
|
||||
if (TextUtils.isEmpty(name)) {
|
||||
Toaster.show("请输入联系人姓名");
|
||||
return;
|
||||
}
|
||||
if (TextUtils.isEmpty(phone)) {
|
||||
Toaster.show("请输入联系人手机号");
|
||||
return;
|
||||
}
|
||||
Contact contact = new Contact(name, phone);
|
||||
writeTag(GsonUtils.toJSONString(contact), mTag);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
package com.ttstd.elderlyassistant.base;
|
||||
|
||||
import android.app.Application;
|
||||
|
||||
import com.hjq.toast.Toaster;
|
||||
|
||||
public class BaseApplication extends Application {
|
||||
|
||||
@Override
|
||||
public void onCreate() {
|
||||
super.onCreate();
|
||||
Toaster.init(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTerminate() {
|
||||
super.onTerminate();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLowMemory() {
|
||||
super.onLowMemory();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTrimMemory(int level) {
|
||||
super.onTrimMemory(level);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
package com.ttstd.elderlyassistant.bean;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
public class Contact implements Serializable {
|
||||
private static final long serialVersionUID = -5570426400839799887L;
|
||||
|
||||
String name;
|
||||
String phone;
|
||||
String tag;
|
||||
/**
|
||||
* 0 电话 1 短信 2 微信语音 3 微信视频
|
||||
*/
|
||||
int defaultOperation;
|
||||
int version;
|
||||
|
||||
|
||||
public Contact() {
|
||||
|
||||
}
|
||||
|
||||
public Contact(String name, String phone) {
|
||||
this.name = name;
|
||||
this.phone = phone;
|
||||
this.defaultOperation = 3;
|
||||
this.version = 1;
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public void setName(String name) {
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
public String getPhone() {
|
||||
return phone;
|
||||
}
|
||||
|
||||
public void setPhone(String phone) {
|
||||
this.phone = phone;
|
||||
}
|
||||
|
||||
|
||||
public String getTag() {
|
||||
return tag;
|
||||
}
|
||||
|
||||
public void setTag(String tag) {
|
||||
this.tag = tag;
|
||||
}
|
||||
}
|
||||
144
app/src/main/java/com/ttstd/elderlyassistant/gson/GsonUtils.java
Normal file
144
app/src/main/java/com/ttstd/elderlyassistant/gson/GsonUtils.java
Normal file
@@ -0,0 +1,144 @@
|
||||
package com.ttstd.elderlyassistant.gson;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.google.gson.JsonArray;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonObject;
|
||||
import com.google.gson.JsonParser;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
|
||||
public class GsonUtils {
|
||||
//https://blog.csdn.net/zte1055889498/article/details/122400299
|
||||
|
||||
public static JsonObject getJsonObject(String jsonString) {
|
||||
JsonObject jsonObject = JsonParser.parseString(jsonString).getAsJsonObject();
|
||||
return jsonObject;
|
||||
}
|
||||
|
||||
private static final Gson gson;
|
||||
|
||||
static {
|
||||
GsonBuilder builder = new GsonBuilder();
|
||||
builder.registerTypeAdapterFactory(new NullStringToEmptyAdapterFactory());
|
||||
builder.registerTypeAdapter(Integer.class, new IntegerDefault0Adapter());
|
||||
builder.registerTypeAdapter(int.class, new IntegerDefault0Adapter());
|
||||
builder.disableHtmlEscaping();
|
||||
builder.enableComplexMapKeySerialization();
|
||||
// builder.excludeFieldsWithoutExposeAnnotation();
|
||||
builder.setDateFormat("yyyy-MM-dd HH:mm:ss");
|
||||
gson = builder.create();
|
||||
}
|
||||
|
||||
public static Type makeJavaType(Type rawType, Type... typeArguments) {
|
||||
return TypeToken.getParameterized(rawType, typeArguments).getType();
|
||||
}
|
||||
|
||||
public static String toString(Object value) {
|
||||
if (Objects.isNull(value)) {
|
||||
return null;
|
||||
}
|
||||
if (value instanceof String) {
|
||||
return (String) value;
|
||||
}
|
||||
return toJSONString(value);
|
||||
}
|
||||
|
||||
public static String toJSONString(Object value) {
|
||||
return gson.toJson(value);
|
||||
}
|
||||
|
||||
public static String toPrettyString(Object value) {
|
||||
return gson.newBuilder().setPrettyPrinting().create().toJson(value);
|
||||
}
|
||||
|
||||
public static JsonElement fromJavaObject(Object value) {
|
||||
JsonElement result = null;
|
||||
if (Objects.nonNull(value) && (value instanceof String)) {
|
||||
result = parseObject((String) value);
|
||||
} else {
|
||||
result = gson.toJsonTree(value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static JsonElement parseObject(String content) {
|
||||
return JsonParser.parseString(content);
|
||||
}
|
||||
|
||||
public static JsonElement getJsonElement(JsonObject node, String name) {
|
||||
return node.get(name);
|
||||
}
|
||||
|
||||
public static JsonElement getJsonElement(JsonArray node, int index) {
|
||||
return node.get(index);
|
||||
}
|
||||
|
||||
public static <T> T toJavaObject(JsonElement node, Class<T> clazz) {
|
||||
return gson.fromJson(node, clazz);
|
||||
}
|
||||
|
||||
public static <T> T toJavaObject(JsonElement node, Type type) {
|
||||
return gson.fromJson(node, type);
|
||||
}
|
||||
|
||||
public static <T> T toJavaObject(JsonElement node, TypeToken<?> typeToken) {
|
||||
return toJavaObject(node, typeToken.getType());
|
||||
}
|
||||
|
||||
public static <E> List<E> toJavaList(JsonElement node, Class<E> clazz) {
|
||||
return toJavaObject(node, makeJavaType(List.class, clazz));
|
||||
}
|
||||
|
||||
public static List<Object> toJavaList(JsonElement node) {
|
||||
return toJavaObject(node, new TypeToken<List<Object>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
public static <V> Map<String, V> toJavaMap(JsonElement node, Class<V> clazz) {
|
||||
return toJavaObject(node, makeJavaType(Map.class, String.class, clazz));
|
||||
}
|
||||
|
||||
public static Map<String, Object> toJavaMap(JsonElement node) {
|
||||
return toJavaObject(node, new TypeToken<Map<String, Object>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
public static <T> T toJavaObject(String content, Class<T> clazz) {
|
||||
JsonObject jsonObject = getJsonObject(content);
|
||||
String jsonString = jsonObject.toString();
|
||||
return gson.fromJson(jsonString, clazz);
|
||||
}
|
||||
|
||||
public static <T> T toJavaObject(String content, Type type) {
|
||||
return gson.fromJson(content, type);
|
||||
}
|
||||
|
||||
public static <T> T toJavaObject(String content, TypeToken<?> typeToken) {
|
||||
return toJavaObject(content, typeToken.getType());
|
||||
}
|
||||
|
||||
public static <E> List<E> toJavaList(String content, Class<E> clazz) {
|
||||
return toJavaObject(content, makeJavaType(List.class, clazz));
|
||||
}
|
||||
|
||||
public static List<Object> toJavaList(String content) {
|
||||
return toJavaObject(content, new TypeToken<List<Object>>() {
|
||||
}.getType());
|
||||
}
|
||||
|
||||
public static <V> Map<String, V> toJavaMap(String content, Class<V> clazz) {
|
||||
return toJavaObject(content, makeJavaType(Map.class, String.class, clazz));
|
||||
}
|
||||
|
||||
public static Map<String, Object> toJavaMap(String content) {
|
||||
return toJavaObject(content, new TypeToken<Map<String, Object>>() {
|
||||
}.getType());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package com.ttstd.elderlyassistant.gson;
|
||||
|
||||
import com.google.gson.JsonDeserializationContext;
|
||||
import com.google.gson.JsonDeserializer;
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParseException;
|
||||
import com.google.gson.JsonPrimitive;
|
||||
import com.google.gson.JsonSerializationContext;
|
||||
import com.google.gson.JsonSerializer;
|
||||
import com.google.gson.JsonSyntaxException;
|
||||
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
public class IntegerDefault0Adapter implements JsonSerializer<Integer>, JsonDeserializer<Integer> {
|
||||
@Override
|
||||
public Integer deserialize(JsonElement json, Type typeOfT, JsonDeserializationContext context)
|
||||
throws JsonParseException {
|
||||
try {
|
||||
if (json.getAsString().equals("")) {
|
||||
return 0;
|
||||
}
|
||||
} catch (Exception ignore) {
|
||||
}
|
||||
try {
|
||||
return json.getAsInt();
|
||||
} catch (NumberFormatException e) {
|
||||
throw new JsonSyntaxException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public JsonElement serialize(Integer src, Type typeOfSrc, JsonSerializationContext context) {
|
||||
return new JsonPrimitive(src);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
package com.ttstd.elderlyassistant.gson;
|
||||
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.TypeAdapter;
|
||||
import com.google.gson.TypeAdapterFactory;
|
||||
import com.google.gson.reflect.TypeToken;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonToken;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
public class NullStringToEmptyAdapterFactory<T> implements TypeAdapterFactory {
|
||||
@Override
|
||||
public <T> TypeAdapter<T> create(Gson gson, TypeToken<T> type) {
|
||||
|
||||
Class<T> rawType = (Class<T>) type.getRawType();
|
||||
if (rawType != String.class) {
|
||||
return null;
|
||||
}
|
||||
return (TypeAdapter<T>) new StringAdapter();
|
||||
}
|
||||
|
||||
public static class StringAdapter extends TypeAdapter<String> {
|
||||
@Override
|
||||
public String read(JsonReader reader) throws IOException {
|
||||
if (reader.peek() == JsonToken.NULL) {
|
||||
reader.nextNull();
|
||||
return "";
|
||||
}
|
||||
return reader.nextString();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter writer, String value) throws IOException {
|
||||
if (value == null) {
|
||||
writer.nullValue();
|
||||
return;
|
||||
}
|
||||
writer.value(value);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,18 +1,30 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activity.main.MainActivity">
|
||||
|
||||
<TextView
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Hello World!"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintLeft_toLeftOf="parent"
|
||||
app:layout_constraintRight_toRightOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
<data>
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<variable
|
||||
name="click"
|
||||
type="com.ttstd.elderlyassistant.activity.main.MainActivity.BtnClick" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{click::wirteTag}"
|
||||
android:text="写入标签"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
@@ -1,9 +1,57 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
<layout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
xmlns:app="http://schemas.android.com/apk/res-auto"
|
||||
xmlns:tools="http://schemas.android.com/tools"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent"
|
||||
tools:context=".activity.nfc.NfcActivity">
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
<data>
|
||||
|
||||
<variable
|
||||
name="click"
|
||||
type="com.ttstd.elderlyassistant.activity.nfc.NfcActivity.BtnClick" />
|
||||
</data>
|
||||
|
||||
<androidx.constraintlayout.widget.ConstraintLayout
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="match_parent">
|
||||
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:hint="Name"
|
||||
android:inputType="text"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="parent" />
|
||||
|
||||
<EditText
|
||||
android:id="@+id/et_phone"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:ems="10"
|
||||
android:hint="phone"
|
||||
android:inputType="phone"
|
||||
android:maxLines="1"
|
||||
android:singleLine="true"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/et_name" />
|
||||
|
||||
|
||||
<Button
|
||||
android:id="@+id/button"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:onClick="@{click::write}"
|
||||
android:text="写入"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@+id/et_phone" />
|
||||
|
||||
</androidx.constraintlayout.widget.ConstraintLayout>
|
||||
</layout>
|
||||
Reference in New Issue
Block a user