简体   繁体   English

NFC标签检测未调用onNewIntent,而是从主活动启动

[英]NFC tag detection is not calling onNewIntent and it's Launching From Main Activity

I am new to NFC. 我是NFC的新手。 I tried to connect to NFC and share the text data from a device to another device. 我试图连接到NFC,并将文本数据从一台设备共享到另一台设备。

I install my application on both devices and in one device I open my application and start tapping the device to the another device in order to transmit data over Beam. 我将我的应用程序安装在两个设备上,并且在一个设备中打开我的应用程序,然后开始将该设备点击到另一台设备上,以便通过Beam传输数据。

On the other device, my application opens due to the Beam interaction. 在另一台设备上,由于Beam的交互,我的应用程序打开。 However, the activity is started with the default MAIN intent action and not with TAG_DISCOVERED (or similar NFC intent). 但是,活动是使用默认的MAIN意向操作而不是TAG_DISCOVERED(或类似的NFC意向)启动的。 Every time it does the same thing. 每次它都做同样的事情。

Also, it's not calling the onNewIntent() method. 另外,它没有调用onNewIntent()方法。 I tried to call onNewIntent from onCreate , but the intent action is still MAIN in that case. 我试图从onCreate调用onNewIntent ,但是在这种情况下,intent动作仍然很重要。 I expected to receive an NFC intent for the Beam interaction. 我期望收到与Beam互动的NFC意图。 So can you please tell me where did I go wrong? 那你能告诉我我哪里出问题了吗?

In this code I am not sharing the data. 在这段代码中,我不共享数据。 I just need the tag first. 我只需要标签。

Manifest: 表现:

<activity android:name="com.framentos.hellonfc.MainActivity"
        android:clearTaskOnLaunch="true"
        android:label="@string/app_name"
        android:launchMode="singleTop"
        android:screenOrientation="portrait" >
        <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.nfc.action.TECH_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.nfc.action.TAG_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
        <meta-data
            android:name="android.nfc.action.TECH_DISCOVERED"
            android:resource="@xml/nfc_tech_filter" />
</activity>

Java code: Java代码:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);
    ctx = this;
    // startHandler();
    _handler = new Handler();
    Button btnWrite = (Button) findViewById(R.id.button);
    message = (TextView) findViewById(R.id.nfcwriteTag);
    btnWrite.setOnClickListener(new View.OnClickListener() {
        @Override
        public void onClick(View v) {

        }
    });
    adapter = NfcAdapter.getDefaultAdapter(this);
    if (adapter == null) {
        message.setText("NFC is not supported on this device.");
    }
    if (adapter.isEnabled()) {
        message.setText("NFC is Enabled on this device.");
    } else {
        message.setText("Please enable NFC to communicate.");
    }
    pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
            getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    IntentFilter tagDetected = new IntentFilter(
            NfcAdapter.ACTION_NDEF_DISCOVERED);
    tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
    IntentFilter tagTech = new IntentFilter(
            NfcAdapter.ACTION_TECH_DISCOVERED);
    tagTech.addCategory(Intent.CATEGORY_DEFAULT);
    IntentFilter tagDetect = new IntentFilter(
            NfcAdapter.ACTION_TAG_DISCOVERED);
    tagDetect.addCategory(Intent.CATEGORY_DEFAULT);
    writeTagFilters = new IntentFilter[] { tagDetected, tagTech ,tagDetect};
    // handleIntent(getIntent());
}


@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    Log.i(getPackageName(), "on New Intent is called...!");
    handleIntent(getIntent());
}

public void onPause() {
    super.onPause();
    WriteModeOff();
}

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

private void WriteModeOn() {
    writeMode = true;
    adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters,
            null);
}

private void WriteModeOff() {
    writeMode = false;
    adapter.disableForegroundDispatch(this);
}

From the code that you posted in your question, I assume that you did not register your application to send a specific NDEF message. 根据您在问题中发布的代码,我假设您没有注册您的应用程序以发送特定的NDEF消息。 In that case, if your app is open on one device, Android will automatically Beam an NDEF message containing a URI record with the Play Store link of your app and an Android Application Record (AAR) to the other device. 在这种情况下,如果您的应用程序在一台设备上打开,则Android会自动将包含URI记录的NDEF消息与您的应用程序的Play商店链接和Android应用程序记录(AAR)发送到另一台设备。

So your second device will receive the following NDEF message: 因此,您的第二台设备将收到以下NDEF消息:

+---------------------------------------------------------------------------------------+
| WKT:URI | http://play.google.com/store/apps/details?id=your.package.name&feature=beam |
+---------------------------------------------------------------------------------------+
| EXT:android:com:pkg | your.package.name                                               |
+---------------------------------------------------------------------------------------+

