I'm getting this (for me) unknown crash in my crashlytics log trying to call enableReaderMode()
in NfcAdapter class:
Caused by java.lang.SecurityException: Permission Denial: isUidActive from pid=XXXX, uid=XXXX requires android.permission.PACKAGE_USAGE_STATS
at android.os.Parcel.createExceptionOrNull(Parcel.java:2387)
at android.os.Parcel.createException(Parcel.java:2371)
at android.os.Parcel.readException(Parcel.java:2354)
at android.os.Parcel.readException(Parcel.java:2296)
at android.nfc.INfcAdapter$Stub$Proxy.setReaderMode(INfcAdapter.java:1027)
at android.nfc.NfcActivityManager.setReaderMode(NfcActivityManager.java:242)
at android.nfc.NfcActivityManager.enableReaderMode(NfcActivityManager.java:218)
at android.nfc.NfcAdapter.enableReaderMode(NfcAdapter.java:1580)
at com.my.package.enableNfc(MyClass.kt:23)
at java.lang.reflect.Method.invoke(Method.java)
at androidx.lifecycle.ClassesInfoCache$MethodReference.invokeCallback(ClassesInfoCache.java:216)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeMethodsForEvent(ClassesInfoCache.java:194)
at androidx.lifecycle.ClassesInfoCache$CallbackInfo.invokeCallbacks(ClassesInfoCache.java:185)
at androidx.lifecycle.ReflectiveGenericLifecycleObserver.onStateChanged(ReflectiveGenericLifecycleObserver.java:37)
at androidx.lifecycle.LifecycleRegistry$ObserverWithState.dispatchEvent(LifecycleRegistry.java:361)
at androidx.lifecycle.LifecycleRegistry.forwardPass(LifecycleRegistry.java:300)
at androidx.lifecycle.LifecycleRegistry.sync(LifecycleRegistry.java:339)
at androidx.lifecycle.LifecycleRegistry.moveToState(LifecycleRegistry.java:145)
at androidx.lifecycle.LifecycleRegistry.handleLifecycleEvent(LifecycleRegistry.java:131)
at androidx.lifecycle.ReportFragment.dispatch(ReportFragment.java:68)
at androidx.lifecycle.ReportFragment$LifecycleCallbacks.onActivityPostResumed(ReportFragment.java:188)
at android.app.Activity.dispatchActivityPostResumed(Activity.java:1469)
at android.app.Activity.performResume(Activity.java:8265)
at android.app.ActivityThread.performResumeActivity(ActivityThread.java:4714)
at android.app.ActivityThread.handleResumeActivity(ActivityThread.java:4756)
at android.app.servertransaction.ResumeActivityItem.execute(ResumeActivityItem.java:52)
at android.app.servertransaction.TransactionExecutor.executeLifecycleState(TransactionExecutor.java:176)
at android.app.servertransaction.TransactionExecutor.execute(TransactionExecutor.java:97)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:2296)
at android.os.Handler.dispatchMessage(Handler.java:106)
at android.os.Looper.loop(Looper.java:239)
at android.app.ActivityThread.main(ActivityThread.java:8071)
at java.lang.reflect.Method.invoke(Method.java)
at com.android.internal.os.RuntimeInit$MethodAndArgsCaller.run(RuntimeInit.java:626)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1015)
I'm initialzing my NfcAdapter by lazy, like this:
private val nfcAdapter: NfcAdapter? by lazy {
NfcAdapter.getDefaultAdapter(activity)
}
And handling it in that way:
fun enableNfc() {
nfcAdapter?.enableReaderMode(
activity, callback,
NfcAdapter.FLAG_READER_NFC_A or
NfcAdapter.FLAG_READER_NFC_B or
NfcAdapter.FLAG_READER_NFC_F or
NfcAdapter.FLAG_READER_NFC_V or
NfcAdapter.FLAG_READER_NFC_BARCODE,
Bundle().apply {
putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 250)
}
)
}
All devices I've tested run successfully, even those that don't have NFC available (which this feature is never triggered).
My question is: Which sort of permission should I grant besides <uses-permission android:name="android.permission.NFC" />
in manifest file? Is it a runtime permission? Why is triggering this exception related to stats ♂️? It's happening in an Android 11 device
Thanks in advance!