如何从 NFC 标签读取多个数据载荷并将这些数据载荷存储到一个 ArrayList 中?

huangapple go评论75阅读模式
英文:

How to read multiple payload from nfc tags and store the payloads into an arraylist?

问题

你好Stackers我在编码方面还是新手需要一些帮助我现在有两个 NFC 标签这两个标签存储着不同的地理坐标经度纬度)。目前我能够从 NFC 标签中读取有效载荷payload)。我想要的是将这两个 NFC 标签的有效载荷存储到一个 ArrayList 中当我读取第一个标签时它会将有效载荷存储到 ArrayList 中但当我读取第二个标签时有效载荷会覆盖前一个载荷

Android 清单文件

<uses-permission android:name="android.permission.NFC" />
<uses-feature
    android:name="android.hardware.nfc"
    android:required="true" />
<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:roundIcon="@mipmap/ic_launcher_round"
    android:supportsRtl="true"
    android:theme="@style/AppTheme">
    <activity android:name=".arraylist"></activity>
    <activity
        android:name=".MainActivity"
        android:launchMode="singleInstance">
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />
            <data
                android:host="*"
                android:scheme="geo" />
        </intent-filter>
    </activity>
</application>

MainActivity

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if (nfcAdapter == null) {
        Toast.makeText(this, "不支持 NFC", Toast.LENGTH_SHORT).show();
        finish();
        return;
    }
    if (!nfcAdapter.isEnabled()) {
        startActivity(new Intent("android.settings.NFC_SETTINGS"));
        Toast.makeText(this, "尚未启用 NFC", Toast.LENGTH_SHORT).show();
    }

    mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
}

private void readIntent(Intent intent) {
    if (list == null) {
        list = new ArrayList<>();
    }
    Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
    for (int i = 0; i < parcelables.length; i++) {
        NdefMessage message = (NdefMessage) parcelables[i];
        NdefRecord[] records = message.getRecords();
        for (int j = 0; j < records.length; j++) {
            NdefRecord record = records[j];
            byte[] original = record.getPayload();
            byte[] value = Arrays.copyOfRange(original, 0, original.length);
            String payload = new String(value);
            
            list.add(payload); // 将当前标签的有效载荷添加到 ArrayList 中
        }
    }
    System.out.println(list);
}

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    readIntent(intent);
}

@Override
protected void onResume() {
    super.onResume();
    nfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
}

@Override
protected void onPause() {
    super.onPause();
    nfcAdapter.disableForegroundDispatch(this);
}

期望的输出应该是:
[geo:1.523534, 103.633690, geo:1.5364496, 103.656321]

这样可以确保第二个标签的有效载荷不会覆盖前一个有效载荷。

英文:

Hi Stackers I still new in coding and need some help. Now I have two NFC tags and both tags is storing with different Geo coordinates(longitude, latitude). Currently, I able to read the payload from the NFC tags. What I want is to store the payloads from both of the NFC tags into an arraylist. When I read the first tag it does stored the payload into arraylist, but when read second tag the payload will overwritten the previous payload.

Android Manifest:

&lt;uses-permission android:name=&quot;android.permission.NFC&quot; /&gt;
&lt;uses-feature
android:name=&quot;android.hardware.nfc&quot;
android:required=&quot;true&quot; /&gt;
&lt;application
android:allowBackup=&quot;true&quot;
android:icon=&quot;@mipmap/ic_launcher&quot;
android:label=&quot;@string/app_name&quot;
android:roundIcon=&quot;@mipmap/ic_launcher_round&quot;
android:supportsRtl=&quot;true&quot;
android:theme=&quot;@style/AppTheme&quot;&gt;
&lt;activity android:name=&quot;.arraylist&quot;&gt;&lt;/activity&gt;
&lt;activity
android:name=&quot;.MainActivity&quot;
android:launchMode=&quot;singleInstance&quot;&gt;
&lt;intent-filter&gt;
&lt;action android:name=&quot;android.intent.action.MAIN&quot; /&gt;
&lt;category android:name=&quot;android.intent.category.LAUNCHER&quot; /&gt;
&lt;/intent-filter&gt;
&lt;intent-filter&gt;
&lt;action android:name=&quot;android.nfc.action.NDEF_DISCOVERED&quot; /&gt;
&lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
&lt;data
android:host=&quot;*&quot;
android:scheme=&quot;geo&quot; /&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;
&lt;/application&gt;

MainActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter == null) {
Toast.makeText(this, &quot;nfc not supported&quot;, Toast.LENGTH_SHORT).show();
finish();
return;
}
if (!nfcAdapter.isEnabled()) {
startActivity(new Intent(&quot;android.settings.NFC_SETTINGS&quot;));
Toast.makeText(this, &quot;nfc not yet open&quot;, Toast.LENGTH_SHORT).show();
}
mPendingIntent = PendingIntent.getActivity(this,0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0 );
}
private void readIntent(Intent intent){
list = new ArrayList&lt;&gt;();
Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
for(int i=0; i&lt;parcelables.length; i ++){
NdefMessage message =(NdefMessage)parcelables[i];
NdefRecord[] records = message.getRecords();
for(int j=0; j&lt;records.length; j++){
NdefRecord record = records[j];
byte[] original = record.getPayload();
byte[] value = Arrays.copyOfRange(original,0,original.length);
String payload = new String(value);
if(list != null){
list.add(payload);
System.out.println(list);
}
}
}
}
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
readIntent(intent);
}
@Override
protected void onResume() {
super.onResume();
nfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null);
}
@Override
protected void onPause() {
super.onPause();
nfcAdapter.disableForegroundDispatch(this);
}

Here is my output:
I/System.out: [geo:1.523534,103.633690]

But my expectation output is:
[geo:1.523534, 103.633690, geo:1.5364496, 103.656321]

So how can achieve that second tag payload will not overwritten the previous payload?

答案1

得分: 0

这次的问题在于,你没有像在你之前类似的问题中那样创建一个 new 的 Fragment 实例,而是每次读取卡片时都创建了一个 new 的数组列表,从而取消引用第一个列表对象,使其被垃圾收集删除。

这是一个典型的变量初始化问题。

每次读取卡片时都会调用 readIntent
因此,请移除 readIntent 中创建新列表的第一行代码。

例如:

private void readIntent(Intent intent){
    Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);

....

然后在你的类定义中仅初始化数组列表一次。

例如:

public class MainActivity extends AppCompatActivity {

    private ArrayList<String> list = new ArrayList();
英文:

The problem this time is that you are not creating a new instance of a Fragment like your were in your previous similar question, you are creating a new arraylist every time a card is read and thus de-referencing the first list object for it to be deleted by the garbage collection.

This is a classic variable initialisation issue.

readIntent is called every time a card is read.
So remove the first line of `readIntent where you create a new list.

e.g.

private void readIntent(Intent intent){
Parcelable[] parcelables = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
....

Then in your class definition initialise the arraylist once only.

e.g.

public class MainActivity extends AppCompatActivity {
private ArrayList&lt;String&gt; list = new ArrayList();

huangapple
  • 本文由 发表于 2020年10月16日 02:02:35
  • 转载请务必保留本文链接:https://go.coder-hub.com/64377325.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定