【问题标题】:NFC-Reader: disableForegroundDispatch() doesn't workNFC 阅读器:disableForegroundDispatch() 不起作用
【发布时间】:2021-12-08 13:47:32
【问题描述】:

我正在开发一个需要使用 NFC-Reader 的应用程序。但是,NFC-Reader 应该只在使用 Scan Activity 时运行。

我已经实现了一个onPause() 方法,包括disableForegroundDispatch(),当切换到可以通过验证的不同活动时也会执行该方法

System.out.println("pause!!!");

令人惊讶的是,至少对我而言,仍然能够在不同的活动中扫描 NFC 芯片,然后将其转发回扫描活动。

非常感谢任何帮助!!! :D

这是源代码(Scan.activity),以防有助于解决问题):

package com.example.bnm_10112021;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;

import android.app.Activity;
import android.content.Intent;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.MenuItem;


import com.google.android.material.bottomnavigation.BottomNavigationView;
import com.google.android.material.bottomsheet.BottomSheetDialog;
import com.google.android.material.navigation.NavigationBarView;

import android.app.PendingIntent;
import android.content.Context;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Parcelable;
import android.util.Log;
import android.view.View;
import android.widget.Button;
import android.widget.LinearLayout;
import android.widget.TextView;

import org.w3c.dom.Text;

import java.io.UnsupportedEncodingException;
import java.util.concurrent.ExecutionException;

public class Scan extends AppCompatActivity {


    public static final String Error_Detected = "No NFC Tag Detected";
    public static final String Write_Success = "Text Written Successfully!";
    public static final String Write_Error = "Error during Writing, Try Again!";
    NfcAdapter nfcAdapter;
    PendingIntent pendingIntent;
    IntentFilter writingTagFilters[];
    boolean writeMode;
    Tag myTag;
    Context context;
    TextView edit_message;
    TextView nfc_contents;
    Button ActivateButton;

    BottomNavigationView bottomNavigationItemView;

    **//Erstellung des dbConnection-Objekts**
    public DatabaseConnection dbConnector = new DatabaseConnection();




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

        bottomNavigationItemView = findViewById(R.id.navigator);
        bottomNavigationItemView.setSelectedItemId(R.id.scan);

