NFC 读取不工作

发布于 2024-11-10 08:26:00 字数 4095 浏览 0 评论 0原文

我是开发 Android 应用程序的新手。目前我正在尝试开发自己的标签阅读器,可以读取 MiFare Ultralight 标签。

但我无法读取标签,因为 NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) 总是返回 false。有人可以帮我吗?

NfcReader.java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mText = (TextView) findViewById(R.id.text);
    mText.setText("Scan a tag");

    mAdapter = NfcAdapter.getDefaultAdapter();

    // Create a generic PendingIntent that will be deliver to this activity. The NFC stack
    // will fill in the intent with the details of the discovered tag before delivering to
    // this activity.
    mPendingIntent = PendingIntent.getActivity(this, 0,
            new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

    // Setup an intent filter for all MIME based dispatches
    IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
    try {
        ndef.addDataType("*/*");
    } catch (MalformedMimeTypeException e) {
        throw new RuntimeException("fail", e);
    }
    mFilters = new IntentFilter[] {
            ndef,
    };

    // Setup a tech list for all NfcF tags
    mTechLists = new String[][] { new String[] { NfcF.class.getName() } };

    Intent intent = getIntent();

    getNdefMessages(intent);
}

public void getNdefMessages(Intent intent) {
    // Parse the intent
    NdefMessage[] msgs = null;
    String action = intent.getAction();
    if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsgs != null) {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; i++) {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }
        }
        else {
        // Unknown tag type
            byte[] empty = new byte[] {};
            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
            NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
            msgs = new NdefMessage[] {msg};
        }
    }        
    else {
        //Log.e(TAG, "Unknown intent " + intent);
        finish();
    }
}

@Override
public void onResume() {
    super.onResume();
    mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}

@Override
public void onNewIntent(Intent intent) {
    Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
    getNdefMessages(intent);            
}

@Override
public void onPause() {
    super.onPause();
    //mAdapter.disableForegroundDispatch(this);
    throw new RuntimeException("onPause not implemented to fix build");
}

Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.nfc.reader"
      android:versionCode="1"
      android:versionName="1.0">

    <uses-permission android:name="android.permission.NFC" />
    <uses-sdk android:minSdkVersion="10"/>
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name="NfcReader"
            android:theme="@android:style/Theme.NoTitleBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED"/>
                <data android:mimeType="text/plain" />
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>

            <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfctech" />
        </activity>

    </application>

</manifest> 

I am newbie in developing android application. Currently I am trying to develop my own tag reader which can read MiFare Ultralight tag.

BUt I failed to read the tag as NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) always return false. Could somebody help me out?

NfcReader.java

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.main);

    mText = (TextView) findViewById(R.id.text);
    mText.setText("Scan a tag");

    mAdapter = NfcAdapter.getDefaultAdapter();

    // Create a generic PendingIntent that will be deliver to this activity. The NFC stack
    // will fill in the intent with the details of the discovered tag before delivering to
    // this activity.
    mPendingIntent = PendingIntent.getActivity(this, 0,
            new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

    // Setup an intent filter for all MIME based dispatches
    IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
    try {
        ndef.addDataType("*/*");
    } catch (MalformedMimeTypeException e) {
        throw new RuntimeException("fail", e);
    }
    mFilters = new IntentFilter[] {
            ndef,
    };

    // Setup a tech list for all NfcF tags
    mTechLists = new String[][] { new String[] { NfcF.class.getName() } };

    Intent intent = getIntent();

    getNdefMessages(intent);
}

public void getNdefMessages(Intent intent) {
    // Parse the intent
    NdefMessage[] msgs = null;
    String action = intent.getAction();
    if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsgs != null) {
            msgs = new NdefMessage[rawMsgs.length];
            for (int i = 0; i < rawMsgs.length; i++) {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }
        }
        else {
        // Unknown tag type
            byte[] empty = new byte[] {};
            NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);
            NdefMessage msg = new NdefMessage(new NdefRecord[] {record});
            msgs = new NdefMessage[] {msg};
        }
    }        
    else {
        //Log.e(TAG, "Unknown intent " + intent);
        finish();
    }
}

@Override
public void onResume() {
    super.onResume();
    mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
}

@Override
public void onNewIntent(Intent intent) {
    Log.i("Foreground dispatch", "Discovered tag with intent: " + intent);
    getNdefMessages(intent);            
}

@Override
public void onPause() {
    super.onPause();
    //mAdapter.disableForegroundDispatch(this);
    throw new RuntimeException("onPause not implemented to fix build");
}

Manifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
      package="com.nfc.reader"
      android:versionCode="1"
      android:versionName="1.0">

    <uses-permission android:name="android.permission.NFC" />
    <uses-sdk android:minSdkVersion="10"/>
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

    <application android:icon="@drawable/icon" android:label="@string/app_name">
        <activity android:name="NfcReader"
            android:theme="@android:style/Theme.NoTitleBar">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />
                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>

            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED"/>
                <data android:mimeType="text/plain" />
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>

            <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfctech" />
        </activity>

    </application>

</manifest> 

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

櫻之舞 2024-11-17 08:26:00

当检测到带有 NDEF 消息的标签时,android 会查找任何具有带有意图过滤器的 Activity 的应用程序,以执行操作“android.nfc.action.NDEF_DISCOVERED”。如果两个或多个应用程序可以处理此操作,则具有最精确过滤器的应用程序会接收意图。当找到具有相同过滤器的应用程序时,用户会选择其中一个。因此,在 AndroidManifest.xml 中,您必须使用此操作来检测 NDEF 格式的标签。

