DaGuy
DaGuy

Reputation: 65

onNewIntent never get triggered in fragment

I am having a problem(s) with getting onNewIntent method to work inside Fragment. I have tried everything but nothing seems to work. My project worked perfectly when using activities but when I switched to fragments it stopped working. My idea is that I wanted to make tabs, where one Tab writes to NFC tag and the other Tabs will read data from the NFC Tag. Here is my code for Fragment(writing Tab):

    public class Home extends Fragment {

    NfcAdapter nfcAdapter;
    Button writebtn;
    Tag tag;
    EditText txtName1, txtName2, txtName3;

    public void onViewCreated(View view, Bundle savedInstanceState) {
        super.onViewCreated(view,savedInstanceState);
        nfcAdapter = NfcAdapter.getDefaultAdapter(getContext());

         txtName1 = (EditText)view.findViewById(R.id.pName1);
         txtName2= (EditText)view.findViewById(R.id.pName2);
        txtName3= (EditText)view.findViewById(R.id.pName3);
        writebtn=(Button)view.findViewById(R.id.nfcWriteBtn);

    }

    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, Bundle savedInstanceState) {
        View v= inflater.inflate(R.layout.home, container,false);
        return v;

    }


    @Override
    public void onResume() {
        super.onResume();

        if(nfcAdapter !=null){

            /* go to phone's nfc settings */
            if(!nfcAdapter.isEnabled()){
                showNfcSettings();
            }
            enableForegroundDispatchSystem();
        }

    }

    private void showNfcSettings() {
        Intent nfcSettingIntent = new Intent(Settings.ACTION_NFC_SETTINGS);
        startActivity(nfcSettingIntent);
    }

    @Override
    public void onPause() {
        super.onPause();

        disableForegroundDispatchSystem();
    }


    protected void onNewIntent(Intent intent) {
        System.out.print("I am here in Home");
        Log.d("my tag", "I am here now");
        Toast.makeText(getActivity(), "NfcIntent!", Toast.LENGTH_SHORT).show();
        if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) {
       // if (nfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
            Toast.makeText(getActivity(), "NfcIntent!", Toast.LENGTH_SHORT).show();
            tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            writebtn.setOnClickListener(new View.OnClickListener() {
                @Override
                public void onClick(View view) {
                    NdefMessage ndefMessage = createNdefMessage(txtName1.getText().toString(), txtName2.getText().toString(),txtName3.getText().toString());
                    writeNdefMessage(tag, ndefMessage);
                }
            });

        }

    }


    private void enableForegroundDispatchSystem() {

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

        PendingIntent pendingIntent = PendingIntent.getActivity(getContext(), 0, intent, 0);

        IntentFilter[] intentFilters = new IntentFilter[]{};

        nfcAdapter.enableForegroundDispatch(getActivity(), pendingIntent, intentFilters, null);
    }

    private void disableForegroundDispatchSystem() {
        nfcAdapter.disableForegroundDispatch(getActivity());
    }
    private void formatTag(Tag tag, NdefMessage ndefMessage) {
        try {

            NdefFormatable ndefFormatable = NdefFormatable.get(tag);

            if (ndefFormatable == null) {
                Toast.makeText(getContext(), "Tag is not ndef formatable!", Toast.LENGTH_SHORT).show();
            }

            else{
                ndefFormatable.connect();
                ndefFormatable.format(ndefMessage);
                ndefFormatable.close();
                Toast.makeText(getContext(), "Tag writen!", Toast.LENGTH_SHORT).show();
            }
        } catch (Exception e) {
            Log.e("formatTag", e.getMessage());
        }

    }

    private void writeNdefMessage(Tag tag, NdefMessage ndefMessage) {

        try {

            if (tag == null) {
                Toast.makeText(getContext(), "Tag object cannot be null", Toast.LENGTH_SHORT).show();
                return;
            }

            Ndef ndef = Ndef.get(tag);

            if (ndef == null) {
                // format tag with the ndef format and writes the message.
                formatTag(tag, ndefMessage);
            } else {
                ndef.connect();
                if (!ndef.isWritable()) {
                    Toast.makeText(getContext(), "Tag is not writable!", Toast.LENGTH_SHORT).show();

                    ndef.close();
                    return;
                }

                ndef.writeNdefMessage(ndefMessage);
                ndef.close();

                Toast.makeText(getContext(), "Tag writen!", Toast.LENGTH_SHORT).show();

            }

        } catch (Exception e) {
            Log.e("writeNdefMessage", e.getMessage());
        }

    }


    private NdefRecord createTextRecord(String content) {
        try {
            byte[] language;
            language = Locale.getDefault().getLanguage().getBytes("UTF-8");

            final byte[] text = content.getBytes("UTF-8");
            final int languageSize = language.length;
            final int textLength = text.length;
            final ByteArrayOutputStream payload = new ByteArrayOutputStream(1 + languageSize + textLength);

            payload.write((byte) (languageSize & 0x1F));
            payload.write(language, 0, languageSize);
            payload.write(text, 0, textLength);

            return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload.toByteArray());

        } catch (UnsupportedEncodingException e) {
            Log.e("createTextRecord", e.getMessage());
        }
        return null;
    }
    private NdefMessage createNdefMessage(String content, String content2, String content3) {

        NdefRecord ndefRecord = createTextRecord(content);
        NdefRecord ndefRecord2 = createTextRecord(content2);
        NdefRecord ndefRecord3 = createTextRecord(content3);

        NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{ndefRecord, ndefRecord2, ndefRecord3});

        return ndefMessage;
    }

}

