简体   繁体   中英

How to write NFC tags while preventing WP from launching the action which is currently stored on NFC tag

I trying to allow people to write to NFC tags using my app, so that my app gets launched with a custom parameter. I want to be able to reprogram NFC tags which already have data on them.

I am using the following code but the problem is, that WP always recognizes the action which is already on the NFC tag and interrupts because it wants to launch the NFC tag action which was written anytime before.

How can I tell the OS to stop triggering the action of the tag so that I can immediately rewrite it?

public enum NfcHelperState
{
    Initializing,
    Waiting,
    Ready,
    Writing,
    Finished,
    Error,
    NoDeviceFound
}
public class NfcHelper
{
    private NfcHelperState _state = NfcHelperState.Initializing;

    public NfcHelperState State
    {
        get { return _state; }
    }


    private ProximityDevice _nfcDevice;

    private long _subscriptionId;
    public NfcHelper()
    {
        Init();
    }

    public void Init()
    {
        UpdateState();
        _nfcDevice = ProximityDevice.GetDefault();
        if (_nfcDevice == null)
        {
            UpdateState(NfcHelperState.NoDeviceFound);
            return;
        }
        UpdateState(NfcHelperState.Waiting);
    }

    private void UpdateState(NfcHelperState? state = null)
    {
        if (state.HasValue)
        {
            _state = state.Value;
        }
        if (OnStatusMessageChanged != null)
        {
            OnStatusMessageChanged(this, _state);
        }
    }

    public void WriteToTag()
    {
        UpdateState(NfcHelperState.Ready);
        _subscriptionId = _nfcDevice.SubscribeForMessage("WriteableTag", WriteableTagDetected);
    }

    private void WriteableTagDetected(ProximityDevice sender, ProximityMessage message)
    {
        UpdateState(NfcHelperState.Writing);
        try
        {
            var str = "action=my_custom_action";
            str += "\tWindowsPhone\t";
            str += CurrentApp.AppId;
            _nfcDevice.PublishBinaryMessage("LaunchApp:WriteTag", GetBufferFromString(str),
                WriteToTagComplete);
        }
        catch (Exception e)
        {
            UpdateState(NfcHelperState.Error);
            StopWaitingForTag();
        }
    }

    private void WriteToTagComplete(ProximityDevice sender, long messageId)
    {
        sender.StopPublishingMessage(messageId);
        UpdateState(NfcHelperState.Finished);
        StopWaitingForTag();
    }

    private void StopWaitingForTag()
    {
        _nfcDevice.StopSubscribingForMessage(_subscriptionId);
    }

    private static IBuffer GetBufferFromString(string str)
    {
        using (var dw = new DataWriter())
        {
            dw.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf16LE;
            dw.WriteString(str);
            return dw.DetachBuffer();
        }
    }

    public delegate void NfcStatusMessageChangedHandler(object myObject, NfcHelperState newState);

    public event NfcStatusMessageChangedHandler OnStatusMessageChanged;
}

WriteToTag is called when a button in my app is tapped and the app waits for a writable tag. If a writable tag is recognized, WriteableTagDetected gets called and immediately starts the writing process. However, this is interrupted by the WP dialog which asks whether to perform the NFC action or not. After writing, WriteToTagComplete should be called, where StopWaitingForTag gets called and ends the write process.

I hope you guys can help me :)

Turns out I thought the wrong way. I didn't need to wait for a tag to arrive in order to rewrite it. In fact, there's no need to do _nfcDevice.SubscribeForMessage("WriteableTag", WriteableTagDetected); before writing. Just start using PublishBinaryMessage and it will write to the tag once it arrives at the device.

My final code looks like the following:

public enum NfcHelperState
{
    Initializing,
    Ready,
    WaitingForWriting,
    FinishedWriting,
    ErrorWriting,
    NoDeviceFound
}
public class NfcHelper
{
    private NfcHelperState _state = NfcHelperState.Initializing;

    public NfcHelperState State
    {
        get { return _state; }
    }


    private ProximityDevice _nfcDevice;
    private long? _writingMessageId;

    public NfcHelper()
    {
        Init();
    }

    public void Init()
    {
        UpdateState();
        _nfcDevice = ProximityDevice.GetDefault();
        if (_nfcDevice == null)
        {
            UpdateState(NfcHelperState.NoDeviceFound);
            return;
        }


        UpdateState(NfcHelperState.Ready);
    }

    private void UpdateState(NfcHelperState? state = null)
    {
        if (state.HasValue)
        {
            _state = state.Value;
        }
        if (OnStatusMessageChanged != null)
        {
            OnStatusMessageChanged(this, _state);
        }
    }

    public void WriteToTag()
    {
        StopWritingMessage();
        UpdateState(NfcHelperState.WaitingForWriting);
        try
        {
            var str = new StringBuilder();
            str.Append("action=my_custom_action");
            str.Append("\tWindowsPhone\t{");
            str.Append(CurrentApp.AppId);
            str.Append("}");
            _writingMessageId = _nfcDevice.PublishBinaryMessage("LaunchApp:WriteTag", GetBufferFromString(str.ToString()),
                WriteToTagComplete);
        }
        catch
        {
            UpdateState(NfcHelperState.ErrorWriting);
            StopWritingMessage();
        }
    }

    private void WriteToTagComplete(ProximityDevice sender, long messageId)
    {
        UpdateState(NfcHelperState.FinishedWriting);
        StopWritingMessage();
    }

    private void StopWritingMessage()
    {
        if (_writingMessageId.HasValue)
        {
            _nfcDevice.StopPublishingMessage(_writingMessageId.Value);
            _writingMessageId = null;
        }
    }

    private static IBuffer GetBufferFromString(string str)
    {
        using (var dw = new DataWriter())
        {
            dw.UnicodeEncoding = Windows.Storage.Streams.UnicodeEncoding.Utf16LE;
            dw.WriteString(str);
            return dw.DetachBuffer();
        }
    }

    public delegate void NfcStatusMessageChangedHandler(object myObject, NfcHelperState newState);

    public event NfcStatusMessageChangedHandler OnStatusMessageChanged;
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM