【问题标题】:How To Use An NFC Tag On Android When Scanned To Open App扫描打开应用程序时如何在 Android 上使用 NFC 标签
【发布时间】:2020-05-18 14:18:27
【问题描述】:

我正在向以下问题寻求建议,我已经在网上查看(以及 stackoverflow 上的类似问题),但没有适合我的解决方案。

我正在编写一个 Android 应用程序(为了全面披露,我正在 Xamarin 中执行此操作 - 但技术应该无关紧要),我想要它做的只是显示警报/祝酒词扫描 NFC 代码时的消息。如果我打开应用程序并将 NFC 标签贴在手机上,则警报会按预期显示。当应用程序关闭并且我将 NFC 标签贴在手机上时,应用程序会打开,但仅此而已。

我对 Android 开发相当陌生(以前我在通过 Xamarin 创建 Android 应用程序时非常通用,并且没有真正使用 NFC/蓝牙等设备功能)所以如果我遗漏了一些相当明显的东西,我深表歉意。

using System.Text;
using Android.App;
using Android.Content;
using Android.Nfc;
using Android.OS;
using Android.Support.V7.App;

namespace Android.Demo
{

    [Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true, LaunchMode = Content.PM.LaunchMode.SingleInstance)]
    [IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered }, Categories = new[] { "android.intent.category.DEFAULT" }, DataMimeType = "*/*")]
    public class MainActivity : AppCompatActivity
    {

        private NfcAdapter _nfcAdapter;

        private PendingIntent _pendingIntent;

        private string[][] _techList = new string[][]{
                     new[] { "android.nfc.tech.NdefFormatable" } ,
                     new [] { "android.nfc.tech.NfcA" } ,
                     new [] { "android.nfc.tech.Ndef" },
                     new [] { "android.nfc.tech.Ndef" }};

        protected override void OnCreate(Bundle savedInstanceState)
        {
            _nfcAdapter = NfcAdapter.GetDefaultAdapter(this);

            base.OnCreate(savedInstanceState);
            Xamarin.Essentials.Platform.Init(this, savedInstanceState);
            SetContentView(Resource.Layout.activity_main);

            _pendingIntent = PendingIntent.GetActivity(this, 0, Intent, 0);

            Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
            SetSupportActionBar(toolbar);


        }

        protected override void OnPause()
        {
            base.OnPause();
            if (_nfcAdapter != null && _nfcAdapter.IsEnabled)
                _nfcAdapter.DisableForegroundDispatch(this);
        }


        protected override void OnResume()
        {
            base.OnResume();


            // doStuff();

            _nfcAdapter.EnableForegroundDispatch(this, _pendingIntent, new[] { new IntentFilter(NfcAdapter.ActionNdefDiscovered), new IntentFilter(NfcAdapter.ActionTechDiscovered), new IntentFilter(NfcAdapter.ActionTagDiscovered), new IntentFilter(NfcAdapter.ActionNdefDiscovered) }, _techList);

        }


        protected override void OnNewIntent(Intent intent)
        {

            var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
            if (tag != null)
            {
                // First get all the NdefMessage
                var rawMessages = intent.GetParcelableArrayExtra(NfcAdapter.ExtraNdefMessages);
                if (rawMessages != null)
                {
                    var msg = (NdefMessage)rawMessages[0];

                    // Get NdefRecord which contains the actual data
                    var record = msg.GetRecords()[0];
                    if (record != null)
                    {
                        if (record.Tnf == NdefRecord.TnfWellKnown) // The data is defined by the Record Type Definition (RTD) specification available from http://members.nfc-forum.org/specs/spec_list/
                        {
                            // Get the transfered data
                            var data = Encoding.ASCII.GetString(record.GetPayload());

                            var alert = new App.AlertDialog.Builder(this).Create();
                            alert.SetMessage(data);
                            alert.SetTitle("NFC Tag Located");
                            alert.Show();

                        }
                    }
                }
            }
        }

    }
}

谢谢

【问题讨论】:

  • 向我们展示你所描述的代码
  • 请出示代码。否则我们怎么知道丢失了什么?
  • 抱歉,我已经使用正在使用的 Xamarin 代码更新了我的原始帖子。

标签: android xamarin.android nfc


【解决方案1】:

通常您应该使用 onNewIntent(Intent intent) 来设置您拥有的最后一个 intnet。 我会按以下方式编写您的代码:

using System.Text;
using Android.App;
using Android.Content;
using Android.Nfc;
using Android.OS;
using Android.Support.V7.App;