In the Activity that contains tabs I have created this method:

 public class DosisHome extends AppCompatActivity {

    protected DrawerLayout mDrawerLayout;
    private ActionBarDrawerToggle mtoggle;
    NfcAdapter nfcAdapter;
    private Toolbar mtoolbar;
    Fragment fragment;
    private TextView mName;
    private SectionsPagerAdapter mSectionsPagerAdapter;
    private ViewPager mViewPager;
    private NavigationView mNavigationView;

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

        mtoolbar = (Toolbar) findViewById(R.id.nav_action);
        setSupportActionBar(mtoolbar);
        mNavigationView= (NavigationView)findViewById(R.id.nav_view);
        mDrawerLayout = findViewById(R.id.drawer_layout);
        mtoggle = new ActionBarDrawerToggle(this, mDrawerLayout, R.string.open, R.string.close);
        mDrawerLayout.addDrawerListener(mtoggle);
        mtoggle.syncState();
        // Create the adapter that will return a fragment for each of the three
        // primary sections of the activity.
        mSectionsPagerAdapter = new SectionsPagerAdapter(getSupportFragmentManager());

        // Set up the ViewPager with the sections adapter.
        mViewPager = (ViewPager) findViewById(R.id.container);
        mViewPager.setAdapter(mSectionsPagerAdapter);

        TabLayout tabLayout = (TabLayout) findViewById(R.id.tabs);

        mViewPager.addOnPageChangeListener(new TabLayout.TabLayoutOnPageChangeListener(tabLayout));
        tabLayout.addOnTabSelectedListener(new TabLayout.ViewPagerOnTabSelectedListener(mViewPager));

        tabLayout.setupWithViewPager(mViewPager);
        tabLayout.setOnTabSelectedListener(new TabLayout.OnTabSelectedListener() {
            @Override
            public void onTabSelected(TabLayout.Tab tab) {
                switch (tab.getPosition())
                {
                    case 0:
                        mViewPager.setCurrentItem(0);
                        mtoolbar.setTitle("Home");
                        break;

                    case 1:
                        mViewPager.setCurrentItem(1);
                        mtoolbar.setTitle("Write");
                        break;

                    case 2:
                        mViewPager.setCurrentItem(2);
                        mtoolbar.setTitle("Read");
                        break;

                    case 3:
                        mViewPager.setCurrentItem(3);
                        mtoolbar.setTitle("Others");
                        break;

                    case 4:
                        mViewPager.setCurrentItem(4);
                        mtoolbar.setTitle("Alarm");
                        break;


                    default:
                        mViewPager.setCurrentItem(tab.getPosition());
                        mtoolbar.setTitle("Home APP");
                        break;
                }

            }

            @Override
            public void onTabUnselected(TabLayout.Tab tab) {

            }

            @Override
            public void onTabReselected(TabLayout.Tab tab) {

            }
        });

        getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        getSupportActionBar().setHomeButtonEnabled(true);

        NavigationView navigationView = findViewById(R.id.nav_view);

        navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) {
                // set item as selected to persist highlight
                menuItem.setChecked(true);

                switch (menuItem.getItemId()){

                    case R.id.nav_write:
                        mViewPager.setCurrentItem(0);
                        mDrawerLayout.closeDrawers();
                        mtoolbar.setTitle("Write");
                        break;

                    case R.id.nav_read:
                        mViewPager.setCurrentItem(1);
                        mDrawerLayout.closeDrawers();
                        mtoolbar.setTitle("Read");
                        break;

                    case R.id.nav_other:
                        mViewPager.setCurrentItem(2);
                        mDrawerLayout.closeDrawers();
                        mtoolbar.setTitle("Others");
                        break;

                    case R.id.nav_alarm:
                        mViewPager.setCurrentItem(3);
                        mDrawerLayout.closeDrawers();
                        mtoolbar.setTitle("Alarm");
                        break;

                    case R.id.nav_logout:
                        FirebaseAuth.getInstance().signOut();
                        finish();
                        startActivity(new Intent(getApplicationContext(),Login.class));

                }


                // close drawer when item is tapped
                mDrawerLayout.closeDrawers();
                return true;
            }
        });

        mDrawerLayout.addDrawerListener(
                new DrawerLayout.DrawerListener() {
                    @Override
                    public void onDrawerSlide(View drawerView, float slideOffset) {
                        // Respond when the drawer's position changes
                    }

                    @Override
                    public void onDrawerOpened(View drawerView) {
                        // Respond when the drawer is opened
                    }

                    @Override
                    public void onDrawerClosed(View drawerView) {
                        // Respond when the drawer is closed
                    }

                    @Override
                    public void onDrawerStateChanged(int newState) {
                        // Respond when the drawer motion state changes
                    }
                }
        );

    }

    @Override
    public void onNewIntent(Intent intent) {
        setIntent(intent);
        super.onNewIntent(intent);
        Toast.makeText(this, "I am in TabsHome", Toast.LENGTH_SHORT).show();
        System.out.print("I am here in TabsHome");
        Log.d("my tag", "I am here");
        // Notify fragment about the new intent

       if(fragment instanceof Home){
           Log.d("my tag", "I am here");
           Home hm = (Home) fragment;
           hm.onNewIntent(intent);
        }

    }







    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.menu_dosis_home, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.


        if(mtoggle.onOptionsItemSelected(item)){
            return true;
        }
        //noinspection SimplifiableIfStatement
        if (item.getItemId()== R.id.action_settings) {
            return true;
        }

        return super.onOptionsItemSelected(item);
    }

    /**
     * A {@link FragmentPagerAdapter} that returns a fragment corresponding to
     * one of the sections/tabs/pages.
     */
    public class SectionsPagerAdapter extends FragmentPagerAdapter {

        public SectionsPagerAdapter(FragmentManager fm) {
            super(fm);
        }

        @Override
        public Fragment getItem(int position) {
            switch (position){

                case 0:
                    Home home= new Home();
                    return home;
                case 1:
                    Writer write = new Writer();
                    return write;

                case 2:
                    Reader read= new Reader();
                    return read;

                case 3:
                    Others other= new Others();
                    return other;

                case 4:
                    Alarm alarm= new Alarm();
                    return alarm;

            }
            return null;
        }

        @Override
        public int getCount() {
            // Show 3 total pages.
            return 5;
        }
        /*to set text instead of icons*/
        public CharSequence getPageTitle(int position){

            return null;
        }
    }
}

