无法从NFC NDEF外部类型启动活动

时间:2014-12-10 10:46:06

标签: android android-activity nfc ndef

我已经写了一个包含外部记录类型的NFC标签。

使用SmartQ读取标记说明如下:

NDEF内容

Record Type:External
Type:/com.domainname:link-uuid
xyzxyz-xyzxyz

支持的技术

android.nfc.NfcA
android.nfc.tech.MifareUltralight
android.nfc.tech.Ndef

所以我非常确定我的标签写得正确。

我尝试在手机注意到某个标记时启动某个活动,并且只有当该类型为外部/com.domainname:link-uuid时才会过滤运行?

我的manifest.xml如下:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.domainname.android.interlink.nfc" >

    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />

    <uses-permission android:name="android.permission.NFC" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".NFCWrite"
            android:configChanges="orientation|keyboardHidden"
            android:label="@string/title_activity_nfcread"
            android:launchMode="singleTask" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>
        <activity
            android:name=".NFCRead"
            android:configChanges="orientation|keyboardHidden"
            android:label="@string/title_activity_nfcread"
            android:launchMode="singleTask" >
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
                <category android:name="android.intent.category.DEFAULT" />
                <data
                    android:host="ext"
                    android:pathPrefix="/com.domainname-uuid"
                    android:scheme="vnd.android.nfc" />
            </intent-filter>
        </activity>
    </application>

</manifest>

阅读活动是:

package com.domainname.android.interlink.nfc;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcManager;
import android.nfc.Tag;
import android.os.Bundle;
import android.os.Parcelable;
import android.util.Log;
import android.widget.Toast;

import java.io.UnsupportedEncodingException;
import java.util.Arrays;


public class NFCRead extends Activity {

    private static final int PENDING_INTENT_TECH_DISCOVERED = 1;
    private static final int PENDING_INTENT_NDEF_DISCOVERED = 1;
    private NfcAdapter mNfcAdapter;