What happens now if your app is not already open on the second device is, that the Android Application Record (second record) will force your app to be started. 如果您的应用尚未在第二个设备上打开,那么现在会发生的是,Android应用记录(第二条记录)将强制您的应用启动。 However, looking at your manifest, you do not have an intent filter that matches the first record of this NDEF message (the Play Store URL). 但是,查看清单时,您没有与该NDEF消息的第一条记录(Play商店URL)匹配的意图过滤器。 Consequently, Android thinks that you do not expect an NDEF message and uses the standard android.intent.action.MAIN (with category android.intent.category.LAUNCHER ) to start your app (or rather the first activity of your app that has an intent filter for action MAIN with category LAUNCHER ). 因此,Android认为您不希望收到NDEF消息,而是使用标准的android.intent.action.MAIN (类别为android.intent.category.LAUNCHER )来启动您的应用(或具有以下功能的应用的第一个活动)行动意图过滤器MAIN有类LAUNCHER )。

In order to receive an NFC intent together with the whole NDEF message in your app, you would need to define a proper intent filter that matches the first record in the above NDEF message: 为了在您的应用中接收NFC意图和整个NDEF消息,您需要定义一个与上面NDEF消息中的第一条记录匹配的适当的意图过滤器:

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED" />
    <category android:name="android.intent.category.DEFAULT" />
    <data android:scheme="http"
          android:host="play.google.com"
          android:pathPrefix="/store/apps/details?id=your.package.name" />
</intent-filter>

Now, Android will recognize that your app/activity is ready to receive an NFC intent and pass the NDEF_DISCOVERED intent to your activity. 现在,Android将识别出您的应用程序/活动已准备就绪,可以接收NFC意图,并将NDEF_DISCOVERED意图传递给您的活动。 Note that you still won't receive that intent through onNewIntent() if your app is not already running. 请注意,如果您的应用尚未运行,您仍然不会通过onNewIntent()收到该意图。 Instead you can get the intent that started your activity with the activity's getIntent() method. 相反,您可以使用活动的getIntent()方法获取启动活动的意图。 Eg in onCreate / onStart / onResume , you could use 例如在onCreate / onStart / onResume ,您可以使用

Intent intent = getIntent();
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
    NdefMessage ndefMessage = null;
    Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
    if ((rawMessages != null) && (rawMessages.length > 0)) {
        ndefMessage = (NdefMessage)rawMessages[0];
    }

    // TODO: do something with the received NDEF message
}

to get the intent and the NDEF message. 获取意图和NDEF消息。

Regarding the intent filters you already have in your manifest: 关于清单中已经包含的意图过滤器:

  1. NDEF_DISCOVERED : NDEF_DISCOVERED

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

    An NDEF_DISCOVERED intent filter without a <data ... /> tag will never trigger on many NFC devices. 没有<data ... />标记的NDEF_DISCOVERED意向过滤器永远不会在许多NFC设备上触发。 You should always define what specific data you expect to be present in the launching NDEF record. 您应该始终定义期望在启动NDEF记录中出现的特定数据。

  2. TECH_DISCOVERED : TECH_DISCOVERED

     <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> 

    You should only use this intent filter if you wan't you application to be started upon detection of a certain NFC tag technology (you define the specific technologies in the nfc_tech_filter.xml file. For your Beam scenario, you would not use such an intent filter. Btw. the <category ...> tag is not used for this intent filter. 仅当您不希望在检测到某种NFC标签技术时就启动应用程序时才应使用此意图过滤器(您在nfc_tech_filter.xml文件中定义了特定技术。对于Beam场景,您不会使用这种意图顺便说一句, <category ...>标签未用于此意图过滤器。

  3. TAG_DISCOVERED : TAG_DISCOVERED

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

    This intent filter should normally not be used in the manifest. 该意图过滤器通常不应在清单中使用。 It is meant as a fallback that triggers if no other app could possibly handle a detected NFC tag. 这意味着如果没有其他应用程序可能会处理检测到的NFC标签,则触发后备事件。 Using this can lead to bad user-experience (eg your app being started for tags it can't or does not actually want to handle). 使用此选项可能会导致不良的用户体验(例如,您的应用因其无法或实际上不想处理的标签而启动)。 It is primarily available for backward compatibility with API level 9 (?). 它主要用于与API级别9(?)向后兼容。

In order to also catch the NFC intents if your activity is already started, you could register for the foreground dispatch like this (in the onResume method): 为了也可以在活动已经开始时捕获NFC意图,可以像这样(在onResume方法中)注册前台调度:

PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);

That way, you will receive any NFC discovery events that occur while your activity is in the foreground in your activity's onNewIntent method. 这样,您将收到在活动的onNewIntent方法中活动处于前台时发生的所有NFC发现事件。 They will be dispatched through an ACTION_TAG_DISCOVERED intent. 它们将通过ACTION_TAG_DISCOVERED意图分派。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM