Android 通过所有活动检测NFC标签
我正在开发基于Android NFC的应用程序,要求从任何活动中不断地将数据读/写到SLIX-2(ICode)标记 从现在起,应用程序开始初始化NFCManager,它完成标记检测的大部分繁重工作,持续轮询状态检查、读写数据 BaseActivity使用其他必需的工作来初始化ANFCManager,例如挂起的重新启动意图、检查nfc适配器、启用ForegroundDispatch等等Android 通过所有活动检测NFC标签,android,nfc,Android,Nfc,我正在开发基于Android NFC的应用程序,要求从任何活动中不断地将数据读/写到SLIX-2(ICode)标记 从现在起,应用程序开始初始化NFCManager,它完成标记检测的大部分繁重工作,持续轮询状态检查、读写数据 BaseActivity使用其他必需的工作来初始化ANFCManager,例如挂起的重新启动意图、检查nfc适配器、启用ForegroundDispatch等等 private fun initField() { mNfcManager = ANfcManager(th
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,并将使用ANfcManager API进行读/写操作。还可以在NFC管理器中使用具有looper内部类的处理程序来持续检查标记的存在性
下面是ActivityA中的函数,它触发标记检测后的方法以及状态检查线程
override fun dispatchActionOnTag(tag: Boolean) {
mNfcStatus = tag
if (nfcStateListener() != null) {
nfcStateListener().updateNfcState(tag)
mNfcManager.startTagCheck() // presence check handler every x sec
}
}
在标记检测和存在性检查的每个活动中都重复了相同的功能(有点不干净,但仍然有效)&基于对标记的读/写数据
我的问题来了,
先决条件:
- 我的应用程序(产品)中的标签位于固定位置(粘贴在硬件中)&除非有标签更改,否则通常不会取出
- 在某些情况下,标记可以在大部分ActivityB中取出,或者ActivityC活动将运行,这需要在这些活动中重复相同的回调代码
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()
}
}
类ANfcManager@Inject构造函数(上下文:context){
private val mContext=上下文
私有lateinit变量nfcAdapter:nfcAdapter
私有lateinit变量mTag:Tag
私有lateinit变量iCodeTag:ICodeSlix2
私有lateinit变量icode:icode
初始化{
val readPermission=ContextCompat.checkSelfPermission(
McContext,
Manifest.permission.WRITE\u外部存储
)==已授予PackageManager.PERMISSION\u权限
如果(!readPermission){
ActivityCompat.requestPermissions(
McContext作为活动,
arrayOf(Manifest.permission.WRITE\u外部存储),113
)
}
/**
*每x秒初始化后台线程以进行状态检查。
*/
val thread=HandlerThread(“存在检查线程”)
thread.start()
mHandler=PresenceHandler(thread.looper)
}
趣味使能ForegroundDispatch(
活动:碎片活动,意图:悬而未决,
过滤器:阵列?,技术列表:阵列?
) {
nfcAdapter.enableForegroundDispatch(活动、意图、过滤器、技术列表)
}
fun disableForegroundDispatch(活动:活动){
nfcAdapter.disableForegroundDispatch(活动)
}
趣味过滤器内容(意图:意图):布尔值{
val action=intent.action
如果(NfcAdapter.ACTION\u TECH\u DISCOVERED==操作
||NfcAdapter.ACTION\u TAG\u DISCOVERED==操作
||NfcAdapter.ACTION\u NDEF\u DISCOVERED==操作
) {
if(intent.hasExtra(NfcAdapter.EXTRA_标签)){
mTag=intent.getParcelableExtra(NfcAdapter.EXTRA_标签)!!
返回if(discoverTag()){
Toast.makeText(mContext,“检测到标记”,Toast.LENGTH\u SHORT.show())
符合事实的
}否则{
ignoreTag()
错误的
}
}
}
返回错误
}
/**
*发现标记族。
*/
fun discoverTag():布尔值{
icode=getTag(mTag)
if(ICodeSlix2::class.java.isInstance(icode))
iCodeTag=icode作为ICodeSlix2
返回iCodeTag!=null
}
有趣的检查nfcpowerstatus():布尔值{
返回检查NFCPowerstatus(mContext)
}
/**
*检查Nfc状态
*/
私有乐趣检查NFCPowerstatus(上下文:上下文?):布尔值{
nfcAdapter=nfcAdapter.getDefaultAdapter(上下文)
var enabled=false
如果(nfcAdapter!=null){
enabled=nfcAdapter.isEnabled
}
返回启用
}
有趣的writeUpdateBlocks(){
试一试{
iCodeTag.connect()
.
.//专有代码
.
}捕获(e:IOException){
e、 printStackTrace()
Log.e(标记“IOException:”,e)
}捕获(e:SmartCardException){
e、 printStackTrace()
Log.e(标记“SmartCardException:”,e)
}捕获(e:IllegalArgumentException){
e、 printStackTrace()
Log.e(标记“IllegalArgumentException:”,e)
}捕获(e:非法状态例外){
e、 printStackTrace()
Log.e(标记“IllegalArgumentException:”,e)
}捕获(e:IndexOutOfBoundsException){
e、 printStackTrace()
Log.e(标记“IndexOutOfBoundsException:”,e)
}最后{
iCodeTag.close()
}
}
必需:-从ActvityA->ActivityB切换时,标签检测
未完成流动(onNewIntent)或未从附近取出标签
并再次点击。我将如何向标签写入/读取数据
因此,标记对象是一个可包裹的对象,只需将其从ActivityA传递到ActivityB,您无需重新发现它
e、 g.类似(对不起,在Java中不是Kotlin)活动a
Intent Intent=newintent(getActivity(),ActivityB.class);
意向。额外(“标签”,mTag);
星触觉(意向);
在活动BonCreate
Intent-Intent=getIntent();
mTag=intent.getParcelableExtra(“标记”)
//开始使用标签做一些事情,就像通过discovery获得一样
//ANfcManager可能需要一个“setTag”方法来设置它而不进行发现。
//或者允许在ANfcManager构造函数中传递标记
并不是说我会使用
enableForegroundDispatch
来读取,尤其是写入标记,因为我发现它太不可靠了,我建议您使用enabledreadermode
,但是您仍然可以在活动之间传递标记对象。很快将Manager类转换为Singleton,其余的都保持不变
基本活动
fun initField() {
mNfcManager = ANfcManager.getInstance(this)
}
class ANfcManager private constructor(context: Context){
companion object : SingletonHolder<ANfcManager, Context>(::ANfcManager) {
val TAG = ANfcManager::class.java.simpleName
}
init{
mContext = context
.
.
.
}
}
fun initField(){
mNfcManager=ANfc