android 更新到API 33后处理NFC时,`onNewIntent()`中`intent.getAction()`为空

jv4diomz  于 2023-03-28  发布在  Android
关注(0)|答案(1)|浏览(492)

我刚刚更新了一个旧的应用程序,并将targetSdkVersioncompileSdkVersoin从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?

myzjeezk

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中的某些字段不会被填充。
至少理论上是这样

相关问题