onNewIntent никогда не срабатывает во фрагменте

avatar
DaGuy
8 апреля 2018 в 10:57
2378
5
1

У меня возникли проблемы с получением метода onNewIntent для работы внутри фрагмента. Я пробовал все, но ничего не работает. Мой проект отлично работал при использовании действий, но когда я переключился на фрагменты, он перестал работать. Моя идея заключается в том, что я хотел сделать вкладки, где одна вкладка записывает в тег NFC, а другие вкладки будут считывать данные из тега NFC. Вот мой код для фрагмента (письменная вкладка):

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

}

В действии, содержащем вкладки, я создал этот метод:

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

Мой манифест активности Android с вкладками:

   <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>

Я исследовал похожие вопросы с решениями, но ни один из них не работает с моей реализацией. Что я здесь делаю не так?

Источник
Sandip Fichadiya
8 апреля 2018 в 11:02
0

что такое переменная fragment в вашем Activity, которую вы использовали в onNewIntent, и как вы ее инициализировали?

Sandip Fichadiya
8 апреля 2018 в 11:07
0

опубликуйте весь код своей деятельности или часть, где вы инициализируете Fragment fragment

Sandip Fichadiya
8 апреля 2018 в 11:16
0

я инициализировал так: Фрагмент фрагмента; ---> Это не инициализация. Это декларация. Я подозреваю, что вы никогда не инициализировали переменную` и, следовательно, ваше условие fragment instanceof Home каждый раз терпит неудачу, потому что фрагмент равен нулю

DaGuy
8 апреля 2018 в 11:17
0

я обновил / отредактировал свой вопрос с полным кодом Activity

Ответы (5)

avatar
Morteza Rastgoo
7 марта 2020 в 15:04
1

В действии сделайте следующее:


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

когда setIntent вызывается в действии, во фрагменте onResume вызывается метод automatically!

Таким образом, вы можете получить намерение следующим образом:

    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)
        }
    }
avatar
Karam
19 августа 2019 в 08:24
0

вы можете использовать интерфейс.

используйте в своих действиях:

private interfaceName listener;

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

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

    return;
}

Интерфейс:

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

Наконец в вашем фрагменте:

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 
    }

}
avatar
Dyan
29 апреля 2019 в 19:30
1

Я не уверен, что вы решили это. Но я пытался сделать то же самое с фрагментом NFC для чтения тегов, проблема для меня заключалась в том, что намерения не инициализировались в нужное время во фрагменте, как только я переместил их в действие, onNewIntent начал работать и оттуда я отправил намерение фрагменту для обработки. Не уверен, что это все еще полезно или нет, если есть лучший способ, не стесняйтесь поделиться им, потому что я хочу, чтобы фрагмент был полностью независимым от активности, если это возможно.

avatar
Sandip Fichadiya
8 апреля 2018 в 11:25
0

Проблема для вас в том, что ваша переменная fragment никогда не инициализируется и, следовательно, условие fragment instanceof Home никогда не работает.

Вы хотите передать данные newIntent во фрагмент Home, который находится в ViewPager в качестве первой страницы (т.е. 0-го индекса). Таким образом, вы можете попросить своего SectionsPagerAdapter предоставить вам фрагмент Home с помощью метода getItem(int position). Но если вы посмотрите на свою реализацию метода getItem(), вы всегда возвращаете новый экземпляр фрагмента с

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

Итак, если вы вызовете mSectionAdapater.getItem(), он даст вам другой экземпляр Home Fragment, а не тот, который отображается в данный момент. Итак, вам нужно сначала внести некоторые изменения в ваш SectionsPagerAdapter, который я показал ниже.

Замените SectionsPagerAdapter на это:

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

теперь измените свой метод onNewIntent() в своей деятельности на:

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

}
DaGuy
8 апреля 2018 в 11:30
0

Я пробовал, он не показывает тост или что-то в этом роде.

Sandip Fichadiya
8 апреля 2018 в 11:32
0

Вы получаете Toast или Log от DosisHome?

DaGuy
8 апреля 2018 в 11:36
0

Нет ничего не отображается

DaGuy
8 апреля 2018 в 11:42
0

Может быть, это часть фрагмента, которая не работает?

Sandip Fichadiya
8 апреля 2018 в 11:43
0

Тогда сначала вы должны посмотреть, почему onNewIntent не вызывается в самой деятельности. Потому что, если это не вызов, метод вашего фрагмента никогда не будет вызван. Как только вы устраните эту проблему, приведенный выше код будет нормально работать для доставки newIntent во фрагмент.

Sandip Fichadiya
8 апреля 2018 в 11:45
0

Может быть, это часть фрагмента, которая не работает? ---> Не думаю. Как я уже сказал, если вы не получаете обратный вызов newIntent в действии, есть другая проблема. Вы должны сначала исправить это, а затем попытаться найти фрагмент. Я думаю, вы что-то изменили при добавлении фрагментов, что вызывает проблему

DaGuy
8 апреля 2018 в 11:56
1

Я посмотрю на это подробнее. Спасибо за вашу помощь :)

avatar
Raman Sharma
8 апреля 2018 в 11:17
0

onNewIntent принадлежит Activity, поэтому вы не можете иметь его непосредственно в своем фрагменте. Что вы можете сделать, так это передать данные в ваш фрагмент из вашей активности, когда он поступит в onNewIntent, если у вас есть ссылка на фрагмент.

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