My AndroidManifest for Activity with tabs :

   <activity android:name=".TabsHome"
        android:windowSoftInputMode="adjustPan"
        android:screenOrientation="portrait"
        android:launchMode="singleTop">

        <intent-filter>
            <category android:name="android.intent.category.DEFAULT" />
            <category android:name="android.intent.category.LAUNCHER" />
            <action android:name="android.nfc.action.TAG_DISCOVERED" />
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />


            <data android:mimeType="text/plain" />
        </intent-filter>

        <meta-data
            android:name="android.nfc.action.TECH_DISCOVERED"
            android:resource="@xml/nfc_tech_filter" />
    </activity>

I have researched similar questions with solutions but none of them seems to work with my implementation. What am I doing wrong here?

Upvotes: 1

Views: 3985

Answers (5)

Morteza Rastgoo
Morteza Rastgoo

Reputation: 6986

In activity do this:


    override fun onNewIntent(intent: Intent) {
        super.onNewIntent(intent)
        setIntent(intent)//This will be used in NFCCardFragment
    }

when the setIntent is called in activity, in the fragment onResume method is called automatically!

So you can get intent from it like this:

    override fun onResume() {
        super.onResume()
        nfcAdapter?.let { adapter ->
            if (adapter.isEnabled)
                adapter.enableForegroundDispatch(
                    requireActivity(),
                    nfcPendingIntent,
                    nfcFilters,
                    nfcTechLists
                )
        }

        //this part is the point
        requireActivity().intent?.let {
        //Do whatever you want!
            resolveNFCIntent(it)
        }
    }