        nfc_contents = (TextView) findViewById(R.id.nfc_contents);
        context = this;
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        /**if(nfcAdapter == null){
            Toast.makeText(this, "This device does not support NFC", Toast.LENGTH_SHORT).show();
            finish();
        }**/
        readFromIntent(getIntent());readFromIntent(getIntent());
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);




    //DOKU, VERALTET!!!!
        bottomNavigationItemView.setOnItemSelectedListener(new NavigationBarView.OnItemSelectedListener() {
            @Override
            public boolean onNavigationItemSelected(@NonNull MenuItem item) {
                int id = item.getItemId();
                switch (id){
                    case R.id.settings:
                        startActivity(new Intent(getApplicationContext(),Settings.class));
                        overridePendingTransition(0,0);
                        return true;
                    case R.id.stats:
                        startActivity(new Intent(getApplicationContext(),Statistics.class));
                        overridePendingTransition(0,0);
                        return true;
                    case R.id.scan:
                        return true;
                    case R.id.wash:
                        startActivity(new Intent(getApplicationContext(),Wash.class));
                        overridePendingTransition(0,0);
                        return true;
                    case R.id.mycloset:
                        startActivity(new Intent(getApplicationContext(),MyCloset.class));
                        overridePendingTransition(0,0);
                        return true;
                }
                return false;
            }
        });
    }

    //String: Parameter an doInBackground; Void: Parameter an publishProgress bzw. onProgressUpdate; String[]: Parameter von doInBackground an onPostExecute
    private class DauertLange extends AsyncTask<String, Void, String[]> {

        @Override
        protected void onPreExecute() {
            super.onPreExecute();
            //Loading Animation
            System.out.println("Vorher");
        }

        @Override
        protected String[] doInBackground(String... pStrings) {
            //publishProgress();
            String sN = pStrings[0];
            String tN = pStrings[1];
            String bd = pStrings[2];
            String z = pStrings[3];
            System.out.println(tN);

            String[] rueckgabe = dbConnector.select(sN,tN,bd,z);
            return rueckgabe;
        }

       /** protected void onProgressUpdate(){
            bottomSheetDialog.setContentView(R.layout.layout_bottom_sheet_loading);

        }**/
        protected void onPostExecute() {
            super.onPreExecute();
            //Loading Animation
            System.out.println("Nacher");
        }
    }

    private void readFromIntent(Intent intent) {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
            Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            NdefMessage[] msgs = null;
            if (rawMsgs != null) {
                msgs = new NdefMessage[rawMsgs.length];
                for (int i = 0; i < rawMsgs.length; i++) {
                    msgs[i] = (NdefMessage) rawMsgs[i];
                }
            }
            buildTagViews(msgs);
        }
    }
    private void buildTagViews(NdefMessage[] msgs) {
        if (msgs == null || msgs.length == 0) return;

        String text = "";
        byte[] payload = msgs[0].getRecords()[0].getPayload();
        String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; // Get the Text Encoding
        int languageCodeLength = payload[0] & 0063; // Get the Language Code, e.g. "en"

        try {
            // Get the Text
            text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
        } catch (UnsupportedEncodingException e) {
            Log.e("UnsupportedEncoding", e.toString());
        }

        System.out.println(text);
        String chipID = text;


        /**String rueckgabe = dbConnector.select("Seriennummer","Chips","NFCID = '" + chipID + "'");
        System.out.println(rueckgabe);
        String ausgabe = dbConnector.select("Art","Kleidungstypen","Seriennummer = '" + rueckgabe + "'");
        System.out.println(ausgabe);
        nfc_contents.setText(ausgabe);**/

        final BottomSheetDialog bottomSheetDialog = new BottomSheetDialog(

                Scan.this, R.style.BottomSheetDialogTheme
        );
        View bottomSheetView = LayoutInflater.from(getApplicationContext())
                .inflate(
                        R.layout.layout_bottom_sheet,
                        null

                );
        bottomSheetDialog.setContentView(bottomSheetView);
        bottomSheetDialog.show();

        //bottomSheetDialog.setContentView(R.layout.layout_bottom_sheet_loading);

        LinearLayout ll = bottomSheetView.findViewById(R.id.bottomSheetContainer);

        //Textfelder identifzieren
        TextView tvBezeichnung = ll.findViewById(R.id.tvBezeichnung);
        TextView tvMarke = ll.findViewById(R.id.tvMarke);
        TextView tvColor = ll.findViewById(R.id.tvColor);
        TextView tvSize = ll.findViewById(R.id.tvSize);
        TextView tvHerkunft = ll.findViewById(R.id.tvHerkunft);


        //Datenbankverbindung über AsyncTask mit Array als Rückgabe
        String[] farbe = new String[10];
        try {
            farbe = new DauertLange().execute("Kleidungstypen.Bezeichnung, Kleidungstypen.Marke, Kleidungstypen.Farbe, Kleidungstypen.Size, Kleidungstypen.Herkunft","Kleidungstypen INNER JOIN Chips ON Kleidungstypen.Seriennummer = Chips.Seriennummer", "NFCID = '" + chipID + "'","5").get();
        } catch (ExecutionException e) {
            e.printStackTrace();
            bottomSheetDialog.dismiss();
        } catch (InterruptedException e) {
            e.printStackTrace();
            bottomSheetDialog.dismiss();
        }

        //Inhalte der Textfelder mit Daten aus DB setzen
        tvBezeichnung.setText(farbe[0]);
        tvMarke.setText(farbe[1]);
        tvColor.setText(farbe[2]);
        tvSize.setText(farbe[3]);
        tvHerkunft.setText("Made in " + farbe[4]);

        //RoundedImageView img = ll.findViewById(R.id.image111);
        //img.setImageURI(uri);


        bottomSheetView.findViewById(R.id.addToCloset).setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                bottomSheetDialog.dismiss();
            }
        });
        //bottomSheetDialog.setContentView(bottomSheetView);
        //bottomSheetDialog.show();

    }

    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        setIntent(intent);
        readFromIntent(intent);
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
            myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        }
    }

    @Override
    public void onPause(){
        System.out.println("pause!!!");
        super.onPause();
        nfcAdapter.disableForegroundDispatch(this);
        nfcAdapter.disableReaderMode(this);
    }

    @Override
    public void onResume(){
        super.onResume();
        nfcAdapter.enableForegroundDispatch(this, pendingIntent, writingTagFilters, null);
    }



}

