FelicaReaderは、XamarinのAndroidアプリとUWPアプリでFelicaカード読み取りを行えるプラグインです。
Felicaカードへのコマンド送信は、Felicaカードユーザーズマニュアル抜粋版に 記載されたコマンドの一部だけを実装しています。特に、暗号化領域に関するコマンドは、技術情報を持ち合わせていないため、今後もサポートする予定はありません。
Platform | Version |
---|---|
Xamarin.Android | API 14+ |
Windows 10 UWP | 10.0.10240+ |
- 201712/29 READMEを改定しました。
- 201712/26 公開しました。
以下では、Xamarin.Formsプロジェクト(アプリ名をSample.FelicaReaderとします)において、変更すべき箇所を説明します。 サンプルコードも公開していますので、併せて参照してください。
Xamarin.Forms sample: nobukuma/FelicaReaderSample
プロジェクトに、NuGetからパッケージをインストールします。
Xamarin.Formsアプリのソリューションにおいて、 共通部分のSample.FelicaReader、またSample.FelicaReader.DroidとSample.FelicaReader.UWPの それぞれでFelicaReaderプラグインをNuGetからインストールする必要があります。
Androidでは、Felicaカードが端末で検知されたときにインテントが発生して、それをアプリで受信することで検知されたFelicaカードを読み取れます。 このインテントの処理は、Androidの固有部分Sample.FelicaReader.Droidで実装する必要があります。
具体的には、Androidの固有部分Sample.FelicaReader.Droidで、ActionTechDiscoveredインテントを受信して、以下を行います。
- インテントのタグデータからNfcFインスタンスを生成する。
- NfcFインスタンスに接続する。
- FelicaCardMediaImplementationインスタンスを作成して、サブスクライバーに通知する。
MainActivity.csでの実装内容は、以下の通りです。
- クラス属性の設定
- IntentFilter属性の設定
- MetaData属性の設定
namespace Sample.FelicaReader.Droid
{
[Activity(Label = "Sample.FelicaReader", Icon = "@drawable/icon", MainLauncher = true,
LaunchMode = Android.Content.PM.LaunchMode.SingleTop,
ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
[IntentFilter(new[] { NfcAdapter.ActionTechDiscovered })]
[MetaData(NfcAdapter.ActionTechDiscovered, Resource = "@xml/nfc_filter")]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
private IFelicaReader felicaReader;
- OnCreateでの設定
- MainActivityインスタンスとその型を指定して、CrossFelicaReader.Initを呼び出す
- インテントの処理(タグデータからNfcFインスタンスを生成して、接続、それを指定して作成したFelicaCardMediaImplementationインスタンスをサブスクライバーに通知)
protected override void OnCreate(Bundle bundle)
{
...(省略)...
CrossFelicaReader.Init(this, GetType());
this.felicaReader = CrossFelicaReader.Current;
LoadApplication(new App(new AndroidInitializer()));
this.ProcessActionTechDiscoveredIntent(this.Intent);
}
private void ProcessActionTechDiscoveredIntent(Intent intent)
{
string action = intent.Action;
if (action != NfcAdapter.ActionTechDiscovered)
{
return;
}
var tag = intent.GetParcelableExtra(NfcAdapter.ExtraTag) as Android.Nfc.Tag;
if (tag != null)
{
var subject = this.felicaReader.WhenCardFound() as Subject<IFelicaCardMedia>;
NfcF nfc = NfcF.Get(tag);
nfc.Connect();
subject.OnNext(new FelicaCardMediaImplementation(nfc));
}
}
- OnNewIntentでのインテントの処理
- 処理内容は上記のインテントの処理と同じ
protected override void OnNewIntent(Intent intent)
{
base.OnNewIntent(intent);
ProcessActionTechDiscoveredIntent(intent);
return;
}
- Pause・Resume時のフォアグラウンドでのインテントのディスパッチの停止・開始
protected override void OnPause()
{
base.OnPause();
this.felicaReader.DisableForeground();
}
protected override void OnResume()
{
base.OnResume();
this.felicaReader.EnableForeground();
}
Resrouces/xml/nfc_filter.xmlを作成して、以下を記述します。
<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2" >
<tech-list>
<tech>android.nfc.tech.NfcF</tech>
</tech-list>
</resources>
プロジェクトのプロパティを開いて、AndroidマニフェストのRequired PermissionsでNFCを選択します。
UWPの固有部分Sample.FelicaReader.UWPで実装すべきコードはありません。
Sample.FelicaReader.UWPのパッケージマニフェストを開いて、機能シートにおいて近接通信を選択します。
共通部分Sample.FelicaReaderでは、Felicaカード検知の通知を購読して、その処理を記述します。
サンプルでは、MainPageのViewModelで、Felicaカード検知の通知を購読して、検知したときの処理を書いています。 ReadWithoutEncryptionで指定するサービスコードとブロック番号リストを変えることで、SuicaやEdyなどFelicaカードが実装するサービスからデータを取得できます。
public class MainPageViewModel : BindableBase, INavigationAware
{
private IFelicaReader felicaReader;
private IDisposable subscription;
...
public MainPageViewModel()
{
this.felicaReader = CrossFelicaReader.Current;
...
}
...
public void OnNavigatedFrom(NavigationParameters parameters)
{
this.subscription.Dispose();
}
...
public void OnNavigatedTo(NavigationParameters parameters)
{
this.subscription = this.felicaReader.WhenCardFound().Subscribe(async x =>
{
try
{
var byteIdm = await x.GetIdm();
this.IDmString = BitConverter.ToString(byteIdm);
System.Diagnostics.Debug.WriteLine("Idm: {0}", this.IDmString, 0x00);
var result = await x.ReadWithoutEncryption(byteIdm, 0x008b, 1, new byte[] { 0x80, 0x00 });
string resStr = BitConverter.ToString(result.PacketData);
System.Diagnostics.Debug.WriteLine("Res: {0}(len={1})", resStr, result.PacketData.Length);
this.Message = String.Format("Res: {0}", resStr, 0x00);
}
catch (Exception e)
{
System.Diagnostics.Debug.WriteLine(e.Message);
}
finally
{
x.Dispose();
}
},
onError: x =>
{
System.Diagnostics.Debug.WriteLine(x.Message);
});
}
}
なお、UWPでアプリが利用される場合、共通部分でFelicaカード検知の開始処理を書く必要があります。サンプルでは、ボタンが押されたときにFelicaカードの検知を開始しています。
public class MainPageViewModel : BindableBase, INavigationAware
{
private IFelicaReader felicaReader;
...
public DelegateCommand ReadButtonClickedCommand { get; private set; }
public MainPageViewModel()
{
this.felicaReader = CrossFelicaReader.Current;
this.ReadButtonClickedCommand = new DelegateCommand(() => ButtonClicked());
...
}
private void ButtonClicked()
{
this.felicaReader.FindCard();
}
FelicaReaderプラグインでは、以下の2つのインターフェースを提供します。
凡例
- ○ 実装済み
- △ 実装を予定
- ー 実装せず
Felicaカードを検知したときに、アプリが通知を受け取るための機能を提供します。
API | 説明 | Android | UWP |
---|---|---|---|
EnableForeground | フォアグラウンドでのカード検知の有効設定 | ○ | △ |
DisableForeground | フォアグラウンドでのカード検知の無効設定 | ○ | △ |
FindCard | カード検知の開始 | ー | ○ |
IsSupported | Felicaカード読み取り機能の対応状況の取得 | ○ | ○ |
IsEnabled | Felicaカード読み取り機能の有効・無効状態の取得 | ○ | ○ |
WhenCardFound | Felicaカード検知の通知を登録するIObservableの取得 | ○ | ○ |
WhenCardfoundで返されるIObservableインスタンスのサブスクライバーは、Felicaカードを検知すると、IFelicaCardMediaインターフェースを実装したクラスのインスタンスを受け取ります。
検知したFelicaカードの情報を取得するための機能を提供します。 Felicaカードへのコマンド送信は、Felicaカードユーザーズマニュアル抜粋版に 記載されたコマンドの一部だけを実装しています。
API | 説明 | Android | UWP |
---|---|---|---|
GetIdm | 検知したFelicaカードのIDm取得 | ○ | ○ |
Send | 検知したFelicaカードへの任意のバイトデータの送信 | ○ | ○ |
Polling | Pollingコマンドの送信、応答の解析 | ○ | ○ |
ReadWithoutEncryption | ReadWithoutEncryptionコマンドの送信、応答の解析 | ○ | ○ |
RequestService | RequestServiceコマンドの送信、応答の解析 | ○ | ○ |
RequestSystemCode | RequestSystemCodeコマンドの送信、応答の解析 | ○ | ○ |
RequestResponse | RequestResponseコマンドの送信、応答の解析 | ○ | ○ |
SearchServiceCode | SearchServiceCodeコマンドの送信、応答の解析 | ○ | ○ |
LICENSEを参照してください。
プラグインに含まれるPcscSdkプロジェクトは、 Universal Windows Platform (UWP) app samples のNear field communication (NFC) sample(Samples/Nfc)に含まれるライブラリを修正したものです。