【问题标题】:NFC class' onNewIntent always runs after 3rd scanNFC 类的 onNewIntent 始终在第 3 次扫描后运行
【发布时间】:2015-01-07 00:43:14
【问题描述】:

我有一个从 NFC 标签捕获数据的 Activity。为了读取标签的内容,我必须扫描标签 3 次。

我希望在第一次扫描时提取标签的内容。

在第一次扫描时,活动似乎进入了以下生命周期方法:

onCreate -> onResume -> enableForegroundMode()

第二次扫描:

onPause -> disableForegroundMode() -> onCreate -> onResume -> enableForegroundMode()

然后在最后的第三次扫描:

onPause -> disableForegroundMode() -> onNewIntent

谁能告诉我为什么会发生这种情况以及为什么我必须总是扫描 3 次?

下面是我的班级和堆栈跟踪

提前致谢

public class NfcActivity extends Activity {

    private static final String TAG = NfcActivity.class.getName();

    protected NfcAdapter nfcAdapter;
    protected PendingIntent nfcPendingIntent;

    Handler handler;
    Runnable runnable;

    Parcelable[] messages;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nfcactivitylayout);
        Log.e(TAG, "oncreate");
        // initialize NFC
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    }

    public void enableForegroundMode() {
        Log.e(TAG, "enableForegroundMode");

        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); // filter for all
        IntentFilter[] writeTagFilters = new IntentFilter[] {tagDetected};
        nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
    }

    public void disableForegroundMode() {
        Log.e(TAG, "disableForegroundMode");

        nfcAdapter.disableForegroundDispatch(this);
    }

    @Override
    public void onNewIntent(Intent intent) {
        Log.e(TAG, "onNewIntent");

        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {          
            //TextView textView = (TextView) findViewById(R.id.title);

            //textView.setText("Hello NFC!");

            messages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (messages != null) {
                setContentView(R.layout.successfulnfc);

                Log.e(TAG, "Found " + messages.length + " NDEF messages"); // is almost always just one

                vibrate(); // signal found messages :-)



                initHandler();
                handler.postDelayed(runnable,  2000);




            }
        } else {
            // ignore
        }
    }

    @Override
    protected void onResume() {
        Log.e(TAG, "onResume");

        super.onResume();

        enableForegroundMode();
    }

    @Override
    protected void onPause() {
        Log.e(TAG, "onPause");

        super.onPause();

        disableForegroundMode();

        if(handler != null){
            handler.removeCallbacks(runnable);
        }
    }

    private void vibrate() {
        Log.e(TAG, "vibrate");

        Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE) ;
        vibe.vibrate(500);
    }





}

.

01-05 12:56:48.849: E/com.carefreegroup.rr3.NfcActivity(12362): oncreate
01-05 12:56:48.859: E/com.carefreegroup.rr3.NfcActivity(12362): onResume
01-05 12:56:48.859: E/com.carefreegroup.rr3.NfcActivity(12362): enableForegroundMode
01-05 12:56:50.099: E/wpa_supplicant(1113): send_and_recv error 0 - cmd 32
01-05 12:56:50.099: E/wpa_supplicant(1113): send_and_recv error 0 - cmd 50
01-05 12:56:50.099: E/wpa_supplicant(1113): send_and_recv error 0 - cmd 32
01-05 12:56:50.099: E/wpa_supplicant(1113): send_and_recv error 0 - cmd 50
01-05 12:56:50.699: E/MP-Decision(1724): Update arg 1
01-05 12:56:52.679: E/MP-Decision(1724): Update arg 2
01-05 12:56:52.699: E/com.carefreegroup.rr3.NfcActivity(12362): onPause
01-05 12:56:52.699: E/com.carefreegroup.rr3.NfcActivity(12362): disableForegroundMode
01-05 12:56:52.719: E/com.carefreegroup.rr3.NfcActivity(12362): oncreate
01-05 12:56:52.719: E/com.carefreegroup.rr3.NfcActivity(12362): onResume
01-05 12:56:52.719: E/com.carefreegroup.rr3.NfcActivity(12362): enableForegroundMode
01-05 12:56:53.689: E/MP-Decision(1724): Update arg 1
01-05 12:56:55.009: E/MP-Decision(1724): Update arg 2
01-05 12:56:55.009: E/com.carefreegroup.rr3.NfcActivity(12362): onPause
01-05 12:56:55.009: E/com.carefreegroup.rr3.NfcActivity(12362): disableForegroundMode
01-05 12:56:55.019: E/com.carefreegroup.rr3.NfcActivity(12362): onNewIntent
01-05 12:56:55.059: E/com.carefreegroup.rr3.NfcActivity(12362): Found 1 NDEF messages
01-05 12:56:55.059: E/com.carefreegroup.rr3.NfcActivity(12362): vibrate
01-05 12:56:55.059: E/com.carefreegroup.rr3.NfcActivity(12362): onResume
01-05 12:56:55.059: E/com.carefreegroup.rr3.NfcActivity(12362): enableForegroundMode
01-05 12:56:56.009: E/MP-Decision(1724): Update arg 1
01-05 12:56:57.059: E/com.carefreegroup.rr3.NfcActivity(12362): about to process tag
01-05 12:56:57.089: E/com.carefreegroup.rr3.NfcActivity(12362): Found 1 records in message 0
01-05 12:56:57.089: E/com.carefreegroup.rr3.NfcActivity(12362):  Record #0 is of class TextRecord
01-05 12:56:57.099: E/com.carefreegroup.rr3.NfcActivity(12362): payload = 1,10,1074,Kelly Waugh
01-05 12:56:57.109: E/MP-Decision(1724): Update arg 2
01-05 12:56:57.129: E/com.carefreegroup.rr3.NfcActivity(12362): onPause
01-05 12:56:57.129: E/com.carefreegroup.rr3.NfcActivity(12362): disableForegroundMode

