Since Android SDK 30, packages does not have full visibility of other packages by default (https://developer.android.com/training/package-visibility).
Basically, starting with API level 30, if you're targeting that version or higher, your app cannot see, or directly interact with, most external packages without explicitly requesting allowance, either through a blanket QUERY_ALL_PACKAGES permission, or by including an appropriate element in your manifest.
(intent.resolveActivity returns null in API 30)
Even while adding the blanket QUERY_ALL_PACKAGES
permission, you apparently still need to add specific queries
Even when permission QUERY_ALL_PACKAGES is added, you still need to add filter to your AndroidManifest.
(What does QUERY_ALL_PACKAGES permission do?)
How do you locate the specific query filter required for NFC actions? I have tried adding everything imaginable to AndroidManifest but without success. Currently my full AndroidManifest file looks like this:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.operationBlipp">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.NFC" />
<permission android:name="android.permission.QUERY_ALL_PACKAGES" />
<uses-feature android:name="android.hardware.nfc"
android:required="true" />
<application
android:networkSecurityConfig="@xml/network_security_config"
android:allowBackup="true"
android:icon="@mipmap/logo_ob_round"
android:label="@string/app_name"
android:roundIcon="@mipmap/logo_ob_light_round"
android:supportsRtl="true"
android:usesCleartextTraffic="true"
android:theme="@style/Theme.NFCApplication">
<activity
android:name="com.example.operationBlipp.MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<action android:name="android.nfc.action.TECH_DISCOVERED"/>
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter" />
</activity>
</application>
<queries>
<package android:name="android.nfc" />
<intent>
<action android:name="android.intent.action.ACTION_TAG_DISCOVERED" />
</intent>
<intent>
<action android:name="android.intent.action.*" />
</intent>
</queries>
</manifest>
And everything compiles but I still just get returned null from resolveIntent as seen here:
@Override
protected void onNewIntent(Intent intent) {
super.onNewIntent(intent);
List<ResolveInfo> resolveInfos = getPackageManager().queryIntentActivities(intent, 0);
setIntent(intent);
resolveIntent(intent);
}
private void resolveIntent(Intent intent) {
String action = intent.getAction();
if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))
{
tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
assert tag != null;
tagHeader = new NFCTagHeader(tag);
Toast.makeText(this, "New card with UID " + tagHeader.getUID() + " detected", Toast.LENGTH_SHORT).show();
}
else if (action == null) {
Log.e("NullAction", "Action is null!");
}
}
I think there was some update for androidstudio which broke this recently because I reverted commits to ones not targeting SDK 30 and encountered the same issue. Maybe there's something else that causes this?
Edit:
Some clarification and added code. It has worked before and is (used to be) a fully functioning application, currently the NFC adapter is initialized in the main function with:
nfcAdapter = nfcHandler.createAdapter(this);
assert nfcAdapter != null;
with the called code basically being
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(context);
which is then used in onResume to enable foreground dispatch:
@Override
protected void onResume() {
super.onResume();
assert nfcAdapter != null;
nfcAdapter.enableForegroundDispatch(this, pendingIntent, null, null);
}
ResolveIntent() gets properly called every time you scan an NFC card but the intent.getAction();
now only returns null.