How to read NFC Tag through my Application if I wr

2019-09-04 09:33发布

问题:

I am trying to operate the function of flash light which can be on/off through NFC tag.

After writing tag, I tried to set up if a certain information would be read on broadcastReceiver, Flash light should be on/off. However, the receiver never responded. I don't know Why..

So, what I really want to know is following below as

"My application can read the information first where is written in the tag through My application. "

as you saw below codes, I tried to operate the function.

This code For write NFC tag

private void enableTagWriteMode() {
    mWriteMode = true;

    //IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
    //this.registerReceiver(Flash.class, tagDetected);
    //IntentFilter[] mWriteTagFilters = new IntentFilter[] { tagDetected };
    mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, null, null);      
}

private void disableTagWriteMode() {
    mWriteMode = false;
    mNfcAdapter.disableForegroundDispatch(this);
}


protected void onNewIntent(Intent intent) {
    // Tag writing mode

    String action = intent.getAction();
    System.out.println("aa: " + action);
    //android.nfc.action.NDEF_DISCOVERED
    if (mWriteMode) {

        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

        String flash = "Flash";
        byte[] textBytes = flash.getBytes();
        NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA,
                                                   "text/plain".getBytes(), new byte[] {}, textBytes);
        NdefMessage message= new NdefMessage(new NdefRecord[] { textRecord });


        boolean write = writeTag(message, detectedTag);

        System.out.println(""+write);

        if (write) {
            Toast.makeText(this, "Success: Wrote placeid to nfc tag", Toast.LENGTH_LONG)
                .show();
        } 
    }
}

This code, For Read NFC code

public class Flash extends BroadcastReceiver {

private boolean isLighOn = false;
private Camera camera;

@Override
public void onReceive(Context context, Intent intent) {


    if ( NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {

        System.out.println("call?");
        //LayoutInflater mInflater =  (LayoutInflater)context.getSystemService(context.LAYOUT_INFLATER_SERVICE);

        PackageManager pm = context.getPackageManager();

        if (!pm.hasSystemFeature(PackageManager.FEATURE_CAMERA)) {
               Log.e("err", "Device has no camera!");
               return;
              }

        camera = Camera.open();
        final Parameters p = camera.getParameters();



        if (isLighOn) {

            Log.i("info", "torch is turn off!");

            p.setFlashMode(Parameters.FLASH_MODE_OFF);
            camera.setParameters(p);
            camera.stopPreview();
            isLighOn = false;

        } 

        else {

            Log.i("info", "torch is turn on!");

            p.setFlashMode(Parameters.FLASH_MODE_TORCH);

            camera.setParameters(p);
            camera.startPreview();
            isLighOn = true;

        }





    }

}

}

This is Filter in manifest.xml

  <receiver android:name =".Flash">
        <intent-filter android:priority="10000">
            <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
            <data android:mimeType="text/plain" />                      
        </intent-filter>                                   
    </receiver>

回答1:

The NFC discovery intents are sent to activities only. You cannot receive them through a BroadcastReceiver. Thus, you have two options for reading the tag:

  1. If you only want to read the tag while your avtivity is in the foreground, you can use the foreground dispatch system (as you already did for writing the tag).

  2. If you want to achieve something similar to what you tried with the BroadcastReceiver, you can register an activity for the NDEF_DISOVERED intent:

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

Note that you cannot give priority to your application using android:priority="10000". If multiple activities are registered for the same data type, an activity chooser will be shown regardless of priority values. In your case, the data type text/plain is likely to collide with other applications, so I suggest that you use an NFC Forum external type instead. With the NFC Forum external type, you can create your own application-specific NDEF record types:

NdefRecord extRecord = NdefRecord.createExternal(
        "yourdomain.com",  // your domain name
        "yourtype",        // your type name
        textBytes);        // payload

And filter for them:

<activity ...>
    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED" />
        <category android:name="android.intent.category.DEFAULT" />
        <data android:scheme="vnd.android.nfc" android:host="ext"
              android:pathPrefix="/yourdomain.com:yourtype" />
    </intent-filter>
</activity>