我刚刚更新了一个旧的应用程序,并将targetSdkVersion
和compileSdkVersoin
从30升级到33。
更新后,现有的NFC功能似乎停止工作。发现intent.getAction()
方法在onNewIntent()
中返回null
,当NFC标签被扫描时会调用该方法。以下是一些相关代码:
@Override
public void onNewIntent(Intent intent) {
String action = intent.getAction(); // This is null now!
boolean correctAction = NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
|| NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action);
if (correctAction) {
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if (mTask != null && !Sensor.getId(tag).equals(mTask.getSensorId())) {
showAlert(R.string.wrong_sensor_error);
} else {
Parcelable[] rawMessages = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
handleNFC(tag, rawMessages);
}
}
}
下面是一些设置代码,其中删除了一些不相关的方法:
public abstract class BaseActivity extends AppCompatActivity {
public static final String EXTRA_TASK = "extra_task";
private NfcAdapter mAdapter;
private PendingIntent mPendingIntent;
private IntentFilter[] mFilters;
private String[][] mTechLists;
private AlertDialog mNfcAlert;
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setUpNFC();
}
@Override
public void onResume() {
super.onResume();
validateToken();
if (mAdapter != null && mAdapter.isEnabled()) {
try {
mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists);
} catch (Exception e) {
FirebaseCrashlytics.getInstance().recordException(e);
setUpNFC();
}
} else {
showNfcAlert();
}
}
private void setUpNFC() {
mAdapter = NfcAdapter.getDefaultAdapter(this);
Intent intent = new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
mPendingIntent = PendingIntent.getActivity(this, 415, intent, PendingIntent.FLAG_MUTABLE);
} else {
mPendingIntent = PendingIntent.getActivity(this, 415, intent, 0);
}
IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
ndef.addDataType("*/*");
} catch (IntentFilter.MalformedMimeTypeException e) {
FirebaseCrashlytics.getInstance().recordException(e);
}
mFilters = new IntentFilter[] {ndef};
String[] r11 = new String[] {NfcA.class.getName(), Ndef.class.getName(), IsoDep.class.getName()};
String[] r12 = new String[] {NfcA.class.getName(), IsoDep.class.getName()};
mTechLists = new String[][] {r11, r12};
mNfcAlert = new AlertDialog.Builder(this)
.setMessage(R.string.nfc_disabled)
.setPositiveButton(R.string.nfc_settings, new DialogInterface.OnClickListener() {
// ....
})
.setNegativeButton(android.R.string.cancel, null).create();
}
// ......
}
在新版本中,Android中的NFC功能是否有一些变化?为什么此代码在针对API 30时有效,而不是API 33?
1条答案
按热度按时间myzjeezk1#
我想我可能找到解决办法了。
Android 11及更高版本要求将
PendingIntent
显式标记为可变或不可变(https://developer.android.com/reference/android/app/PendingIntent#FLAG_MUTABLE)。在Android 11之前,默认情况下PendingIntent
被视为可变。NFC流似乎修改了
PendingIntent
中的Intent
,以便添加诸如从Intent#getAction()
返回的字段之类的字段。如果PendingIntent
通过FLAG_IMMUTABLE
被标记为不可变,则其中的Intent
无法修改,因此Intent
中的某些字段不会被填充。至少理论上是这样