namespace Android.Demo
{

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true, LaunchMode = Content.PM.LaunchMode.SingleInstance)]
[IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered }, Categories = new[] { "android.intent.category.DEFAULT" }, DataMimeType = "*/*")]
public class MainActivity : AppCompatActivity
{

    private NfcAdapter _nfcAdapter;

    private PendingIntent _pendingIntent;

    private string[][] _techList = new string[][]{
                 new[] { "android.nfc.tech.NdefFormatable" } ,
                 new [] { "android.nfc.tech.NfcA" } ,
                 new [] { "android.nfc.tech.Ndef" },
                 new [] { "android.nfc.tech.Ndef" }};

    protected override void OnCreate(Bundle savedInstanceState)
    {
        _nfcAdapter = NfcAdapter.GetDefaultAdapter(this);

        base.OnCreate(savedInstanceState);
        Xamarin.Essentials.Platform.Init(this, savedInstanceState);
        SetContentView(Resource.Layout.activity_main);

        _pendingIntent = PendingIntent.GetActivity(this, 0, Intent, 0);

        Android.Support.V7.Widget.Toolbar toolbar = FindViewById<Android.Support.V7.Widget.Toolbar>(Resource.Id.toolbar);
        SetSupportActionBar(toolbar);


    }

    protected override void OnPause()
    {
        base.OnPause();
        if (_nfcAdapter != null && _nfcAdapter.IsEnabled)
            _nfcAdapter.DisableForegroundDispatch(this);
    }


    protected override void OnResume()
    {
        base.OnResume();
        if(isNfcIntent(getIntent())){
            processNfcIntent(getIntent());
        }

        // doStuff();

        _nfcAdapter.EnableForegroundDispatch(this, _pendingIntent, new[] { new IntentFilter(NfcAdapter.ActionNdefDiscovered), new IntentFilter(NfcAdapter.ActionTechDiscovered), new IntentFilter(NfcAdapter.ActionTagDiscovered), new IntentFilter(NfcAdapter.ActionNdefDiscovered) }, _techList);

    }


    protected override void OnNewIntent(Intent intent)
    {

        setIntent(intent);
    }

}

processIntent(Intent intent){
var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
         // First get all the NdefMessage
            var rawMessages = intent.GetParcelableArrayExtra(NfcAdapter.ExtraNdefMessages);
            if (rawMessages != null)
            {
                var msg = (NdefMessage)rawMessages[0];

                // Get NdefRecord which contains the actual data
                var record = msg.GetRecords()[0];
                if (record != null)
                {
                    if (record.Tnf == NdefRecord.TnfWellKnown) // The data is defined by the Record Type Definition (RTD) specification available from http://members.nfc-forum.org/specs/spec_list/
                    {
                        // Get the transfered data
                        var data = Encoding.ASCII.GetString(record.GetPayload());

                        var alert = new App.AlertDialog.Builder(this).Create();
                        alert.SetMessage(data);
                        alert.SetTitle("NFC Tag Located");
                        alert.Show();

                    }
                }
            }

     }
}

所以这样processNfcIntent(Intent intent)将在应用程序启动时调用,如果它因为触摸NFC标签而启动,如果onNewIntent(Intent intent)被调用,它将被调用。

android 总是在onNewIntent(Intent intent) 之后调用onResume()。 如果意图不是 nfc 意图,则函数 isNfcIntent(Intent intent) 应返回 false,例如:

private boolean isNfcIntent(Intent intent){

var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
    return tag != null;
}

【讨论】:

  • 谢谢卡拉姆,这也有效,也是一个完全可以接受的答案。
【解决方案2】:

我有一个应用程序,它在运行时读取标签并注册处理标签,以便它在不运行时启动。

您可能缺少的是,当您运行带有标签的Intent 时,其中的数据会传递给OnNewIntent,但是当您不运行时,Intent 会传递给onCreate

在那里我做了类似的事情:-


protected override void OnCreate(Bundle savedInstanceState)
        {

        // Other onCreate Stuff

        // Get any Intent the app was started with
        var mIntent = getIntent();
        // Check that the Intent contains details about NFC data
        var tag = mIntent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
        if (tag != null)
        {
           OnNewIntent(mIntent);
        } 

注意我不做 Xamarin,所以没有测试,但我在 Java 中做类似

【讨论】:

  • 谢谢安德鲁。稍后我回家时会对此进行测试并报告我的发现。
  • 谢谢,这绝对完美(在 c# 中有一个属性 Intent 可以完成 getIntent() 所做的工作,因此必须稍微调整一下)。非常感谢
猜你喜欢
  • 2015-04-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2016-01-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多