Я работаю над приложением Android NF C с требованием непрерывного чтения / записи данных в тег SLIX-2 (ICode) из любого действия.
На данный момент приложение начинает инициализировать NFCManager, который выполняет большую часть тяжелой работы по обнаружению тегов, постоянно опрашивая для проверки присутствия, чтения и записи данных.
BaseActivity выполняет инициализацию ANFCManager с другой необходимой работой, такой как ожидание перезапуска Intent, проверьте nf c адаптер, enableForegroundDispatch, ...
private fun initField() {
mNfcManager = ANfcManager(this)
}
private fun createPendingRestartIntent() {
pendingIntent = PendingIntent.getActivity(this, 0, Intent(this, javaClass)
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0
)
}
override fun onResume() {
super.onResume()
try {
if(mNfcManager.checkNfcPowerStatus()) // NfcAdapter enabled or not
setReadyToHandleTag()
else Log.w(TAG, "Nfc is not supported or disabled.")
} catch (e: AcmNfcManager.NfcNotEnabledException) {
Log.e(TAG, "Nfc not enabled", e)
}
}
private fun setReadyToHandleTag() {
try {
TECHLISTS = arrayOf(arrayOf(IsoDep::class.java.name), arrayOf(NfcV::class.java.name),
arrayOf(NfcA::class.java.name), arrayOf(NfcB::class.java.name),
arrayOf(NfcF::class.java.name),arrayOf(Ndef::class.java.name),
arrayOf(NdefFormatable::class.java.name))
val tagDetected = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
tagDetected.addCategory(Intent.CATEGORY_DEFAULT)
TAGFILTERS = arrayOf(tagDetected)
} catch (e: Exception) {
Log.e(TAG, "TECH or TAG filter no detected!!!" )
}
pendingIntent?.let { mNfcManager.enableForegroundDispatch(this, it, TAGFILTERS, TECHLISTS) }
}
override fun onNewIntent(intent: Intent) {
super.onNewIntent(intent)
nfcState = mNfcManager.filterIntent(intent)
dispatchActionOnTag(nfcState)
}
// this abs function will provide the Tag state in the corresponding class
abstract fun dispatchActionOnTag(tag: Boolean)
Каждое действие имеет NfcListener для обнаружения тегов и выполняет чтение / запись с использованием API ANfcManager. Также для постоянной проверки присутствия тега, используя обработчик с внутренним классом петлителя внутри NF C Менеджер для проверки присутствия.
Вот функция внутри ActivityA, которая запускает метод после обнаружения тега как а также поток проверки присутствия,
override fun dispatchActionOnTag(tag: Boolean) {
mNfcStatus = tag
if (nfcStateListener() != null) {
nfcStateListener().updateNfcState(tag)
mNfcManager.startTagCheck() // presence check handler every x sec
}
}
Эта же функция была повторена (не совсем чисто, но все еще работает) в каждом действии для обнаружения тегов и проверки присутствия и на основе этих данных чтения / записи в тег.
Вот моя проблема,
Предварительные условия:
Метка в моем приложении (продукте) находится на фиксированное местоположение (прикреплено к оборудованию) и обычно не вынимается, если нет изменения тега.
Существуют ситуации, когда Tag можно извлечь в основном из ActivityB или Activity C будет выполнено действие, из-за которого необходимо повторить один и тот же код обратного вызова в этих действиях.
Обязательно: - При переключении из ActvityA-> ActivityB поток обнаружения тегов не выполняется (onNewIntent) или TAg не вынимается из близости и снова нажимается. Как я буду записывать / считывать данные в тег?
ANFCManager,
class ANfcManager @Inject constructor(context: Context) {
private val mContext = context
private lateinit var nfcAdapter: NfcAdapter
private lateinit var mTag: Tag
private lateinit var iCodeTag: ICodeSlix2
private lateinit var icode: ICode
init {
val readPermission = ContextCompat.checkSelfPermission(
mContext,
Manifest.permission.WRITE_EXTERNAL_STORAGE
) == PackageManager.PERMISSION_GRANTED
if (!readPermission) {
ActivityCompat.requestPermissions(
mContext as Activity,
arrayOf(Manifest.permission.WRITE_EXTERNAL_STORAGE), 113
)
}
/**
* initialize background thread for presence check every x seconds.
*/
val thread = HandlerThread("PresenceCheckThread")
thread.start()
mHandler = PresenceHandler(thread.looper)
}
fun enableForegroundDispatch(
activity: FragmentActivity, intent: PendingIntent,
filters: Array<IntentFilter>?, techLists: Array<Array<String>>?
) {
nfcAdapter.enableForegroundDispatch(activity, intent, filters, techLists)
}
fun disableForegroundDispatch(activity: Activity) {
nfcAdapter.disableForegroundDispatch(activity)
}
fun filterIntent(intent: Intent): Boolean {
val action = intent.action
if (NfcAdapter.ACTION_TECH_DISCOVERED == action
|| NfcAdapter.ACTION_TAG_DISCOVERED == action
|| NfcAdapter.ACTION_NDEF_DISCOVERED == action
) {
if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) {
mTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)!!
return if (discoverTag()) {
Toast.makeText(mContext, "Tag detected.", Toast.LENGTH_SHORT).show()
true
} else {
ignoreTag()
false
}
}
}
return false
}
/**
* discover the Tag family.
*/
fun discoverTag(): Boolean {
icode = getTag(mTag)
if (ICodeSlix2::class.java.isInstance(icode))
iCodeTag = icode as ICodeSlix2
return iCodeTag != null
}
fun checkNfcPowerStatus(): Boolean {
return checkNfcPowerStatus(mContext)
}
/**
* Check Nfc status
*/
private fun checkNfcPowerStatus(context: Context?): Boolean {
nfcAdapter = NfcAdapter.getDefaultAdapter(context)
var enabled = false
if (nfcAdapter != null) {
enabled = nfcAdapter.isEnabled
}
return enabled
}
fun writeUpdateBlocks() {
try {
iCodeTag.connect()
.
. // proprietary code
.
}catch (e: IOException) {
e.printStackTrace()
Log.e(TAG, "IOException: ", e)
} catch (e: SmartCardException) {
e.printStackTrace()
Log.e(TAG, "SmartCardException: ", e)
} catch (e: IllegalArgumentException) {
e.printStackTrace()
Log.e(TAG, "IllegalArgumentException: ", e)
} catch (e: IllegalStateException) {
e.printStackTrace()
Log.e(TAG, "IllegalArgumentException: ", e)
} catch (e: IndexOutOfBoundsException) {
e.printStackTrace()
Log.e(TAG, "IndexOutOfBoundsException: ", e)
} finally {
iCodeTag.close()
}
}