Search code examples
androidandroid-fragmentsnfcfragment-lifecycle

replacement method for onNewIntent() in android fragment


I am developing a NFC app using Fragments. the fragment class will not let me use onNewIntent() for me to be able to make the app scan NFC tags. Is there a replacement function or work around to this issue. below are the methods I am using in the Fragment class. I have two fragments which are responsible for different NFC functions. I need to be able to manage the NFC functionality using the fragment lifecycle individually rather than passing data to the fragment activity.

 @Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);

    if (getArguments() != null) {
        mParam1 = getArguments().getString(ARG_PARAM1);
        mParam2 = getArguments().getString(ARG_PARAM2);
    }
    _nfcAdapter = NfcAdapter.getDefaultAdapter(getActivity().getApplicationContext());
    CheckNfcStatus();

    NfcManager manager = (NfcManager) getActivity().getApplicationContext().getSystemService(Context.NFC_SERVICE);
    NfcAdapter adapter = manager.getDefaultAdapter();
}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    // Inflate the layout for this fragment
    View v = inflater.inflate(R.layout.fragment_heart_beat, container, false);

    heartbearSearch = v.findViewById(R.id.heartBeat_Search);
    heartbearSuccess = v.findViewById(R.id.heartBeat_Success);
    heartbearSearch.setVisibility(View.VISIBLE);
    heartbearSuccess.setVisibility(View.GONE);
    
    return inflater.inflate(R.layout.fragment_heart_beat, container, false);
}


protected String TagUid;

@Override
public void onResume() {
    //CheckNfcStatus();
    AlertDialog alert = new AlertDialog.Builder(getActivity().getApplicationContext()).create();
    super.onResume();
    if (_nfcAdapter == null) {                           // checks if NFC is available on the device
        alert.setMessage("NFC is not supported on this device.");
        alert.setTitle("NFC Unavailable");
        alert.show();
    }
    else {
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);

        Intent intent = new Intent(getActivity().getApplicationContext(), getClass());
        intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

        final PendingIntent pendingIntent = PendingIntent.getActivity(getActivity().getApplicationContext(), 0, intent, 0);

        IntentFilter[] filters = new IntentFilter[]{
                new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED),};
        String[][] techList = new String[][]{
                new String[]{NfcA.class.getName()},
                new String[]{NfcB.class.getName()},
                new String[]{NfcF.class.getName()},
                new String[]{NfcV.class.getName()},
                new String[]{NfcBarcode.class.getName()
                },
                // Filter for nfc tag discovery
        };
        _nfcAdapter.enableForegroundDispatch(getActivity(), pendingIntent, filters, techList);
    }
}

@Override
public void onPause() {
    super.onPause();
    _nfcAdapter.disableForegroundDispatch(getActivity());
}

@Override
public void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    HBClass hb = new HBClass();

    if (intent.getAction() == NfcAdapter.ACTION_TECH_DISCOVERED) {
        Boolean res = true;

        if (res) {
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            if (tag != null) {
                if (hb.ReadTagSync(tag)) {
                    Context context = getContext();
                    mheartImage.startAnimation(mHeartAnimation);

                    CharSequence toastMessage = "Transmission successful";
                    int duration = Toast.LENGTH_SHORT;
                    Toast.makeText(context, toastMessage, duration).show();

                    textView.setText("Scan a new Tag");
                }
            }
        }
    }
}


public void SendRWBool(boolean someval) {

    writeFlag = true;
    //WriteNFC(tg);
}

private void CheckNfcStatus() {
    Context context = getActivity().getApplicationContext();
    int duration = Toast.LENGTH_LONG;
    if (_nfcAdapter == null) {
        CharSequence toastMessage = "No NFC available for the device!";
        Toast.makeText(context, toastMessage, duration).show();
        // NFC is not available for device
    } else if (!_nfcAdapter.isEnabled()) {
        CharSequence toastMessage = "Please Enable NFC!";
        Toast.makeText(context, toastMessage, duration).show();
        // NFC is available for device but not enabled
    } else {
        CharSequence toastMessage = "NFC enabled!";
        Toast.makeText(context, toastMessage, duration).show();
        // NFC is enabled
    }
}

Solution

  • Really NFC is an Activity scoped operation and really needs to be handled in your Activity.

    Some parts like configuring can be done in Fragments but the actual interaction with the Tag data should be done in the Activity whether you are using the Manifest, ForegroundDispatch or enableReaderMode.

    You need to turn your thinking on it's head to get what you want.

    Have your NFC handling code in the Activity but make it conditional on what it does based on which fragment is active.

    e.g. some pseudo code

    handleNfc() {
      if current fragment equal Fragment 1 {
        // Process NFC the Fragment 1 way
      } else {
        // Process NFC the Fragment 2 way
      }
    }
    

    There are various ways to doing this with the Fragment communicating to the activity that it it the "current" fragment when it is created and the Activity communicates back the processed data for the Fragment to use.

    Some option are interfaces for the Activity to Fragment communication.

    Or I think a better method is a shared view model as it is very easy for the Fragment to observe the shared view model to get notified when the Activity has finished processing the NFC data.