.

<activity
    android:name=".NfcActivity"
    android:screenOrientation="portrait" >
    <intent-filter>


        <action android:name="android.nfc.action.NDEF_DISCOVERED" />

        <category android:name="android.intent.category.DEFAULT" />

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

[编辑1]

Intent i;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nfcactivitylayout);
        Log.e(TAG, "oncreate");
        // initialize NFC
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        i = getIntent();

        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(i.getAction())) {           
            //TextView textView = (TextView) findViewById(R.id.title);

            //textView.setText("Hello NFC!");

            messages = i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (messages != null) {
                setContentView(R.layout.successfulnfc);

                Log.e(TAG, "Found " + messages.length + " NDEF messages"); // is almost always just one

                vibrate(); // signal found messages :-)



                initHandler();
                handler.postDelayed(runnable,  2000);




            }
        } else {
            // ignore
        }


    }

[编辑 3]

public class NfcActivity extends Activity {

    private static final String TAG = NfcActivity.class.getName();

    protected NfcAdapter nfcAdapter;
    protected PendingIntent nfcPendingIntent;

    Handler handler;
    Runnable runnable;

    Parcelable[] messages;

    Intent i;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nfcactivitylayout);
        Log.e(TAG, "oncreate");
        // initialize NFC
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, this.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

        i = getIntent();

        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(i.getAction())) {          
            //TextView textView = (TextView) findViewById(R.id.title);

            //textView.setText("Hello NFC!");

            messages = i.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            if (messages != null) {
                setContentView(R.layout.successfulnfc);

                Log.e(TAG, "Found " + messages.length + " NDEF messages"); // is almost always just one

                vibrate(); // signal found messages :-)



                initHandler();
                handler.postDelayed(runnable,  2000);




            }
        } else {
            // ignore
        }


    }

    public void enableForegroundMode() {
        Log.e(TAG, "enableForegroundMode");

        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED); // filter for all
        IntentFilter[] writeTagFilters = new IntentFilter[] {tagDetected};
        nfcAdapter.enableForegroundDispatch(this, nfcPendingIntent, writeTagFilters, null);
    }

    public void disableForegroundMode() {
        Log.e(TAG, "disableForegroundMode");

        nfcAdapter.disableForegroundDispatch(this);
    }

    @Override
    public void onNewIntent(Intent intent) {
        Log.e(TAG, "onNewIntent");

        Intent processPayloadIntent = new Intent(NfcActivity.this, NfcscannerActivity.class);

        processPayloadIntent.setAction("QRCODE_ACTION"); 
        processPayloadIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
        startActivity(processPayloadIntent);
    }

    @Override
    protected void onResume() {
        Log.e(TAG, "onResume");

        super.onResume();

        enableForegroundMode();
    }

    @Override
    protected void onPause() {
        Log.e(TAG, "onPause");

        super.onPause();

        disableForegroundMode();

        if(handler != null){
            handler.removeCallbacks(runnable);
        }
    }

    private void vibrate() {
        Log.e(TAG, "vibrate");

        Vibrator vibe = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE) ;
        vibe.vibrate(500);
    }


    public void initHandler(){

          handler = new Handler();
          runnable = new Runnable() {
                public void run() {
                    processTag();

                }

                private void processTag() {
                    Log.e(TAG, "about to process tag");

                    // parse to records
                    for (int i = 0; i < messages.length; i++) {
                        try {
                            List<Record> records = new Message((NdefMessage)messages[i]);

                            Log.e(TAG, "Found " + records.size() + " records in message " + i);

                            for(int k = 0; k < records.size(); k++) {
                                Log.e(TAG, " Record #" + k + " is of class " + records.get(k).getClass().getSimpleName());

                                Record record = records.get(k);

                                NdefRecord ndefRecord = record.getNdefRecord();

                                byte[] arr = ndefRecord.getPayload();

                                String payload = new String(arr);

                                payload = payload.substring(3, payload.length());

                                Log.e(TAG, "payload = " + payload);

                                Intent processPayloadIntent = new Intent(NfcActivity.this, NfcscannerActivity.class);
                                processPayloadIntent.putExtra("payload", payload);
                                processPayloadIntent.setAction("NFC"); 
                                processPayloadIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
                                startActivity(processPayloadIntent);


                            }
                        } catch (Exception e) {
                            Log.e(TAG, "Problem parsing message", e);
                        }

                    }

                }
            };

        }


}

