NFC标签检测不会调用onNewIntent并且它是从主活动启动的

时间:2014-03-20 11:27:36

标签: android nfc nfc-p2p android-beam android-applicationrecord

我是NFC新手。我尝试连接到NFC并将文本数据从设备共享到另一台设备。

我在两台设备和一台设备上安装我的应用程序我打开应用程序并开始将设备点击到另一台设备,以便通过Beam传输数据。

在另一台设备上,我的应用程序因Beam交互而打开。但是,活动是使用默认的MAIN意图操作启动的,而不是使用TAG_DISCOVERED(或类似的NFC意图)启动的。每次它做同样的事情。

此外,它没有调用onNewIntent()方法。我试图从onNewIntent调用onCreate,但在这种情况下,意图操作仍然是MAIN。我希望能够获得Beam交互的NFC意图。那么请你告诉我哪里出错了?

在此代码中,我不共享数据。我首先需要标签。

清单:

<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代码:

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

1 个答案:

答案 0 :(得分:27)

根据您在问题中发布的代码,我假设您没有注册您的应用程序以发送特定的NDEF消息。在这种情况下,如果您的应用在一台设备上打开,Android会自动将包含您的应用的Play商店链接和Android应用记录(AAR)的URI记录的NDEF消息发送到另一台设备。

因此,您的第二台设备将收到以下NDEF消息:

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

如果您的应用尚未在第二台设备上打开,现在会发生什么,即Android应用程序记录(第二条记录)将强制您的应用程序启动。但是,查看清单时,您没有与此NDEF消息的第一条记录(Play商店URL)匹配的intent过滤器。因此,Android认为您不期望NDEF消息并使用标准android.intent.action.MAIN(类别为android.intent.category.LAUNCHER)来启动您的应用(或者更确切地说是您的应用的第一个具有意图过滤器操作的活动MAINLAUNCHER}。

为了在您的应用中接收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>

现在,Android会识别您的应用/活动已准备好接收NFC意图并将NDEF_DISCOVERED意图传递给您的活动。请注意,如果您的应用尚未运行,您仍然无法通过onNewIntent()收到该意图。相反,您可以通过活动的getIntent()方法获得启动活动的意图。例如。在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
}

获取意图和NDEF消息。

关于清单中已有的意图过滤器:

  1. NDEF_DISCOVERED

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

    没有NDEF_DISCOVERED标记的<data ... />意图过滤器永远不会在许多NFC设备上触发。您应该始终定义您希望在启动NDEF记录中出现的具体数据。

  2. 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" />
    

    如果您希望在检测到某种NFC标签技术时启动应用程序(您在nfc_tech_filter.xml文件中定义特定技术),则应该只使用此意图过滤器。对于您的Beam场景,你不会使用这样的意图过滤器。顺便说一下。<category ...>标签不用于这个意图过滤器。

  3. TAG_DISCOVERED

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

    通常不应在清单中使用此意图过滤器。它意味着如果没有其他应用程序可能处理检测到的NFC标记,则会触发回退。使用此功能可能会导致糟糕的用户体验(例如,您的应用是针对标签启动的,它实际上并不是或者实际上并不想处理)。它主要用于向后兼容API级别9(?)。

  4. 如果你的活动已经开始,为了也能捕获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);
    

    这样,您就会收到活动在活动onNewIntent方法中处于前台时发生的任何NFC发现事件。他们将通过ACTION_TAG_DISCOVERED意图发送。