Я создаю приложение Xamarin.Forms, в котором при помещении карты NFC в телефон приложение должно запускаться автоматически и немедленно считывать все данные тега (по крайней мере идентификатор и полезные данные) за один цикл.На некоторых устройствах Android приложение запускается должным образом, но OnNewIntent в MainActivity не запускается. И оно также запускает мое приложение без чтения каких-либо данных. Почему-то метка не обнаруживается.
На других телефонах Android приложение вообще не запускается при помещении карты NFC в устройство.
Я использую следующий код, адаптированный из этого проекта, но в него внесены существенные изменения.
Мой первый вопрос: как я могу обеспечить надежный запуск приложения и чтение данных на устройствах Android? Нужны ли какие-либо изменения, чтобы обеспечить согласованность срабатывания OnNewIntent?
Мой второй вопрос касается достижения такого же поведения на iOS. Можно ли запустить приложение и прочитать данные NFC за один цикл на iOS с помощью Xamarin.Forms, учитывая ограничения iOS NFC?
NativeNFCAdapterService
using System;
using System.Linq;
using System.Threading.Tasks;
using NfcAdapter = Android.Nfc.NfcAdapter;
using Android.Content;
using Android.Nfc.Tech;
using Android.Nfc;
using Android.OS;
using NFCTestApp.Interfaces;
using NFCTestApp.Droid.Services;
using Xamarin.Essentials;
using Xamarin.Forms;
using NFCTestApp.Droid.Enums;
using System.IO;
[assembly: Dependency(typeof(NativeNFCAdapterService))]
namespace NFCTestApp.Droid.Services
{
class NativeNFCAdapterService : INfcAdapter
{
private readonly MainActivity mainActivity = (MainActivity)Platform.CurrentActivity;
private Lazy lazynfcAdapter = new Lazy(() => NfcAdapter.GetDefaultAdapter(Platform.CurrentActivity));
private NfcAdapter NfcAdapter => lazynfcAdapter.Value;
private PendingIntent pendingIntent;
private IntentFilter[] writeTagFilters;
private string[][] techList;
private ReaderCallback readerCallback;
public event Action TagDiscovered;
public event Action AllDataRead;
private NfcStatus NfcStatus => NfcAdapter == null ?
NfcStatus.Unavailable : NfcAdapter.IsEnabled ?
NfcStatus.Enabled : NfcStatus.Disabled;
public static Tag DetectedTag { get; set; }
public NativeNFCAdapterService()
{
Platform.ActivityStateChanged += Platform_ActivityStateChanged;
}
private void Platform_ActivityStateChanged(object sender, ActivityStateChangedEventArgs e)
{
switch (e.State)
{
case ActivityState.Resumed:
EnableForegroundDispatch();
break;
case ActivityState.Paused:
DisableForegroundDispatch();
break;
}
}
public void ConfigureNfcAdapter()
{
IntentFilter tagdiscovered = new IntentFilter(NfcAdapter.ActionTagDiscovered);
IntentFilter ndefDiscovered = new IntentFilter(NfcAdapter.ActionNdefDiscovered);
IntentFilter techDiscovered = new IntentFilter(NfcAdapter.ActionTechDiscovered);
tagdiscovered.AddCategory(Intent.CategoryDefault);
ndefDiscovered.AddCategory(Intent.CategoryDefault);
techDiscovered.AddCategory(Intent.CategoryDefault);
var intent = new Intent(mainActivity, mainActivity.Class).AddFlags(ActivityFlags.SingleTop);
pendingIntent = PendingIntent.GetActivity(mainActivity, 0, intent, PendingIntentFlags.Immutable);
techList = new string[][]
{
new string[] { nameof(NfcA) },
new string[] { nameof(NfcB) },
new string[] { nameof(NfcF) },
new string[] { nameof(NfcV) },
new string[] { nameof(IsoDep) },
new string[] { nameof(NdefFormatable) },
new string[] { nameof(MifareClassic) },
new string[] { nameof(MifareUltralight) },
};
readerCallback = new ReaderCallback();
readerCallback.OnTagDiscoveredEvent += HandleTagDiscovered;
writeTagFilters = new IntentFilter[] { tagdiscovered, ndefDiscovered, techDiscovered };
}
public void DisableForegroundDispatch()
{
NfcAdapter?.DisableForegroundDispatch(Platform.CurrentActivity);
NfcAdapter?.DisableReaderMode(Platform.CurrentActivity);
}
public void EnableForegroundDispatch()
{
if (pendingIntent == null || writeTagFilters == null || techList == null) { return; }
NfcAdapter?.EnableForegroundDispatch(Platform.CurrentActivity, pendingIntent, writeTagFilters, techList);
NfcAdapter?.EnableReaderMode(Platform.CurrentActivity, readerCallback, NfcReaderFlags.NfcA, null);
Task.Run(async () => await ReadAllTagInfoAsync());
}
public void UnconfigureNfcAdapter()
{
Platform.ActivityStateChanged -= Platform_ActivityStateChanged;
}
public void HandleTagDiscovered(string tagId)
{
TagDiscovered?.Invoke(tagId);
}
public async Task SendAsync(byte[] bytes)
{
Ndef ndef = null;
try
{
if (DetectedTag == null)
DetectedTag = await GetDetectedTag();
ndef = Ndef.Get(DetectedTag);
if (ndef == null) return;
if (!ndef.IsWritable)
{
await Application.Current.MainPage.DisplayAlert("Error", "Tag is readonly", "Ok");
return;
}
if (!ndef.IsConnected)
{
await ndef.ConnectAsync();
}
await WriteToTag(ndef, bytes);
}
catch (IOException)
{
await Application.Current.MainPage.DisplayAlert("Error", "Transmission error - possibly due to movement.", "Ok");
}
catch (Exception)
{
await Application.Current.MainPage.DisplayAlert("Error", "Request error", "Ok");
}
finally
{
if (ndef?.IsConnected == true) ndef.Close();
ndef = null;
DetectedTag = null;
}
}
private async Task GetDetectedTag()
{
mainActivity.NfcTag = new TaskCompletionSource();
readerCallback.NFCTag = new TaskCompletionSource();
var tagDetectionTask = await Task.WhenAny(mainActivity.NfcTag.Task, readerCallback.NFCTag.Task);
return await tagDetectionTask;
}
private async Task WriteToTag(Ndef ndef, byte[] chunkedBytes)
{
var ndefRecord = new NdefRecord(NdefRecord.TnfWellKnown, NdefRecord.RtdText?.ToArray(), Array.Empty(), chunkedBytes);
NdefMessage message = new NdefMessage(new[] { ndefRecord });
ndef.WriteNdefMessage(message);
await Application.Current.MainPage.DisplayAlert("NFC", "Write Successful", "Ok");
}
public async Task ReadAllTagInfoAsync()
{
if (DetectedTag == null)
{
DetectedTag = await GetDetectedTag();
}
var info = new System.Text.StringBuilder();
info.AppendLine("Tech List:");
foreach (var tech in DetectedTag.GetTechList())
{
info.AppendLine($"- {tech}");
}
Ndef ndef = Ndef.Get(DetectedTag);
if (ndef != null)
{
info.AppendLine("NDEF Supported: Yes");
info.AppendLine($"NDEF Type: {ndef.Type}");
info.AppendLine($"Is Writable: {ndef.IsWritable}");
info.AppendLine($"Max Size: {ndef.MaxSize} bytes");
var ndefMessage = ndef.CachedNdefMessage;
if (ndefMessage != null && ndefMessage.GetRecords().Any())
{
foreach (var ndefRecord in ndefMessage.GetRecords())
{
info.AppendLine($"Payload: {System.Text.Encoding.UTF8.GetString(ndefRecord.GetPayload())}");
}
}
}
else
{
info.AppendLine("NDEF Supported: No");
}
AllDataRead?.Invoke(info.ToString());
return info.ToString();
}
}
}
ReaderCallback.cs
public class ReaderCallback : Java.Lang.Object, NfcAdapter.IReaderCallback
{
public TaskCompletionSource NFCTag { get; set; }
public event Action OnTagDiscoveredEvent;
public void OnTagDiscovered(Tag tag)
{
var isSuccess = NFCTag?.TrySetResult(tag);
if (NFCTag == null || !isSuccess.Value)
NativeNFCAdapterService.DetectedTag = tag;
byte[] tagIdBytes = tag.GetId();
string tagId = BitConverter.ToString(tagIdBytes).Replace("-", "");
OnTagDiscoveredEvent?.Invoke(tagId);
}
}
MainActivity.cs
[MetaData(NfcAdapter.ActionTechDiscovered, Resource = "@xml/nfc_tech_filter")]
[IntentFilter(new[] { NfcAdapter.ActionTechDiscovered }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")]
[IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")]
[IntentFilter(new[] { NfcAdapter.ActionTagDiscovered }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")]
[Activity(Label = "NFCTestApp", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public TaskCompletionSource NfcTag { get; set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
protected override void OnNewIntent(Intent intent)
{
System.Diagnostics.Debug.WriteLine("It is here");
base.OnNewIntent(intent);
Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
{
await Xamarin.Forms.Application.Current.MainPage.DisplayAlert("NFC Tag Discovered", "A1", "OK");
});
}
}
AndroidManifest.xml
Подробнее здесь: https://stackoverflow.com/questions/791 ... id-and-ios
Xamarin.Forms NFC: автоматический запуск приложения и чтение данных тегов на Android и iOS ⇐ Android
Форум для тех, кто программирует под Android
1730718318
Anonymous
Я создаю приложение Xamarin.Forms, в котором при помещении карты NFC в телефон приложение должно запускаться автоматически и немедленно считывать все данные тега (по крайней мере идентификатор и полезные данные) за один цикл.На некоторых устройствах Android приложение запускается должным образом, но OnNewIntent в MainActivity не запускается. И оно также запускает мое приложение без чтения каких-либо данных. Почему-то метка не обнаруживается.
На других телефонах Android приложение вообще не запускается при помещении карты NFC в устройство.
Я использую следующий код, адаптированный из этого проекта, но в него внесены существенные изменения.
Мой [b]первый[/b] вопрос: как я могу обеспечить надежный запуск приложения и чтение данных на устройствах Android? Нужны ли какие-либо изменения, чтобы обеспечить согласованность срабатывания OnNewIntent?
Мой [b]второй[/b] вопрос касается достижения такого же поведения на iOS. Можно ли запустить приложение и прочитать данные NFC за один цикл на iOS с помощью Xamarin.Forms, учитывая ограничения iOS NFC?
NativeNFCAdapterService
using System;
using System.Linq;
using System.Threading.Tasks;
using NfcAdapter = Android.Nfc.NfcAdapter;
using Android.Content;
using Android.Nfc.Tech;
using Android.Nfc;
using Android.OS;
using NFCTestApp.Interfaces;
using NFCTestApp.Droid.Services;
using Xamarin.Essentials;
using Xamarin.Forms;
using NFCTestApp.Droid.Enums;
using System.IO;
[assembly: Dependency(typeof(NativeNFCAdapterService))]
namespace NFCTestApp.Droid.Services
{
class NativeNFCAdapterService : INfcAdapter
{
private readonly MainActivity mainActivity = (MainActivity)Platform.CurrentActivity;
private Lazy lazynfcAdapter = new Lazy(() => NfcAdapter.GetDefaultAdapter(Platform.CurrentActivity));
private NfcAdapter NfcAdapter => lazynfcAdapter.Value;
private PendingIntent pendingIntent;
private IntentFilter[] writeTagFilters;
private string[][] techList;
private ReaderCallback readerCallback;
public event Action TagDiscovered;
public event Action AllDataRead;
private NfcStatus NfcStatus => NfcAdapter == null ?
NfcStatus.Unavailable : NfcAdapter.IsEnabled ?
NfcStatus.Enabled : NfcStatus.Disabled;
public static Tag DetectedTag { get; set; }
public NativeNFCAdapterService()
{
Platform.ActivityStateChanged += Platform_ActivityStateChanged;
}
private void Platform_ActivityStateChanged(object sender, ActivityStateChangedEventArgs e)
{
switch (e.State)
{
case ActivityState.Resumed:
EnableForegroundDispatch();
break;
case ActivityState.Paused:
DisableForegroundDispatch();
break;
}
}
public void ConfigureNfcAdapter()
{
IntentFilter tagdiscovered = new IntentFilter(NfcAdapter.ActionTagDiscovered);
IntentFilter ndefDiscovered = new IntentFilter(NfcAdapter.ActionNdefDiscovered);
IntentFilter techDiscovered = new IntentFilter(NfcAdapter.ActionTechDiscovered);
tagdiscovered.AddCategory(Intent.CategoryDefault);
ndefDiscovered.AddCategory(Intent.CategoryDefault);
techDiscovered.AddCategory(Intent.CategoryDefault);
var intent = new Intent(mainActivity, mainActivity.Class).AddFlags(ActivityFlags.SingleTop);
pendingIntent = PendingIntent.GetActivity(mainActivity, 0, intent, PendingIntentFlags.Immutable);
techList = new string[][]
{
new string[] { nameof(NfcA) },
new string[] { nameof(NfcB) },
new string[] { nameof(NfcF) },
new string[] { nameof(NfcV) },
new string[] { nameof(IsoDep) },
new string[] { nameof(NdefFormatable) },
new string[] { nameof(MifareClassic) },
new string[] { nameof(MifareUltralight) },
};
readerCallback = new ReaderCallback();
readerCallback.OnTagDiscoveredEvent += HandleTagDiscovered;
writeTagFilters = new IntentFilter[] { tagdiscovered, ndefDiscovered, techDiscovered };
}
public void DisableForegroundDispatch()
{
NfcAdapter?.DisableForegroundDispatch(Platform.CurrentActivity);
NfcAdapter?.DisableReaderMode(Platform.CurrentActivity);
}
public void EnableForegroundDispatch()
{
if (pendingIntent == null || writeTagFilters == null || techList == null) { return; }
NfcAdapter?.EnableForegroundDispatch(Platform.CurrentActivity, pendingIntent, writeTagFilters, techList);
NfcAdapter?.EnableReaderMode(Platform.CurrentActivity, readerCallback, NfcReaderFlags.NfcA, null);
Task.Run(async () => await ReadAllTagInfoAsync());
}
public void UnconfigureNfcAdapter()
{
Platform.ActivityStateChanged -= Platform_ActivityStateChanged;
}
public void HandleTagDiscovered(string tagId)
{
TagDiscovered?.Invoke(tagId);
}
public async Task SendAsync(byte[] bytes)
{
Ndef ndef = null;
try
{
if (DetectedTag == null)
DetectedTag = await GetDetectedTag();
ndef = Ndef.Get(DetectedTag);
if (ndef == null) return;
if (!ndef.IsWritable)
{
await Application.Current.MainPage.DisplayAlert("Error", "Tag is readonly", "Ok");
return;
}
if (!ndef.IsConnected)
{
await ndef.ConnectAsync();
}
await WriteToTag(ndef, bytes);
}
catch (IOException)
{
await Application.Current.MainPage.DisplayAlert("Error", "Transmission error - possibly due to movement.", "Ok");
}
catch (Exception)
{
await Application.Current.MainPage.DisplayAlert("Error", "Request error", "Ok");
}
finally
{
if (ndef?.IsConnected == true) ndef.Close();
ndef = null;
DetectedTag = null;
}
}
private async Task GetDetectedTag()
{
mainActivity.NfcTag = new TaskCompletionSource();
readerCallback.NFCTag = new TaskCompletionSource();
var tagDetectionTask = await Task.WhenAny(mainActivity.NfcTag.Task, readerCallback.NFCTag.Task);
return await tagDetectionTask;
}
private async Task WriteToTag(Ndef ndef, byte[] chunkedBytes)
{
var ndefRecord = new NdefRecord(NdefRecord.TnfWellKnown, NdefRecord.RtdText?.ToArray(), Array.Empty(), chunkedBytes);
NdefMessage message = new NdefMessage(new[] { ndefRecord });
ndef.WriteNdefMessage(message);
await Application.Current.MainPage.DisplayAlert("NFC", "Write Successful", "Ok");
}
public async Task ReadAllTagInfoAsync()
{
if (DetectedTag == null)
{
DetectedTag = await GetDetectedTag();
}
var info = new System.Text.StringBuilder();
info.AppendLine("Tech List:");
foreach (var tech in DetectedTag.GetTechList())
{
info.AppendLine($"- {tech}");
}
Ndef ndef = Ndef.Get(DetectedTag);
if (ndef != null)
{
info.AppendLine("NDEF Supported: Yes");
info.AppendLine($"NDEF Type: {ndef.Type}");
info.AppendLine($"Is Writable: {ndef.IsWritable}");
info.AppendLine($"Max Size: {ndef.MaxSize} bytes");
var ndefMessage = ndef.CachedNdefMessage;
if (ndefMessage != null && ndefMessage.GetRecords().Any())
{
foreach (var ndefRecord in ndefMessage.GetRecords())
{
info.AppendLine($"Payload: {System.Text.Encoding.UTF8.GetString(ndefRecord.GetPayload())}");
}
}
}
else
{
info.AppendLine("NDEF Supported: No");
}
AllDataRead?.Invoke(info.ToString());
return info.ToString();
}
}
}
ReaderCallback.cs
public class ReaderCallback : Java.Lang.Object, NfcAdapter.IReaderCallback
{
public TaskCompletionSource NFCTag { get; set; }
public event Action OnTagDiscoveredEvent;
public void OnTagDiscovered(Tag tag)
{
var isSuccess = NFCTag?.TrySetResult(tag);
if (NFCTag == null || !isSuccess.Value)
NativeNFCAdapterService.DetectedTag = tag;
byte[] tagIdBytes = tag.GetId();
string tagId = BitConverter.ToString(tagIdBytes).Replace("-", "");
OnTagDiscoveredEvent?.Invoke(tagId);
}
}
MainActivity.cs
[MetaData(NfcAdapter.ActionTechDiscovered, Resource = "@xml/nfc_tech_filter")]
[IntentFilter(new[] { NfcAdapter.ActionTechDiscovered }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")]
[IntentFilter(new[] { NfcAdapter.ActionNdefDiscovered }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")]
[IntentFilter(new[] { NfcAdapter.ActionTagDiscovered }, Categories = new[] { Intent.CategoryDefault }, DataMimeType = "text/plain")]
[Activity(Label = "NFCTestApp", Icon = "@mipmap/icon", Theme = "@style/MainTheme", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation | ConfigChanges.UiMode | ConfigChanges.ScreenLayout | ConfigChanges.SmallestScreenSize)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
public TaskCompletionSource NfcTag { get; set; }
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
LoadApplication(new App());
}
protected override void OnNewIntent(Intent intent)
{
System.Diagnostics.Debug.WriteLine("It is here");
base.OnNewIntent(intent);
Xamarin.Forms.Device.BeginInvokeOnMainThread(async () =>
{
await Xamarin.Forms.Application.Current.MainPage.DisplayAlert("NFC Tag Discovered", "A1", "OK");
});
}
}
AndroidManifest.xml
Подробнее здесь: [url]https://stackoverflow.com/questions/79155186/xamarin-forms-nfc-automatically-launch-app-and-read-tag-data-on-android-and-ios[/url]
Ответить
1 сообщение
• Страница 1 из 1
Перейти
- Кемерово-IT
- ↳ Javascript
- ↳ C#
- ↳ JAVA
- ↳ Elasticsearch aggregation
- ↳ Python
- ↳ Php
- ↳ Android
- ↳ Html
- ↳ Jquery
- ↳ C++
- ↳ IOS
- ↳ CSS
- ↳ Excel
- ↳ Linux
- ↳ Apache
- ↳ MySql
- Детский мир
- Для души
- ↳ Музыкальные инструменты даром
- ↳ Печатная продукция даром
- Внешняя красота и здоровье
- ↳ Одежда и обувь для взрослых даром
- ↳ Товары для здоровья
- ↳ Физкультура и спорт
- Техника - даром!
- ↳ Автомобилистам
- ↳ Компьютерная техника
- ↳ Плиты: газовые и электрические
- ↳ Холодильники
- ↳ Стиральные машины
- ↳ Телевизоры
- ↳ Телефоны, смартфоны, плашеты
- ↳ Швейные машинки
- ↳ Прочая электроника и техника
- ↳ Фототехника
- Ремонт и интерьер
- ↳ Стройматериалы, инструмент
- ↳ Мебель и предметы интерьера даром
- ↳ Cантехника
- Другие темы
- ↳ Разное даром
- ↳ Давай меняться!
- ↳ Отдам\возьму за копеечку
- ↳ Работа и подработка в Кемерове
- ↳ Давай с тобой поговорим...
Мобильная версия