方針変更

又、この後でISO15693を処理するためのFragmentを書くことが決まっているため、本クラスからSuperClassを抽出して、AbstractNfcTagFragmentを作ることにしよう。
■[android][sdk]UIを持たないFragment その3

元々計画していたのは、以下のようにNFCTagをハンドルするための抽象クラスを用意しておき、そこからTagの種別毎に処理を変えたクラスを実装することだった。 いわゆる「テンプレートパターン」であり、これでFragmentにNfc規格毎の実装を分離することにしたのである。

ところがこれには問題があることが判った。

NFCTagのForegroundDispatch機能はActivity毎に処理するインテントとタグ規格の種類をフィルタとして用意してやることで処理を振り分ける方法であり、NfcAdapterクラスによって提供されている。

AbstractNfcTagFragment#onResumeメソッド
    @Override
    public void onResume() {
        Activity a = this.getActivity();

        IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndef.addDataType("*/*");
        } catch (MalformedMimeTypeException e) {
            throw new RuntimeException("fail", e);
        }
        IntentFilter filters = new IntentFilter { ndef }; 
        String techList = new String{ new String[] { NfcF.class.getName() }};

        PendingIntent pendingIntent = PendingIntent.getActivity(a, 0, new Intent(a, a.getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this.getActivity());
        adapter.enableForegroundDispatch(this.getActivity(), pendingIntent, filters, techList );
        
        super.onResume();
    }

NFCTagのディスカバリで不可欠なのはPendingIntentとそれをフィルタするタグのタイプとテクノロジであり、XMLファイルかコードで指定したタグのタイプ、テクノロジのみをディスカバリの対象にできるのだ。

問題なのはこのPendingIntentの登録がActivityごとであり、種類の違うフィルタを使ったインテントを登録できないことだ。これでは、タグの種類毎に用意したクラス、例えば FeliCa/FeliCaLiteとISO15693で別々なインテントを待つことができないのだ。(後出しじゃんけんで後に登録したフィルタだけが有効になる)

アドホックな解決方法としては、フィルタがActivityで一つしか持てないのであればActivity毎に管理してしまうことだが、余計な処理が必要になるし、それではわざわざタグの種類が違う実装を分離する意味が無くなるわけで本末転倒である。

どうやらクラス設計まで立ち戻る必要がありそうだ。