Android: how do you disable that your app reopens when scanning a NFC tag?

依然范特西╮ 提交于 2020-02-20 05:43:29

问题


I'm writing an android application that reads data from a Mifare Classic card (4k). I have edited my AndroidManifest.xml file so that the app gets started (or I can choose another app that uses NFC). But when my app is openend and I hold my card next to my phone, it gives the popup again where I can choose which app to open. After some research I have found that I need to edit the function: onNewIntent, because this is the function that gets called when you scan a tag when your app is running.

This is my code: (When I scan my card, the toast on the second line of the handleIntent function reads: 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;
    }

}
}

回答1:


You already registered for the foreground dispatch system. This is how you would typically give your app precedence over other registered apps while it is the foreground application. However, you only registered the foreground dispatch for tags that contain an NDEF message that starts with a Text record (or a MIME type record of type text/plain), which seems not to apply to your tag:

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

Instead, you could register to catch just any tag with the foreground dispatch system (you can later silently drop tags that you are not interested in):

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

Alternatively, you could register for a more specific type using the last two parameters of the NfcAdapter.enableForegroundDispatch() method.



来源:https://stackoverflow.com/questions/28496577/android-how-do-you-disable-that-your-app-reopens-when-scanning-a-nfc-tag

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!