On Android, there is a button on the screen, and I want to read NFC tags only while I press that button
I'm trying to do it with the code below, but when I put the NFC card close while I was pressing the button, the display didn't change and it didn't work.
Apparently, the onNewIntent does not occur even if the NFC tag is nearby.
Why?
"Now Reading Atag" appears when you press the read button, so OnTouch seems to have been supplemented.
I'm trying to run it on Android 10 (API 29) on Pixel 3 (Felica card compatible for Japanese model)
I explicitly specified the techlist for enableForegroundDispatch, but it didn't work.
techlist=arrayOf(
arrayOf (android.nfc.tech.NfcA::class.java.name),
arrayOf (android.nfc.tech.NfcB::class.java.name),
arrayOf (android.nfc.tech.IsoDep::class.java.name),
arrayOf (android.nfc.tech.MifareClassic::class.java.name),
arrayOf (android.nfc.tech.NfcV::class.java.name),
arrayOf (android.nfc.tech.NfcF::class.java.name),
arrayOf (android.nfc.tech.NdefFormatable::class.java.name),
arrayOf (android.nfc.tech.MifareUltralight::class.java.name)
)
As Kouki.W said, it seemed difficult to realize with enableForegroundDispatch, so I changed it to enableReaderMode, but it still doesn't work.
nfc_adapt!!.enableReaderMode(this, {t->
tview!!.text=t.toString()
tview!!.setBackgroundColor(Color.YELLOW)
tview!!.setTextColor(Color.rgb(0,0,0))
nfc_adapt!!.disableReaderMode(this)
read_button!!.isEnabled=false//disable read button until user push the delete button
delete_button!!.isEnabled=true
},(
NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK or
NfcAdapter.FLAG_READER_NFC_A or
NfcAdapter.FLAG_READER_NFC_Bor
NfcAdapter.FLAG_READER_NFC_BARCODE or
NfcAdapter.FLAG_READER_NFC_For
NfcAdapter.FLAG_READER_NFC_V
),
null)
AndroidManifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.youtube_dler">
<uses-permission android:name="android.permission.NFC">/uses-permission>
<application
android:allowBackup="true"
android: icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android: roundIcon="@mipmap/ic_launcher_round"
android:supportRtl="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:
class MainActivity:AppCompatActivity(){
var pendingintent —PendingIntent?= null
varnfc_adapt —NfcAdapter ?= null
variFilter:IntentFilter?= null
vartview —TextView?= null
var read_button —Button?=null // Button to press when loading
var delete_button —Button?=null//Press button to erase TextView (tview) contents
@SuppressLint ("ClickableViewAccessibility")
override fun onCreate (savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
tview=findViewById(R.id.textView) // TextView for display
nfc_adapt = NfcAdapter.getDefaultAdapter (applicationContext)
pendingIntent=PendingIntent.getActivity(this,0,Intent(this,javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0
)
iFilter=IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
valiFilters=arrayOf<IntentFilter> (iFilter!!)
read_button=findViewById (R.id.button)
delete_button=findViewById (R.id.button2)
delete_button!!.isEnabled=false
read_button!!.setOnTouchListener(fun(v:View, m:MotionEvent): Boolean{
when(m.action){
MotionEvent.ACTION_DOWN->{
tview!!.setBackgroundColor(Color.rgb(0,0,0))
tview!!.setTextColor(Color.rgb(0,255,0))
tview!!.text="Now Reading A Tag"
Log.d(null, "ACTION UPPED")
nfc_adapt!!.enableForegroundDispatches(this,pendintent,iFilters,null)
return false
}
MotionEvent.ACTION_UP->{
nfc_adapt!!.disableForegroundDispatches(this)
US>tview!!.text="
return false
}
}
return false
})
// Delete contents of TextView
delete_button!!.setOnClickListener{
US>tview!!.text="
tview!!.setBackgroundColor(Color.rgb(0,0,0))
tview!!.setTextColor(Color.rgb(0,255,0))
read_button!!.isEnabled=true
it.isEnabled=false
}
}
override fun onNewIntent(intent:Intent) {
super.onNewIntent(intent)
valaction —String?=intent.action
if(action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)){
varnfc_tag_array=intent.getParcelableArrayExtra(NfcAdapter.EXTRA_TAG)
if(nfc_tag_array==null){
tvview?.setBackgroundColor(Color.YELLOW)
tview?.setTextColor(Color.rgb(0,0,0))
tvview?.text="read a tag but does not contain tag data"
return
}
valt=nfc_tag_array[0]as Tag?
if(t==null){
tview!!.text="Read a tag but it a null"
} else{
tview!!.text=t.toString()// Display TAG contents (not data) as a string
}
tview!!.setBackgroundColor(Color.YELLOW)
tview!!.setTextColor(Color.rgb(0,0,0))
nfc_adapt!!.disableForegroundDispatches(this)
read_button!!.isEnabled=false//Disable the read button once you read it so that you can read it again when delete_button is pressed
delete_button!!.isEnabled=true
}
else{
// nothing to do
}
}
}
Hello, I saw/confirmed the code you gave me on the old device (Android 4.1.2/API Level 16).
I understand that enableForegrondDipatch does not work well, but when I check this document, it is as follows:
This method must be called from the main thread, and only when the activity is in the foreground (resumed).
This method is used to react to events on the NFC card with the foreground app as a top priority.(Of course, NFC scans other apps and services in the OS, so it cannot be stopped.)Therefore, the correct usage is to start with onResume in the lifecycle event and stop with onPause.In fact, if you implement it that way, it works fine for us.
If you want to react temporarily, such as only when you press a button, why don't you consider another implementation, such as launching read activity/fragments with a button, reading them, and then returning them to the previous page?
With thread relationships, you may be able to move if you work hard, but it seems like a less recommended way.
https://developer.android.com/guide/topics/connectivity/nfc/advanced-nfc?hl=ja#foreground-dispatch
We received a comment saying that NfcAdapter.enableReadMode (implemented from Android 4.4) was able to be read by NFC Activity from a time other than onResume.
https://qiita.com/zaburo/items/6a34dfd8f87d7ffba56a
© 2024 OneMinuteCode. All rights reserved.