Upvotes: 3

Karam
Karam

Reputation: 323

what you can do is to use an interface.

in your Activity use:

private interfaceName listener;

public void setNewIntentListner(Fragment fragmentName) {
    listener =  fragmentName;
}

 @Override
protected void onNewIntent(Intent intent) {
    if(listener != null){
    listener.newIntent(intent);
    }

    return;
}

The interface:

public interface InterfaceName{
    void newIntent(Intent intent);
}

Finally in your fragment:

public class fragmentName extends Fragment implements interfaceName{

    private MainActivity mainActivity;

    @Override
    public void onStart() {
        super.onStart();
        mainActiviyt = (MainActivity)getActivity();
        mainActivity.setNewIntentListner(this);

    }
    @Override
    public void newIntent(Intent intent) {
    // here you have your intent in your fragment 
    }

}

Upvotes: 0

Dyan
Dyan

Reputation: 1753

I'm not sure if you guys solved this. But, I was trying to do the same have a NFC fragment to read the tags, the problem for me was the intents were not being initialized at the right time in the fragment as soon as I moved them to the activity the onNewIntent started working and from there I sent the intent to the fragment to be processed. Not sure if this is still useful or not, if there is a better way feel free to share it because I want to have the fragment completely independent from the activity if it is possible.

Upvotes: 1

Sandip Fichadiya
Sandip Fichadiya

Reputation: 3480

The problem for you is, your fragment variable is never initialized and hence the fragment instanceof Home condition never works.

You want to pass the newIntent data to Home fragment which resides in ViewPager as the first page (i.e 0th index). So you can ask your SectionsPagerAdapter to give you the Home fragment via getItem(int position) method. But if you look at your implementation of getItem() method, you are always returning new Instance of fragment with

case 0:
    Home home= new Home();
    return home;

So, if you call mSectionAdapater.getItem(), it'll give you another instance of Home Fragment and not the one which is being displayed currently. So you need to do some changes first in your SectionsPagerAdapter I showed below.

Change your SectionsPagerAdapter with this:

public class SectionsPagerAdapter extends FragmentPagerAdapter {
    private List<Fragment> mFragments = new ArrayList<>();

    public SectionsPagerAdapter(FragmentManager fm) {
        super(fm);
        mFragments.add(new Home());
        mFragments.add(new Writer());
        mFragments.add(new Reader());
        mFragments.add(new Others());
        mFragments.add(new Alarm());
    }

    @Override
    public Fragment getItem(int position) {
        return mFragments.get(position);
    }

    @Override
    public int getCount() {
        // Show 3 total pages.
        return mFragments.size();
    }

    /*to set text instead of icons*/
    public CharSequence getPageTitle(int position) {

        return null;
    }
}

now, change your onNewIntent() method in your Activity with:

@Override
public void onNewIntent(Intent intent) {
    setIntent(intent);
    super.onNewIntent(intent);
    Toast.makeText(this, "I am in TabsHome", Toast.LENGTH_SHORT).show();
    System.out.print("I am here in TabsHome");
    Log.d("my tag", "I am here");
    // Notify fragment about the new intent

    Fragment fragment = mSectionsPagerAdapter.getItem(0);

    if(fragment instanceof Home){
       Log.d("my tag", "I am here");
       Home hm = (Home) fragment;
       hm.onNewIntent(intent);
    }

}

Upvotes: 0

Raman Sharma
Raman Sharma

Reputation: 177

onNewIntent belongs to Activity so you cannot have directly it in your fragment. What you can do is pass the data to your fragment from your activity when it arrives in onNewIntent provided you have the reference to the fragment.

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
List<Fragment> allFragments = getSupportFragmentManager().getFragments();
Fragment fragment;
    for (Fragment fragment : allFragments) {
        if (fragment instanceof Home) {
            Home frgHome = (Home) fragment;
            frgHome.onNewIntent(intent);
        }
    }
}

Upvotes: 0

Related Questions