I have an application which starts in Kiosk mode and should read and react on NFCTags. It's using enableReaderMode
on the NFCAdapter
in onResume
to start reading them. Everything works fine if the app is e.g. (re-)started during development. However, if I reboot the device (and the activity gets started automatically) the activity is only sometimes put into the right mode, but often only plays the NFC system sound and my handleTag
is not called.
From what I logged, the NFCAdapter setup code I have is correctly called in all circumstances
I tried enableForegroundDispatch
as well, but there's the same effect. I also tried periodically recalling enableReaderMode
but it also has the same effect.
Anybody has an idea what's going on?
Update
I see this error message in the logs when I try to set the reader mode in the cases where it fails
NfcService: setReaderMode: Caller is not in foreground and is not system process.
Although the activity is clearly visible in the forgreound.
Phone is a Google Pixel 3
The application is device owner through
adb shell dpm set-device-owner ...
The manifest of the application
<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"
android:testOnly="true">
<!-- snip DeviceAdminReceiver -->
<activity
android:name=".FullscreenActivity"
android:screenOrientation="reverseLandscape"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:theme="@style/FullscreenTheme">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.HOME" />
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" />
The FullscreenActivity which should handle the NFC Tag
public class FullscreenActivity extends AppCompatActivity {
NfcAdapter mAdapter;
private DevicePolicyManager mDevicePolicyManager;
private ComponentName mAdminComponentName;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mDevicePolicyManager = (DevicePolicyManager) getSystemService(
Context.DEVICE_POLICY_SERVICE);
if (mDevicePolicyManager.isDeviceOwnerApp(getPackageName())) {
mAdminComponentName = MyDeviceAdminReceiver.getComponentName(this);
IntentFilter intentFilter = new IntentFilter(Intent.ACTION_MAIN);
intentFilter.addCategory(Intent.CATEGORY_HOME);
intentFilter.addCategory(Intent.CATEGORY_DEFAULT);
mDevicePolicyManager.addPersistentPreferredActivity(
mAdminComponentName, intentFilter,
new ComponentName(getPackageName(),
FullscreenActivity.class.getName()));
mDevicePolicyManager.setLockTaskPackages(mAdminComponentName,
new String[]{getPackageName()});
mDevicePolicyManager.setKeyguardDisabled(mAdminComponentName, true);
}
startLockTask();
}
@Override
public void onWindowFocusChanged(boolean hasFocus) {
super.onWindowFocusChanged(hasFocus);
if (hasFocus) {
setFullscreenFlags();
}
}
private void setFullscreenFlags() {
getWindow().getDecorView()
.setSystemUiVisibility(View.SYSTEM_UI_FLAG_LOW_PROFILE
| View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
| View.SYSTEM_UI_FLAG_FULLSCREEN
| View.SYSTEM_UI_FLAG_LAYOUT_STABLE
| View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY
| View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
| View.SYSTEM_UI_FLAG_HIDE_NAVIGATION);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
}
@Override
protected void onResume() {
super.onResume();
setFullscreenFlags();
mAdapter = NfcAdapter.getDefaultAdapter(this);
setupNfcAdapter();
}
private void setupNfcAdapter() {
if (mAdapter == null) return;
Bundle options = new Bundle();
// No sure this is needed
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 50000);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0,
new Intent(this, getClass())
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
mAdapter.enableReaderMode(this, this::handleTag,
NfcAdapter.FLAG_READER_NO_PLATFORM_SOUNDS |
NfcAdapter.FLAG_READER_NFC_A |
NfcAdapter.FLAG_READER_NFC_B |
NfcAdapter.FLAG_READER_NFC_F |
NfcAdapter.FLAG_READER_NFC_V, options);
}
@Override
protected void onPause() {
super.onPause();
if (mAdapter != null) {
mAdapter.disableReaderMode(this);
}
}
private void handleTag(Tag tag) {
Log.d("NFCADAPTER", "tag detected");
}
}
enableReaderMode
does not help you as it helped me (on Galaxy A40 if that matters) with the same issue. I callenableReaderMode
in 100 ms interval for the first second after I need to enable the reader mode. Thank you for posting update as it really helped me to pin the problem (Caller is not in foreground and is not system process). See this question as well. – Lutero