経緯
ふと、AndroidでNFCタグを書き込むことをやりたくなった。
数年前にJavaで書いて以来すっかり忘れてしまったので、kotlinでNFCタグに、NDEFで書き込むアプリを書いてみました。
環境
Android Stusio 3.1.3
Qua Phone (Android 7.0)
NFCタグ
コード
パーミッションとして、android.permission.NFCを要求
ハードウェアとして、nfcを搭載していることを明記したぐらいです。
注意:NFCのサンプルコードでは、ここにintentでタグを読んだ際に、アプリが起動するようにintentフィルターを書いたりするが、今回のコードは、書き込みなので、アプリ起動していない時に、書き込みしないようにするため、ここには、intentフィルターは書きません。
AndroidManifest.xml
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="jp.eguchi.android.nfc_writer">
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>
MainActivity.kt
package jp.eguchi.android.nfc_writer
// Androidで、NFCタグに書き込んでみる Kotlin
// Progmramed by Kazuyuki Eguchi
import android.app.PendingIntent
import android.content.Intent
import android.content.IntentFilter
import android.nfc.*
import android.nfc.tech.Ndef
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
class MainActivity : AppCompatActivity() {
private val TAG: String = "Debug"
private var intentFiltersArray: Array<IntentFilter>? = null
private var techListsArray: Array<Array<String>>? = null
private var mAdapter: NfcAdapter? = null
private var pendingIntent: PendingIntent ? = null
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
Log.d(TAG,"onCreate")
val intent = Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)
pendingIntent = PendingIntent.getActivity(this,123,intent,0)
val ndef = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED).apply {
this.addDataType("*/*")
}
intentFiltersArray = arrayOf(ndef)
techListsArray = arrayOf(
arrayOf(android.nfc.tech.Ndef::class.java.name),
arrayOf(android.nfc.tech.NdefFormatable::class.java.name))
mAdapter = NfcAdapter.getDefaultAdapter(applicationContext)
}
override fun onResume() {
super.onResume()
Log.d(TAG,"onRusume()")
mAdapter?.enableForegroundDispatch(this, pendingIntent, intentFiltersArray, techListsArray)
}
override fun onPause() {
super.onPause()
Log.d(TAG,"onPause()")
mAdapter?.disableForegroundDispatch(this)
}
override fun onNewIntent(intent: Intent) {
Log.d(TAG,"onNewIntent")
if (intent == null) {
return
}
Log.d(TAG,"Action" + intent.action)
if(NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.action)) {
val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
if (tag == null) {
return
}
val ndef = Ndef.get(tag);
if(ndef == null) {
return;
}
if(ndef.isWritable) {
Log.d(TAG,"is Writable")
try {
val record = NdefRecord.createTextRecord("en","Hello")
val msg = NdefMessage(record);
ndef.connect()
ndef.writeNdefMessage(msg)
ndef.close()
} catch (e:FormatException) {
Log.d(TAG,e.toString())
}
}
}
}
}
参考:読み込みコード(onNewIntent部分のみ)
MainActivity.kt
override fun onNewIntent(intent: Intent) {
Log.d(TAG,"onNewIntent")
if (intent == null) {
return
}
Log.d(TAG,"Action" + intent.action)
if(NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.action)) {
val tag = intent.getParcelableExtra<Tag>(NfcAdapter.EXTRA_TAG)
if (tag == null) {
return
}
val ndef = Ndef.get(tag);
if(ndef == null) {
return;
}
val raws = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if(raws == null){
return;
}
var msgs = arrayOfNulls<NdefMessage>(raws.size)
for(i in 0..raws.size-1) {
msgs[i] = raws.get(i) as NdefMessage?
for(records in msgs) {
for(record in records?.records!!){
Log.d(TAG,"TNF=" + record.tnf)
Log.d(TAG,"mime=" + record.toMimeType())
Log.d(TAG,"payload=" + String(record.payload));
}
}
}
}
}