【问题标题】:onNewIntent never get triggered in fragmentonNewIntent 永远不会在片段中触发
【发布时间】:2018-04-08 10:57:29
【问题描述】:

我在获取 onNewIntent 方法以在 Fragment 中工作时遇到问题。我已经尝试了一切,但似乎没有任何效果。我的项目在使用活动时运行良好,但是当我切换到片段时它停止工作。我的想法是我想制作标签,其中一个标签写入 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;
    }

}

在包含选项卡的 Activity 中,我创建了这个方法:

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

我的带有标签的 Activity 的 AndroidManifest :

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

我用解决方案研究了类似的问题,但似乎没有一个适用于我的实现。我在这里做错了什么?

【问题讨论】:

  • 您在Activity 中使用的fragment 变量是什么,您在onNewIntent 中使用了它,您是如何初始化它的?
  • 贴出你的Activity的全部代码或者你初始化的部分Fragment fragment
  • 我已经这样初始化了:片段片段; ---> 这不是初始化。是宣言。我怀疑您从未初始化变量`,因此您的fragment instanceof Home 条件每次都失败,因为片段为空
  • 我已经用完整的 Activity 代码更新/编辑了我的问题

标签: android android-fragments nfc onnewintent


【解决方案1】:

我不确定你们是否解决了这个问题。但是,我试图做同样的事情,有一个 NFC 片段来读取标签,对我来说,问题是当我将意图移动到 onNewIntent 开始工作的活动时,意图没有在片段中的正确时间初始化,并且从那里我将意图发送到要处理的片段。不确定这是否仍然有用,如果有更好的方法可以随意分享,因为如果可能的话,我希望片段完全独立于活动。

【讨论】:

    【解决方案2】:

    在活动中这样做:

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

    在activity中调用setIntent时,在fragment中调用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)
            }
        }
    

    【讨论】:

      【解决方案3】:

      onNewIntent 属于 Activity,因此您不能直接在片段中使用它。您可以做的是在数据到达 onNewIntent 时将数据从您的 Activity 传递给您的片段,前提是您有对片段的引用。

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

      【讨论】:

        【解决方案4】:

        您的问题是,您的 fragment 变量永远不会初始化,因此 fragment instanceof Home 条件永远不会起作用。

        您希望将 newIntent 数据传递给位于ViewPager 中的Home 片段作为第一页(即第0 个索引)。所以你可以让你的SectionsPagerAdapter通过getItem(int position)方法给你Home片段。但是,如果您查看 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;
            }
        }
        

        现在,在 Activity 中更改 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);
            }
        
        }
        

        【讨论】:

        • 我试过了 没有显示吐司什么的
        • 您是否从DosisHome 获得 Toast 或 Log?
        • 没有显示任何内容
        • 可能是 Fragment 部分无法正常工作?
        • 我会更深入地研究它。谢谢你的帮助:)
        【解决方案5】:

        你能做的就是使用一个接口。

        在您的 Activity 中使用:

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

        【讨论】:

          猜你喜欢
          • 2021-05-08
          • 2020-10-21
          • 2014-05-15
          • 2015-02-06
          • 2021-05-22
          • 2015-04-19
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多