Androidで画面上にボタンがあり、そのボタンを押している間だけNFCタグを読み込むようにしたいです

下記のコードで実現しようとしているのですが、ボタンを押している間にNFCカードを近づけても表示が変わらず、うまくいきません。  
どうやらNFCタグが近くにあってもonNewIntentが発生しないようです。  
なぜでしょうか?

読み取り用のボタンを押すと"Now Reading A tag"は表示されるのでOnTouchは補足できているようです。

Pixel3(日本モデルのためFelicaカード対応)上のAndroid 10 (API 29)で動かそうとしています

* * *

### Update

enableForegroundDispatchのtechlistを明示的に指定してみましたがうまく行きませんでした。

```

    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)
            )
    
```

* * *

### Update 2

Kouki.
WさんがおっしゃるようにenableForegroundDispatchでは実現が難しそうだったため、enableReaderModeに変えてみましたがやはりうまくできません。

```

    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_B or
                                NfcAdapter.FLAG_READER_NFC_BARCODE or
                                NfcAdapter.FLAG_READER_NFC_F or
                                NfcAdapter.FLAG_READER_NFC_V
                                ),
                        null)
    
    
```

### Update 2おわり

* * *

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: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:

```

    class MainActivity : AppCompatActivity() {
        var pendintent: PendingIntent? = null
        var nfc_adapt: NfcAdapter? = null
        var iFilter: IntentFilter? = null
        var tview: TextView? = null
        var read_button:  Button? = null // 読み込むときに押すボタン
        var delete_button: Button? = null // TextView(tview)の内容を消すときに押すボタン
        @SuppressLint("ClickableViewAccessibility")
        override fun onCreate(savedInstanceState: Bundle?) {
            super.onCreate(savedInstanceState)
            setContentView(R.layout.activity_main)
            tview = findViewById(R.id.textView) // 表示用のTextView
            nfc_adapt = NfcAdapter.getDefaultAdapter(applicationContext)
            pendintent = PendingIntent.getActivity(this, 0, Intent(this, javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0
            )
            iFilter = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
            val iFilters = 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!!.enableForegroundDispatch(this, pendintent,iFilters, null)
                        return false
                    }
                    MotionEvent.ACTION_UP -> {
                        nfc_adapt!!.disableForegroundDispatch(this)
                        tview!!.text = ""
                        return false
                    }
                }
                return false
            })
    
            // Delete contents of TextView
    
            delete_button!!.setOnClickListener {
                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)
            val action: String? = intent.action
            if (action.equals(NfcAdapter.ACTION_TECH_DISCOVERED)) {
                var nfc_tag_array = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_TAG)
                if (nfc_tag_array == null) {
                    tview?.setBackgroundColor(Color.YELLOW)
                    tview?.setTextColor(Color.rgb(0,0,0))
                    tview?.text =  "read a tag but does not contain tag data"
                    return
                }
                val t = nfc_tag_array[0] as Tag?
                if (t == null) {
                    tview!!.text = "Read a tag but it a null"
                } else {
                    tview!!.text = t.toString() // TAGの内容(データではない)を文字列で表示する
                }
                tview!!.setBackgroundColor(Color.YELLOW)
                tview!!.setTextColor(Color.rgb(0,0,0))
                nfc_adapt!!.disableForegroundDispatch(this)
                read_button!!.isEnabled = false // 読んだら一旦読み込みボタンを無効にしてdelete_buttonが押されたら再度読み込みできるようにする
                delete_button!!.isEnabled = true
    
    
            }
            else {
                // nothing to do
            }
        }
    
    }
    
```
CC BY-SA 4.0
2020-07-22T10:05:20.007
68827
2020-07-23T16:44:43.440
2020-07-23T14:33:03.690
5246
5246
question
android kotlin
Androidでボタンを押している間だけNFCタグのデータを読み込ませたい
こんにちは、少し古い端末(Android 4.1.2/API Level16)で頂いたコードを拝見/確認させていただきました。

enableForegrondDipatchがうまく動作しないとのことですが、こちらドキュメントを確認すると以下のようにあります。

> This method must be called from the main thread, and only when the activity
> is in the foreground (resumed).

このメソッドですが、フォアグラウンドになっているアプリを最優先にしてNFCカードのイベントに反応させるために用います。(当然OS内の他のアプリやサービスもNFCはスキャンしてるのでスキャンを止めることはできません)。そのためライフサイクルイベント内のonResumeで開始、onPauseで停止という用法が正しいです。実際そのように実装した場合は当方では問題なく動作しています。

ボタンを押した時のみなど一時的に反応させたい理由があるのであれば、ボタンで読み取り用のアクティビティ/フラグメントを起動、読み取り後、前のページに戻すなど、別の実装方法を検討されてはいかがでしょうか?

スレッド関係で、頑張れば動かせる可能性はありますが、あまり推奨されないやりかたに思えます。

<https://developer.android.com/guide/topics/connectivity/nfc/advanced-
nfc?hl=ja#foreground-dispatch>

[https://developer.android.com/reference/android/nfc/NfcAdapter#enableForegroundDispatch(android.app.Activity,%20android.app.PendingIntent,%20android.content.IntentFilter[],%20java.lang.String[][])](https://developer.android.com/reference/android/nfc/NfcAdapter#enableForegroundDispatch\(android.app.Activity,%20android.app.PendingIntent,%20android.content.IntentFilter%5B%5D,%20java.lang.String%5B%5D%5B%5D\))

## 追記

NfcAdapter.enableReadMode (Android 4.4から実装)
を利用してonResume以外のタイミングからNFCのActivityによる読み取りが行えたとの旨コメントをいただきました。

<https://qiita.com/zaburo/items/6a34dfd8f87d7ffba56a>
CC BY-SA 4.0
2020-07-23T09:09:34.973
68859
2020-07-23T16:44:43.440
2020-07-23T16:44:43.440
37777
37777
68827
answer