[kotlin] android 11以降の NFC 取得処理

今回は、NFC取得処理について、個人で書いているときに詰まったので備忘録的にまとめました。
誰かの参考になると幸いです。

今回使ったNFC

今回使ったNFCは、以下のフェリカを使っています。防水対応しているらしい。ちなみに、このフェリカを使った理由は、一番取得にかかる時間が短そうだし品質も悪くなさそうだからです。

5枚セット FeliCa [フェリカ] カード Lite-S (無地) [大手企業・教育機関で導入実績有]
【5枚セット】大手企業・教育機関で導入実績あり 他、1枚・10枚セット・30枚セット・50枚セット・100枚セット・200枚セット・300枚セットがございます。 社員証、学生証、ポイントカード、勤怠管理システム、入退室管理システム、セキュリ...

このNFCに情報を書きこむ際には、NFC Toolsを使いました。情報の書き込みも読み取りもできるすぐれもの。今回は、テキスト文字で「あ」と入力しました。

NFC Tools - Google Play のアプリ
NFC Tools アプリで、NFCタグの読み取りと書き込みができます。

NFC取得処理

manifestにNFC取得処理のリクエストを書く

NFC処理のためにandroid manifestの以下の部分にpermissionを追加します。

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools">
    
    /*以下の処理を追記*/
    <uses-permission android:name="android.permission.NFC" />
    <uses-feature
        android:name="android.hardware.nfc"
        android:required="true" />

そのあと、一旦実行しよ~と思って動かそうとするとSDKが低いとエラーが吐かれました….
ですので、gradleのcompileSdk・targetSdkを34にあげました。

android {
    namespace = "com.example.nfc_acquisition"
    compileSdk = 34  /*変更*/

    defaultConfig {
        applicationId = "com.example.nfc_acquisition"
        minSdk = 24
        targetSdk = 34  /*変更*/
        versionCode = 1
        versionName = "1.0"

変更後は一応実行することができました。

全体のコード

そして今回の全体的なコードは以下のようになります

class MainActivity : ComponentActivity() {

    private var nfcAdapter: NfcAdapter? = null
    private var pendingIntent: PendingIntent? = null
    /*取得したテキスト*/
    private var getText by mutableStateOf("")

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContent {
            NFC_AcquisitionTheme {
                // A surface container using the 'background' color from the theme
                Surface(
                    modifier = Modifier.fillMaxSize(),
                    color = MaterialTheme.colorScheme.background
                ) {
                    Text(
                        text = "取得した値:$getText",
                    )
                }
            }
        }

        nfcAdapter = NfcAdapter.getDefaultAdapter(this)
        val intent = Intent(this, javaClass).also {
            it.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
        }
        val flags = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
            PendingIntent.FLAG_MUTABLE or PendingIntent.FLAG_UPDATE_CURRENT
        } else {
            PendingIntent.FLAG_UPDATE_CURRENT
        }
        pendingIntent = PendingIntent.getActivity(
            this,
            0,
            intent,
            flags
        )

    }

    override fun onResume() {
        super.onResume()

        nfcAdapter!!.enableForegroundDispatch(this, pendingIntent, null, null)
    }

    override fun onPause() {
        super.onPause()

        nfcAdapter?.disableForegroundDispatch(this)
    }

    override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)

        if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent?.action) {
            val rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
            val message = rawMessages?.map { it as NdefMessage }?.firstOrNull()

            if (message != null) {
                val record = message.records.firstOrNull()
                val payload = record?.payload
                val text = String(payload ?: ByteArray(0), Charsets.UTF_8)
                getText = text
            }
        }
    }
}

画面はこのようになっています。
NFCが取得されると、取得した値の部分に値を表示します。

onNewIntent

override fun onNewIntent(intent: Intent?) {
        super.onNewIntent(intent)

        if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent?.action) {
            val rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
            val message = rawMessages?.map { it as NdefMessage }?.firstOrNull()

            if (message != null) {
                val record = message.records.firstOrNull()
                val payload = record?.payload
                val text = String(payload ?: ByteArray(0), Charsets.UTF_8)
                getText = text
            }
        }
    }

NFC取得するたびにこのonNewIntentが呼び出されます。
ここでは、NFCからデータを読み取りgetTextに値を代入します。

まとめ

今回は、androidアプリ開発でNFC取得するための処理をまとめました。個人的になぜか詰まったのでこれで解決できる人がいれば幸いです。

他にこのような記事を書いていますので興味があれば~。

機種によりカメラ起動中にNFC処理が反応しない件
個人的な android 開発中に、カメラの起動中に NFC の取得処理を挟もうとしたのだが、正しく処理できる場合とできない場合が存在した... android のバージョンが 11 以降だと NFC の処理ががらりと変わるので、それが原因...

コメント

タイトルとURLをコピーしました