IntentFilter в NFC — Xamarin — C#

Контекст: Framework 4.5, Xamarin.Android v5.0.

Я хочу использовать технологию NFC для реализации ярлыков для пользователей моего приложения. Я хочу, чтобы пользователи сканировали метку NFC, чтобы им просто нужно было указать значение в предопределенной схеме.

Я поместил некоторые аргументы в свое сообщение NFC, и я делаю это, когда пишу сообщение на своей метке NFC:

    var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Tag;
    var ndef = Ndef.Get(tag);
            NdefRecord external = NdefRecord.CreateExternal(applicationPackageName(), "letypetype", Encoding.ASCII.GetBytes("param"));
            NdefRecord appRecord = NdefRecord.CreateApplicationRecord(applicationPackageName());
            NdefMessage ndefMessage = new NdefMessage(external, appRecord);
    if (ndef != null)
    {
        ndef.Connect();
        ndef.WriteNdefMessage(ndefMessage);
    }

Затем я хочу использовать его в своем приложении, поэтому я поместил его в AndroidManifest.xml следующим образом:

<uses-feature android:name="android.hardware.nfc" android:required="true" />

И в моей основной деятельности у меня есть следующий фильтр намерений:

     [IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered },
      Categories = new[] { Intent.CategoryDefault },
      DataScheme = "vnd.android.nfc", DataPathPrefix = "letypetype",
     DataHost = "ext")]
        public class Activity1 : Activity
       { ...

И я пытаюсь обработать свой параметр в этом действии с помощью метода переопределения OnResume:

    protected override void OnResume()
    {
        base.OnResume();
        if (NfcAdapter.ActionNdefDiscovered.Equals(this.Intent.Action))
        {
            IParcelable[] rawMsgs = this.Intent.GetParcelableArrayExtra(NfcAdapter.ExtraNdefMessages);
            if (rawMsgs != null)
            {
                NdefMessage[] msgs = new NdefMessage[rawMsgs.Length];
                for (int i = 0; i < rawMsgs.Length; i++)
                {
                    msgs[i] = (NdefMessage)rawMsgs[i];
                }
            }
        }
    }

Но вернуть его нет возможности. Так что я почти уверен, что делаю что-то не так, но я не знаю, что.


person Le0n    schedule 29.10.2015    source источник
comment
Вы пробовали мое решение?   -  person Majkl    schedule 30.10.2015
comment
Извините, я отсутствовал в пятницу. Так что да, я попробовал ваш код, и я также добавляю эту строку в свой AndroidManifest.xml: ‹uses-permission android:name=android.permission.NFC /› И да, тег запускает приложение, и после того, как я пытаюсь доступ к дополнительной информации о моем теге. Но до сих пор нет лишнего тега для доступа... Так что, возможно, проблема связана с созданием моего сообщения... Я не знаю...   -  person Le0n    schedule 03.11.2015
comment
Вы решили проблему? Отметьте ответ, который помог вам, или опубликуйте свой собственный ответ, чтобы помочь людям, у которых такая же проблема.   -  person Majkl    schedule 22.12.2015


Ответы (2)


Проблема, с которой вы столкнулись, является результатом вашего неправильного фильтра намерений для внешней записи. В настоящее время в вашем случае происходит то, что фильтр намерений

[IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered },
      Categories = new[] { Intent.CategoryDefault },
      DataScheme = "vnd.android.nfc",
      DataPathPrefix = "letypetype",
      DataHost = "ext")]

не соответствует внешней записи, которую вы создали с помощью

NdefRecord external = NdefRecord.CreateExternal(
            applicationPackageName(),
            "letypetype",
            Encoding.ASCII.GetBytes("param"));

Вместо этого ваша активность запускается из-за записи приложения Android (AAR). Поскольку не было соответствующего фильтра намерений NFC, Android не знает, что ваша активность поддерживает NFC, и, следовательно, не передает тег (и его сообщения NDEF) вашей активности.

Поэтому, чтобы получать дескриптор сообщений/тегов NDEF в своей деятельности, вам необходимо обновить фильтр намерений, чтобы он соответствовал внешней записи. Если имя пакета приложения «com.example», то ваш фильтр намерений должен выглядеть так:

[IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered },
      Categories = new[] { Intent.CategoryDefault },
      DataScheme = "vnd.android.nfc",
      DataPathPrefix = "/com.example:letypetype",
      DataHost = "ext")]

Обратите внимание, что поле домена и косая черта должны быть включены в атрибут DataPathPrefix.

Также обратите внимание, что (хотя это обычно работает) имя пакета Java/Android не является допустимым доменным именем в соответствии со спецификацией форума NFC для внешнего типа. Вместо этого вы должны использовать настоящее доменное имя (например, «example.com»).

И наконец: не забудьте запросить разрешение NFC в манифесте:

<uses-permission android:name="android.permission.NFC" />
person Michael Roland    schedule 07.11.2015

Если я правильно понял вопрос (если не так поправьте пожалуйста), то проблема в чтении данных из тега? Попробуйте сначала просто прочитать EnableForegroundDispatch и OnNewIntent, а затем настройте под свои нужды.

private NfcAdapter mNfcAdapter;

В действии при создании

  mNfcAdapter = NfcAdapter.GetDefaultAdapter(this);

В действии при возобновлении

if (mNfcAdapter != null)
    {
      var tagDetected = new IntentFilter(NfcAdapter.ActionTagDiscovered);//or try other Action type
      var filters = new[] { tagDetected };
      var intent = new Intent(this, GetType()).AddFlags(ActivityFlags.SingleTop);
      var pendingIntent = PendingIntent.GetActivity(this, 0, intent, 0);
      mNfcAdapter.EnableForegroundDispatch(this, pendingIntent, filters, null);
    }

И переварить

    protected override void OnNewIntent(Intent intent)
{
  object obj = intent.GetParcelableExtra(NfcAdapter.ExtraTag);
  if (obj != null && obj is Tag)
  {
    Tag t = (Tag)obj;
    byte[] id = t.GetId();
    string[] techList = t.GetTechList();
    int con = t.DescribeContents();
    string objName = t.ToString();
  }
}

не забудьте для в OnPause

if (mNfcAdapter != null) mNfcAdapter.DisableForegroundDispatch(this);

и OnDestroy

if (mNfcAdapter != null)
    {
      mNfcAdapter.Dispose();
      mNfcAdapter = null;
    }
person Majkl    schedule 30.10.2015