    /**
     * Called when the activity is first created.
     */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        Log.i("NFCRead.onCreate","Running...");
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_nfcread);

        // Resolve the intent that started us:
        try {
            resolveIntent(this.getIntent());
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * Called when the activity gets focus.
     */
    @Override
    public void onResume() {
        Log.i("NFCRead.onResume","Running...");
        super.onResume();

        // Retrieve an instance of the NfcAdapter ("connection" to the NFC system service):
        NfcManager nfcManager = (NfcManager) this.getSystemService(Context.NFC_SERVICE);
        if (nfcManager != null) {
            mNfcAdapter = nfcManager.getDefaultAdapter();
        }

        if (mNfcAdapter != null) {
            // The isEnabled() method, if invoked directly after the NFC service
            // crashed, returns false regardless of the real setting (Android 2.3.3+).
            // As a nice side-effect it re-establishes the link to the correct instance
            // of NfcAdapter. Therefore, just execute this method twice whenever we
            // re-request the NfcAdapter, so we can be sure to have a valid handle.
            try {
                mNfcAdapter.isEnabled();
            } catch (NullPointerException e) {
                // Drop NullPointerException that is sometimes thrown
                // when NFC service crashed
            }
            try {
                mNfcAdapter.isEnabled();
            } catch (NullPointerException e) {
                // Drop NullPointerException that is sometimes thrown
                // when NFC service crashed
            }

            // Create a PendingIntent to handle discovery of Ndef and NdefFormatable tags:
            PendingIntent pi = createPendingResult(
                    PENDING_INTENT_NDEF_DISCOVERED,
                    new Intent(),
                    0);
            if (pi != null) {
                try {
                    // Enable foreground dispatch for Ndef and NdefFormatable tags:
                    mNfcAdapter.enableForegroundDispatch(
                            this,
                            pi,
                            new IntentFilter[]{
                                    new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
                            },
                            new String[][]{
                                    new String[]{"android.nfc.tech.Ndef"}
                            });
                } catch (NullPointerException e) {
                    // Drop NullPointerException that is sometimes thrown
                    // when NFC service crashed
                }
            }
        }
    }

    /**
     * Called when the activity loses focus.
     */
    @Override
    public void onPause() {
        Log.i("NFCRead.onPause","Running...");
        super.onPause();

        if (mNfcAdapter != null) {
            try {
                // Disable foreground dispatch:
                mNfcAdapter.disableForegroundDispatch(this);
            } catch (NullPointerException e) {
                // Drop NullPointerException that is sometimes thrown
                // when NFC service crashed
            }
        }
    }

    /**
     * Called when activity receives a new intent.
     */
    @Override
    public void onNewIntent(Intent data) {
        Log.i("NFCRead.onNewIntent","Running...");
        // Resolve the intent that re-invoked us:
        try {
            resolveIntent(data);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        }
    }

    /**
     * Called when a pending intent returns (e.g. our foreground dispatch).
     */
    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        Log.i("NFCRead.onActivityResult","Running...");
        switch (requestCode) {
            case PENDING_INTENT_TECH_DISCOVERED:
                // Resolve the foreground dispatch intent:
                try {
                    resolveIntent(data);
                } catch (UnsupportedEncodingException e) {
                    e.printStackTrace();
                }
                break;
        }
    }

    /**
     * Method to handle any intents that triggered our activity.
     * @param data                The intent we received and want to process.
     *
     */
    private void resolveIntent(Intent data) throws UnsupportedEncodingException {
        Log.i("resolveIntent","Running...");
        this.setIntent(data);

        String action = data.getAction();

        // We were started from the recent applications history: just show our main activity
        // (otherwise, the last intent that invoked us will be re-processed)
        if ((data.getFlags() & Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY) != 0) { return; }

        // Intent is a tag technology (we are sensitive to Ndef, NdefFormatable) or
        // an NDEF message (we are sensitive to URI records with the URI http://www.mroland.at/)
        if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
            Log.i("TECH_DISCOVERED", "TECH_DISCOVERED");
            if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
                // The reference to the tag that invoked us is passed as a parameter (intent extra EXTRA_TAG)
                Tag tag = data.getParcelableExtra(NfcAdapter.EXTRA_TAG);

                Log.i("NDEF Discovered:", tag.toString());

                // Let's read the tag whenever we are not in write mode

                // Retrieve information from tag and display it
                StringBuilder tagInfo = new StringBuilder();

                // Get tag's UID:
                byte[] uid = tag.getId();
                tagInfo.append("UID: ").append(new String(uid, "UTF-8")).append("\n\n");

                // Get tag's NDEF messages: The NDEF messages are passed as parameters (intent
                // extra EXTRA_NDEF_MESSAGES) and have to be casted into an NdefMessage array.
                Parcelable[] ndefRaw = data.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
                NdefMessage[] ndefMsgs = null;
                if (ndefRaw != null) {
                    ndefMsgs = new NdefMessage[ndefRaw.length];
                    for (int i = 0; i < ndefMsgs.length; ++i) {
                        // Cast each NDEF message from Parcelable to NdefMessage:
                        ndefMsgs[i] = (NdefMessage) ndefRaw[i];
                    }
                }

                // Find External records:

                if (ndefMsgs != null) {
                    // Iterate through all NDEF messages on the tag:
                    for (NdefMessage ndefMsg : ndefMsgs) {
                        // Get NDEF message's records:
                        NdefRecord[] records = ndefMsg.getRecords();

                        if (records != null) {
                            // Iterate through all NDEF records:
                            for (NdefRecord record : records) {
                                // Test if this record is a URI record:
                                if ((record.getTnf() == NdefRecord.TNF_EXTERNAL_TYPE)
                                        && Arrays.equals(record.getType(), NdefRecord.RTD_TEXT)) {
                                    // Get record payload:

                                    //                                    // Drop prefix identifier byte and convert remaining URL to string (UTF-8):
                                    //                                    String uri = new String(Arrays.copyOfRange(payload, 1, payload.length), Charset.forName("UTF-8"));

                                    // Use UriRecordHelper to decode URI record payload:
                                    String uuid = new String(record.getPayload(), "UTF-8");

                                    tagInfo.append("UUID: ");
                                    tagInfo.append(uuid);
                                    tagInfo.append("\n");
                                }
                            }
                        }
                    }
                }

                // Show our tag detected dialog (with the tag information passed as parameter):
                Toast toast = Toast.makeText(getApplicationContext(), tagInfo.toString(), Toast.LENGTH_SHORT);
                toast.show();
            }
        }
    }

}

我做错了,因为即使应用程序正在运行,也从未调用此活动。因此,我的应用程序永远不会读取标记。

我使用了教程中的大部分代码,由我修改,因此我可以学习它。我设法让它在编写标签时工作,但我无法阅读它们。

请有人指出我哪里出错了。感谢。

1 个答案:

答案 0 :(得分:1)

我已经解决了这个问题。

问题在于我在编写标签时将/放在域名前面。

所以我改变了:

NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE,"/com.domainname:link1-uuid".getBytes(),new byte[]{},msgBytes);

为:

NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_EXTERNAL_TYPE,"com.domainname:link1-uuid".getBytes(),new byte[]{},msgBytes);

活动现在开始完美。