【问题讨论】:

    标签: android nfc


    【解决方案1】:

    首先,onCreate() 是获取 NFC Intent 的一种完全有效的方式。如果 Android 将 Intent 传递给您的 Activity 的现有实例,您只会获得 onNewIntent()。您需要处理NDEF_DISCOVERED Intent 进入onCreate() 以及 当它进入onNewIntent() 的情况。您可以在 this one 之类的示例应用程序中看到这一点,我相信您已经在 a book 中进行了介绍。 :-)

    您可能希望考虑做的另一件事是在活动的清单条目上使用android:launchMode="singleTask",以确保只使用该活动的一个副本。这也显示在同一个示例应用程序中。

    【讨论】:

    • :) 是的,我有你的书,不是吗。我已经修改了清单并将 ACTION_TAG_DISCOVERED 代码添加到 onCreate。我不确定这是否是你的意思? onCreate 仍未处理 NFC 标签,并且 onNewIntent 仍在运行。当 NFC 代码现在在 onCreate 和 OnNewIntent 中时,为什么会这样?
    • 对不起,马克,我错过了 NDEF_DISCOVERED 部分。现在是第一次扫描。如果您不介意检查它是否已按照您的建议实现,我现在将发布完整的代码?如果我快速连续扫描标签两次,则 onNewIntent 运行并且应用程序冻结。我不希望标签被处理两次,所以我应该从 onNewIntent 中删除处理标签的代码吗?
    • @turtleboy:“如果您不介意检查它是否已按照您的建议实施?” -- 我将有一个您在onCreate()onNewIntent() 之间复制的业务逻辑的通用实现。 “我不希望标签被处理两次,所以我应该从 onNewIntent 中删除处理标签的代码吗?” -- 如果用户想要处理两个不同的标签,不是快速连续,而是在您的应用程序仍在运行时怎么办?你最好弄清楚你在哪里以及为什么冻结。
    • 我已经发布了我现在在编辑 3 中所做的代码更改。我已将 NFC 捕获代码放在 onCreate 中。 onCreate 然后更改视图,处理标签并将内容发送到另一个活动以发送到服务器。 onNewIntent 只是调用这个相同的 Activity 但具有不同的操作,因此不处理标签数据或发送到服务器。这背后的原因是我的应用程序是针对护理行业的。护理人员在客户家扫描标签以将其记录到通话中。所以看护人可以在上午 10 点扫描进来,然后在上午 11 点扫描出去。如果她在上午 10 点误扫描,我不希望应用程序让她登录然后立即退出
    • 我尝试扫描标签 A 然后扫描标签 B,它似乎工作正常。编辑 3 会是一个好的解决方案吗?
    猜你喜欢
    • 1970-01-01
    • 2012-01-04
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-03-02
    • 1970-01-01
    • 2021-12-10
    相关资源
    最近更新 更多