【问题讨论】:

  • 我对@9​​87654325@ 的理解是,当 Activity 处于前台时,它会优先处理您的 Activity 处理 NFC 意图。例如。如果发现一个标签可以由多个应用程序处理,那么您首先要处理它。因此,禁用前台调度会禁用该优先级,但不会阻止将 NFC 意图发送到您的应用程序。如果您只想在前台使用 NFC,那么听起来您应该使用阅读器模式而不是注册意图。
  • @Michael 我需要改变什么才能做到这一点?
  • 在适当的时候(例如 onResume 和 onPause)致电 enableReaderModedisableReaderModeenableReaderMode 的参数之一是当发现 NFC 标签时将调用的回调。
  • @Michael 我之前已经尝试过并实现了nfcAdapter.disableReaderMode(this) 行,这并没有改变任何东西。它仍然执行 NFC 方法!
  • 从清单中删除所有 NFC 意图过滤器。并摆脱前台调度代码。

标签: java android-studio nfc bottomnavigationview onpause


【解决方案1】:

如果您真的想让扫描看起来只发生在您的一个活动中,那么您真正需要做的就是在所有其他活动中静默处理 NFC。

这是因为 NFC 事件实际上是在系统 NFC 应用程序/服务中检测和处理的,如果您没有要求将它们转发到您的前台应用程序,那么系统 NFC 应用程序/服务可能会处理标签数据自己并用它做一些事情(打开另一个应用程序或打开它自己的对话框来显示标签的内容)。

因此,仅在您的扫描活动中禁用它只是允许其他操作发生,而不是实际停止 NFC 处理的发生。

由于enableForegroundDispatch 的旧 API 对您的控制很少,并且无法控制系统生成的 NFC 事件声音,因此您需要使用更好的 enableReaderMode API。

所以在所有活动中enableReaderModeonResumedisableReaderModeonPause。您可以将其设置为捕获所有标签技术并关闭 NFC 声音。

然后,当您希望 Activity 不响应 NFC 标签时,onTagDiscovered 只是一个空方法。因此系统会默默地向您的 App 发送任何发现的 Tag 事件以供其忽略。

然后在“Scan.activity”中,onTagDiscovered 方法会执行您的 NFC 处理。 (然后应该做声音通知本身而不是系统)

当您的应用处于前台时,当 NFC 打开时,您还应该有一个广播接收器到enableReaderMode(使用 NFC 快速设置不会暂停您的应用)。

您不需要任何 Intent 过滤器,除非您希望您的应用由具有特定类型数据的 NFC 卡启动。

此答案中的示例广播接收器和enableReaderMode https://stackoverflow.com/a/59397667/2373819

在所有非 NFC 活动中静默捕获所有 NFC 事件是我在我的应用程序中执行此操作的方式(您可以通过使用用于静默处理 NFC 的代码扩展普通 Activity 类来创建模板类,然后将其用作Activity 类的基础)

【讨论】:

  • 不幸的是,我还没有创建 onTagDiscovered 方法。我必须在哪里实现它到我现有的 Scan.activity 中?
  • 你会implements NfcAdapter.ReaderCallback 然后在所有活动中,但是scan.activity 中的代码会让你的标签在这个解决方案中读/写代码,所有其他活动都是一个空方法。跨度>
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-08-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-10-30
  • 1970-01-01
相关资源
最近更新 更多