如果您想阅读 NDEF 消息,不必担心您正在阅读的标签类型(Ultralight、Felica、Topaz...)。 Android 使用 android.nfc.tech.Ndef 来调度 NDEF 格式的标签。因此,当您的 Activity 位于前台时,要获取所有 NdefMessage,您可以使用以下代码片段:

//Called in onCreate()
private void nfcConfig() {
    mAdapter = NfcAdapter.getDefaultAdapter(this);
    pendingIntent = PendingIntent.getActivity(
            this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    techListsArray = new String[][]{new String[]{
                Ndef.class.getName()
            }};     
}

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

@Override
public void onPause() {
    super.onPause();
    mAdapter.disableForegroundDispatch(this);
}

@Override
public void onNewIntent(Intent intent) {
    getNdefMessages(intent);            
}

如果您想读取 Ultralight 标签(或其他技术),那应该是因为您需要来自该标签的原始数据。它不能从主应用程序线程执行。例如:

private void nfcConfig(){
...
//Mifare Ultralight filter
techListsArray = new String[][]{new String[]{
            NfcA.class.getName(),
            MifareUltralight.class.getName()
        }};
...
}

@Override
public void onNewIntent(Intent intent) {
    getRawData(intent);            
}

private void getRawData(Intent intent){
    final Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    MifareUltralight ulTag = MifareUltralight.getTag();
    new ReadMFULTask(ulTag).execute();
}

private static class ReadMFULTask extends AsyncTask<Void, Void, Void> {

    private Tag mTag;

    public ReadMFULTask(Tag tag){
        mTag = tag;
    }

    @Override
    protected Void doInBackground(Void... arg0) {

    MifareUltralight ulTag = MifareUltralight.get(mTag);
    try {
        ulTag.connect();
            //Read all pages from an Ul tag
            for(int i=0; i < 16; i=i+4){
            byte[] data = ulTag.readPages(i);
                String dataString = HexUtilities.getHexString(data);
                Log.d("RAW DATA", dataString);
            }
            ulTag.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}

When a tag with an NDEF message is detected, android looks for any Application with an Activity with intent-filter for action "android.nfc.action.NDEF_DISCOVERED". If two or more applications can handle this action, the one with the most precise filter receives the intent. When applications with the same filter are found, is the user who chooses one. So in your AndroidManifest.xml you have to use this action for detecting NDEF formatted tags.

If you want to read NDEF messages don't worry about which type of tag you are reading (Ultralight, Felica, Topaz,...). Android uses android.nfc.tech.Ndef for dispatch NDEF formatted tags. So for getting all NdefMessages when you activity is on foreground, you can use this snippet:

//Called in onCreate()
private void nfcConfig() {
    mAdapter = NfcAdapter.getDefaultAdapter(this);
    pendingIntent = PendingIntent.getActivity(
            this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    techListsArray = new String[][]{new String[]{
                Ndef.class.getName()
            }};     
}

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

@Override
public void onPause() {
    super.onPause();
    mAdapter.disableForegroundDispatch(this);
}

@Override
public void onNewIntent(Intent intent) {
    getNdefMessages(intent);            
}

If you want to read an Ultralight tag ( or another technology), it should be because you need the raw data from the tag. It must not be executed from the main application thread. For example:

private void nfcConfig(){
...
//Mifare Ultralight filter
techListsArray = new String[][]{new String[]{
            NfcA.class.getName(),
            MifareUltralight.class.getName()
        }};
...
}

@Override
public void onNewIntent(Intent intent) {
    getRawData(intent);            
}

private void getRawData(Intent intent){
    final Tag tag = (Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    MifareUltralight ulTag = MifareUltralight.getTag();
    new ReadMFULTask(ulTag).execute();
}

private static class ReadMFULTask extends AsyncTask<Void, Void, Void> {

    private Tag mTag;

    public ReadMFULTask(Tag tag){
        mTag = tag;
    }

    @Override
    protected Void doInBackground(Void... arg0) {

    MifareUltralight ulTag = MifareUltralight.get(mTag);
    try {
        ulTag.connect();
            //Read all pages from an Ul tag
            for(int i=0; i < 16; i=i+4){
            byte[] data = ulTag.readPages(i);
                String dataString = HexUtilities.getHexString(data);
                Log.d("RAW DATA", dataString);
            }
            ulTag.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }
}
想你的星星会说话 2024-11-17 08:26:00

在代码中,您根据 ACTION_TECH_DISCOVERED 设置意图过滤器,但随后尝试 ndef.addDataType(/),这是为 ACTION_NDEF_DISCOVERED 设置意图过滤器的方法。相反,您可以简单地执行以下操作:

IntentFilter ntech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
mFilters = new IntentFilter[]{ ntech };

确保您已正确设置 nfc_tech_list.xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>

In your code you are setting your intent filter based on ACTION_TECH_DISCOVERED, but then you try ndef.addDataType(/), which is the way you would go about setting up an intent filter for ACTION_NDEF_DISCOVERED. Instead you could simply do something like this:

IntentFilter ntech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
mFilters = new IntentFilter[]{ ntech };

make sure you have nfc_tech_list.xml set up properly:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
</resources>
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文