Android:如何禁止应用程序在扫描 NFC 标签时重新打开?

2024-04-28

我正在编写一个 Android 应用程序,用于从 Mifare Classic 卡(4k)读取数据。我已经编辑了 AndroidManifest.xml 文件,以便应用程序启动(或者我可以选择另一个使用 NFC 的应用程序)。但是,当我的应用程序处于开放状态并且我将卡放在手机旁边时,它会再次弹出窗口,我可以在其中选择要打开的应用程序。经过一番研究,我发现我需要编辑该函数:onNewIntent,因为这是在应用程序运行时扫描标签时调用的函数。

这是我的代码:(当我扫描我的卡时,第二行的吐司handleIntent函数如下:ACTION_TECH_DISCOVERED.)

package be.khleuven.aanwezigheidssysteem;

import android.app.Activity;
import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.AsyncTask;
import android.os.Bundle;
import android.util.Log;
import android.widget.TextView;
import android.widget.Toast;
import android.content.IntentFilter.MalformedMimeTypeException;

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




public class Login extends Activity {
public static final String MIME_TEXT_PLAIN = "text/plain";
public static final String TAG = "NfcDemo";

private TextView mTextView;
private NfcAdapter mNfcAdapter;

@Override
protected void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_login);

    mTextView = (TextView) findViewById(R.id.textView_explanation);

    mNfcAdapter = NfcAdapter.getDefaultAdapter(this);


    if (mNfcAdapter == null) {
        // Stop here, we definitely need NFC
        Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
        //finish();
        return;

    }

    if (!mNfcAdapter.isEnabled()) {
        mTextView.setText("NFC is disabled.");
    } else {
        mTextView.setText(R.string.explanation);
    }

    handleIntent(getIntent());
}

@Override
protected void onResume() {
    super.onResume();

    /**
     * It's important, that the activity is in the foreground (resumed). Otherwise
     * an IllegalStateException is thrown.
     */
    setupForegroundDispatch(this, mNfcAdapter);
}

@Override
protected void onPause() {
    /**
     * Call this before onPause, otherwise an IllegalArgumentException is thrown as well.
     */
    stopForegroundDispatch(this, mNfcAdapter);

    super.onPause();
}

@Override
public void onNewIntent(Intent intent) {
    /**
     * This method gets called, when a new Intent gets associated with the current activity instance.
     * Instead of creating a new activity, onNewIntent will be called. For more information have a look
     * at the documentation.
     *
     * In our case this method gets called, when the user attaches a Tag to the device.
     */
    handleIntent(intent);
}

private void handleIntent(Intent intent) {
    String action = intent.getAction();
    Toast.makeText(this, action, Toast.LENGTH_LONG).show();
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

        String type = intent.getType();
        if (MIME_TEXT_PLAIN.equals(type)) {

            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            new NdefReaderTask().execute(tag);

        } else {
            Log.d(TAG, "Wrong mime type: " + type);
        }
    } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)) {
        Toast.makeText(this, "Ze zijn gelijk", Toast.LENGTH_LONG).show();
        // In case we would still use the Tech Discovered Intent
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        String[] techList = tag.getTechList();
        String searchedTech = Ndef.class.getName();

        for (String tech : techList) {
            if (searchedTech.equals(tech)) {
                new NdefReaderTask().execute(tag);
                break;
            }
        }
        TextView t = (TextView) findViewById(R.id.textView_explanation);
        t.setText("Mooi kaartje heb je daar");
    }

    else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {

        // In case we would still use the Tech Discovered Intent
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        String[] techList = tag.getTechList();
        String searchedTech = Ndef.class.getName();

        for (String tech : techList) {
            if (searchedTech.equals(tech)) {
                new NdefReaderTask().execute(tag);
                break;
            }
        }
    }
    if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
        TextView textView = (TextView) findViewById(R.id.textView_explanation);
        textView.setText("Hello NFC tag!");
    } else {
        // ignore
    }

}

public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
    final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    final PendingIntent pendingIntent = PendingIntent.getActivity(activity.getApplicationContext(), 0, intent, 0);

    IntentFilter[] filters = new IntentFilter[1];
    String[][] techList = new String[][]{};

    // Notice that this is the same filter as in our manifest.
    filters[0] = new IntentFilter();
    filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
    filters[0].addCategory(Intent.CATEGORY_DEFAULT);
    try {
        filters[0].addDataType(MIME_TEXT_PLAIN);
    } catch (MalformedMimeTypeException e) {
        throw new RuntimeException("Check your mime type.");
    }

    adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
}

public static void stopForegroundDispatch(final Activity activity, NfcAdapter adapter) {
    adapter.disableForegroundDispatch(activity);
}

private class NdefReaderTask extends AsyncTask<Tag, Void, String> {

    @Override
    protected String doInBackground(Tag... params) {
        Tag tag = params[0];

        Ndef ndef = Ndef.get(tag);
        if (ndef == null) {
            // NDEF is not supported by this Tag.
            return null;
        }

        NdefMessage ndefMessage = ndef.getCachedNdefMessage();

        NdefRecord[] records = ndefMessage.getRecords();
        for (NdefRecord ndefRecord : records) {
            if (ndefRecord.getTnf() == NdefRecord.TNF_WELL_KNOWN && Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
                try {
                    return readText(ndefRecord);
                } catch (UnsupportedEncodingException e) {
                    Log.e(TAG, "Unsupported Encoding", e);
                }
            }
        }

        return null;
    }

}
}

您已经注册了前台调度系统。当您的应用程序是前台应用程序时,通常会通过这种方式让您的应用程序优先于其他已注册的应用程序。但是,您仅注册了包含以文本记录(或 text/plain 类型的 MIME 类型记录)开头的 NDEF 消息的标签的前台调度,这似乎不适用于您的标签:

filters[0].addAction(NfcAdapter.ACTION_NDEF_DISCOVERED);
filters[0].addCategory(Intent.CATEGORY_DEFAULT);
filters[0].addDataType(MIME_TEXT_PLAIN);

相反,您可以注册以使用前台调度系统捕获任何标签(稍后您可以默默地删除您不感兴趣的标签):

public static void setupForegroundDispatch(final Activity activity, NfcAdapter adapter) {
    final Intent intent = new Intent(activity, activity.getClass());
    intent.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

    final PendingIntent pendingIntent = PendingIntent.getActivity(activity, 0, intent, 0);

    adapter.enableForegroundDispatch(activity, pendingIntent, null, null);
}

或者,您可以使用最后两个参数注册更具体的类型NfcAdapter.enableForegroundDispatch() method.

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Android:如何禁止应用程序在扫描 NFC 标签时重新打开? 的相关文章

随机推荐