简体   繁体   中英

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

I still new in coding. Now I have two nfc tags and each tag is storing different coordinate:latitude, longitude and what I want is when the device detect nfc tags it will read the payload and store it into arraylist. Currently, I able to read the first nfc tag and store the payload into arraylist. But the problem I face is that when I read the second nfc tag the previous data in arraylist is overwritten. How can I achieve both nfc tags payload are able to store into an arraylist?

Android Manifest:

<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=".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:scheme="geo" android:host="*" />

        </intent-filter>
    </activity>
</application>

Mainactivity:

private NfcAdapter nfcAdapter;
private TextView textView;
PendingIntent mPendingIntent;

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

    BottomNavigationView bottomNav = findViewById(R.id.bottom_nav);
    bottomNav.setOnNavigationItemSelectedListener(navListener);
    getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, new FragmentMessage()).commit();


    nfcAdapter = NfcAdapter.getDefaultAdapter(this);
    if (nfcAdapter == null) {
        Toast.makeText(this, "nfc not supported", Toast.LENGTH_SHORT).show();
        finish();
        return;
    }
    if (!nfcAdapter.isEnabled()) {
        startActivity(new Intent("android.settings.NFC_SETTINGS"));
        Toast.makeText(this, "nfc not yet open", 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){
    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);
            getSupportFragmentManager().beginTransaction().add(R.id.fragment_container, FragmentMessage.newInstance(payload), "FragmentMessage").commit();


        }
    }
}



@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);
}

private BottomNavigationView.OnNavigationItemSelectedListener navListener = new BottomNavigationView.OnNavigationItemSelectedListener() {
    @Override
    public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
        Fragment selectedFragment = null;

        switch (menuItem.getItemId()) {
            case R.id.homeFragment:
                selectedFragment = new FragmentHome();
                break;
            case R.id.homeFragment1:
                selectedFragment = new FragmentMessage();
                break;

        }
        getSupportFragmentManager().beginTransaction().replace(R.id.fragment_container, selectedFragment).commit();
        return true;
    }
};

FragmentMessage:

private String text;
ArrayList<String> list;

public static Fragment newInstance(String tv1) {
    FragmentMessage fragment = new FragmentMessage();
    Bundle args = new Bundle();
    args.putString("TEXT",tv1);
    fragment.setArguments(args);
    return fragment;
}

@Nullable
@Override
public View onCreateView(@NonNull LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
    View v = inflater.inflate(R.layout.fragment_message, container, false);
    TextView textView = v.findViewById(R.id.text_view_fragment);
    list= new ArrayList<>();

    if(getArguments() != null){
        text = getArguments().getString("TEXT");
        if(list != null){
            list.add(text);
        }
        System.out.println(list);



    }

    return v;
}

}

Because with each NFC card reading you add a newInstance of the Fragment, so you get a new copy of the Arraylist to which you only copy in 1 payload String.

So you have multiple copies of the Fragment which contain each contain a different new Arraylist

I'm not sure why you want a new Fragment each with one latitude, longitude value unless you want to have something like viewpager show the multiple Fragments in a slideshow each with one coordinate on each.

But there a number of solutions depending on what you are doing, and there is too many to list in detail, but generally the fall in to to categories.

  1. Only create one Fragment in the Activity's onCreate and then get your one instance of the Fragment from back from the FragmentManager (eg by using something like findFragmentById ) and then call a method on it that add's the data to the existing Arraylist in this Fragment.

  2. Possibly better solution is to store the data from each NFC card to a structure outside of a Fragment's lifecycle, this can be done as a Arraylist variable in the Activity with Interfaces or in Shared ViewModel or in a Room or SQLite Database. Therefore when you add , replace or do any other FragmentTransaction you won't be likely to destroy the existing Arraylist or create a new instance of the Arraylist and multiple Fragments can access the data stored outside themselves.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM