在全屏启动器应用程序来自后台后,Android NFC 读取失败
Posted
技术标签:
【中文标题】在全屏启动器应用程序来自后台后,Android NFC 读取失败【英文标题】:Android NFC read fails after fullscreen launcher app comes from background 【发布时间】:2019-07-25 12:37:09 【问题描述】:我的应用程序是一个启动器,我在安装后立即设置为默认值,它在第一次启动时确实读取 NFC 标签没有问题,但如果我锁定手机并且他们解锁它(此时我的应用程序已经在屏幕上并且onResume()
被调用)应用停止读取标签(手机读取标签时播放不同的声音,我猜是 NFC 失败的声音)并且 onNewIntent(Intent intent)
没有被调用。
我已经尝试让我的过滤器和意图成为活动范围而不是本地(从 setupForegroundDispatch
中删除),但仍然存在同样的问题。如果我重新打开应用程序(杀死并重新启动),那么 NFC 阅读器确实可以正确读取。
所以下面是我的逻辑:
NfcAdapter nfcAdapter;
@Override
protected void onResume()
super.onResume();
if (nfcAdapter == null)
nfcAdapter=NfcAdapter.getDefaultAdapter(this);
setupForegroundDispatch(this, nfcAdapter);
public static void setupForegroundDispatch(Activity activity, NfcAdapter adapter)
final Intent intent = new Intent(activity.getApplicationContext(), activity.getClass());
final PendingIntent pendingIntent = PendingIntent.getActivity(
activity.getApplicationContext(), 0, intent, 0);
IntentFilter[] filters = new IntentFilter[2];
String[][] techList = new String[][];
filters[0] = new IntentFilter();
filters[0].addAction(NfcAdapter.ACTION_TAG_DISCOVERED);
filters[1] = new IntentFilter();
filters[1].addAction(NfcAdapter.ACTION_TECH_DISCOVERED);
adapter.enableForegroundDispatch(activity, pendingIntent, filters, techList);
@Override
protected void onNewIntent(Intent intent)
super.onNewIntent(intent);
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) ||
NfcAdapter.ACTION_TECH_DISCOVERED.equals(action))
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (tag != null)
//do my logic here
@Override
protected void onPause()
super.onPause();
nfcAdapter.disableForegroundDispatch(this);
我的清单
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="br.org.company.app">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_INTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.SEND_SMS" />
<uses-permission android:name="android.permission.READ_SMS" />
<uses-permission android:name="android.permission.CALL_PHONE" />
<uses-permission android:name="android.permission.CALL_PRIVILEGED" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission android:name="android.permission.READ_PHONE_STATE" />
<uses-permission android:name="android.permission.READ_PHONE_NUMBERS" />
<uses-permission android:name="android.permission.STATUS_BAR" />
<uses-permission android:name="android.permission.EXPAND_STATUS_BAR" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission android:name="android.permission.PREVENT_POWER_KEY" />
<uses-permission android:name="android.permission.CHANGE_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS" />
<uses-permission android:name="android.permission.REORDER_TASKS" />
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:sharedUserId="android.uid.system"
android:supportsRtl="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar"
android:versionName="1.2.1xdk"
android:usesCleartextTraffic="true">
<meta-data
android:name="com.google.android.actions"
android:resource="@xml/actions" />
<receiver android:name=".receivers.GpsLocationReceiver">
<intent-filter>
<action android:name="android.location.PROVIDERS_CHANGED" />
<category android:name="android.intent.category.DEFAULT" />
<action android:name="android.location.LocationManager.KEY_LOCATION_CHANGED" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.PassiveLocationChangedReceiver"
android:enabled="true">
<intent-filter>
<action android:name="android.location.LocationManager.KEY_LOCATION_CHANGED" />
</intent-filter>
</receiver>
<receiver
android:name=".receivers.BootReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.BOOTUP_COMPLETE" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.MyWakefulReceiver" />
<receiver android:name=".receivers.InternetConnectionReceiver">
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
<action android:name="android.net.wifi.WIFI_STATE_CHANGE" />
</intent-filter>
</receiver>
<receiver android:name=".receivers.IncomingCall">
<intent-filter>
<action android:name="android.intent.action.PHONE_STATE" />
</intent-filter>
</receiver>
<activity
android:name=".FirstScreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:sharedUserId="android.uid.system"
android:soundEffectsEnabled="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<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>
<activity
android:name=".FullscreenActivity"
android:configChanges="orientation|keyboardHidden|screenSize"
android:label="@string/app_name"
android:launchMode="singleTask"
android:screenOrientation="portrait"
android:sharedUserId="android.uid.system"
android:soundEffectsEnabled="true"
android:theme="@style/Theme.AppCompat.Light.NoActionBar">
<intent-filter>
<action android:name="android.intent.action.CALL_BUTTON" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED" />
</intent-filter>
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<data android:mimeType="text/pg" />
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_type" />
</activity>
<receiver
android:name=".AppDeviceAdmin"
android:description="@string/app_name"
android:label="@string/app_name"
android:permission="android.permission.BIND_DEVICE_ADMIN">
<meta-data
android:name="android.app.device_admin"
android:resource="@xml/app_device_admin" />
<intent-filter>
<action android:name="android.app.action.PROFILE_PROVISIONING_COMPLETE" />
<action android:name="android.app.action.DEVICE_ADMIN_ENABLED" />
</intent-filter>
</receiver>
</application>
</manifest>
在 logcat 上没有例外,看到 NFC 读取甚至没有传递到我的应用程序。 (在它从后台返回并且手机读取 NFC 后,甚至 onPause(),onResume() 都不会在我的应用程序上触发)
到目前为止,它与我的应用程序作为启动器有关,尽管我没有发现任何关于此限制的信息。
【问题讨论】:
请显示清单文件代码 @PJain 添加了清单 在这里我可以在你的代码中看到在 onNewIntent 中你只使用了 ACTION_TAG_DISCOVERED 和 ACTION_TECH_DISCOVERED 但根据 nfc 的文档,首先调度系统将尝试读取 ACTION_NDEF_DISCOVERED 所以请添加代码并重试 @PJain 添加但错误仍然存在 【参考方案1】:所以我找到了问题的答案;这个应用程序是全屏的(公司的内部应用程序)所以在我的onCreate()
我有各种标志来保持应用程序在屏幕上并尽可能避免锁定屏幕上的键盘保护(以避免用户去其他应用程序)和这就是问题所在,我的应用程序有
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON
WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
WindowManager.LayoutParams.FLAG_FULLSCREEN
并且由于某种原因阻止键盘保护出现(在锁定屏幕上运行应用程序)会禁用向应用程序的 NFC 传送(我猜是出于安全原因)。由于这是一个内部应用程序(并且所有手机都是由 IT 团队预先设置的),因此解决方案是通过手机设置手动从锁定屏幕中删除键盘保护并删除标志
WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
因此,每次用户锁定和解锁手机时,系统都会再次启用 NFC 读取器。
【讨论】:
以上是关于在全屏启动器应用程序来自后台后,Android NFC 读取失败的主要内容,如果未能解决你的问题,请参考以下文章
在全屏模式下显示状态栏 Ionic for android 和 iOS