Android NFC读取应用崩溃求助:空对象引用异常
解决NFC读取Activity跳转时的空指针异常问题
我一眼就定位到问题根源了——崩溃日志里的空指针,是因为intent.getAction()返回了null,你却直接调用了equals()方法。咱们来捋清楚为什么会这样:
当把NFC读取Activity设为启动页时,系统是检测到NFC标签后才启动这个Activity的,这时传递的Intent带有明确的NFC相关Action(比如ACTION_NDEF_DISCOVERED),所以intent.getAction()不会为空。但当你从其他Activity通过按钮跳转过来时,传递的只是普通的跳转Intent,根本没有设置NFC相关Action,这时候intent.getAction()就是null,调用equals()自然就抛出空指针了。
修复方案
咱们只需要在处理Intent之前,先做一层空值判断,确保只有当Intent确实是NFC触发的情况下,才执行读取逻辑。
1. 修改onCreate中的readTag调用
在调用readTag之前,先判断当前Intent是否来自NFC触发:
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); mNfcAdapter = NfcAdapter.getDefaultAdapter(this); mNfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_CLEAR_TOP), 0); IntentFilter ndefDiscovery = new IntentFilter( NfcAdapter.ACTION_NDEF_DISCOVERED); IntentFilter tagDiscovery = new IntentFilter( NfcAdapter.ACTION_TAG_DISCOVERED); mTagFilters = new IntentFilter[]{ ndefDiscovery, tagDiscovery }; // 新增:只有当Intent是NFC相关的才调用readTag String action = getIntent().getAction(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { readTag(getIntent()); } }
2. 加固readTag方法的空判断
在方法开头就加上空值检查,避免后续逻辑出现意外:
private void readTag(Intent intent) { // 先判断intent和action是否为空,为空直接返回 if (intent == null || intent.getAction() == null) { return; } String action = intent.getAction(); if (action.equals(NfcAdapter.ACTION_NDEF_DISCOVERED) || action.equals(NfcAdapter.ACTION_TAG_DISCOVERED)) { // 原有的读取逻辑... findViewById(R.id.progress).setVisibility(View.GONE); Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); boolean writeable = writableTag(detectedTag); TextView writeableText = (TextView) findViewById(R.id.tag_writeable); writeableText.setText("Writeable? " + (writeable ? "Yes" : "No")); Ndef ndef = Ndef.get(detectedTag); if (ndef != null) { try { ndef.connect(); int maxSize = ndef.getMaxSize(); TextView infoText = (TextView) findViewById(R.id.tag_content); TextView maxSizeText = (TextView) findViewById(R.id.tag_max_size); maxSizeText.setText("Tag capacity: " + maxSize + " bytes"); TextView remainingSizeText = (TextView) findViewById(R.id.tag_remaining_size); NdefMessage message = ndef.getNdefMessage(); if (message != null) { NdefRecord[] records = message.getRecords(); StringBuilder sb = new StringBuilder(); for (NdefRecord record : records) { String payload = new String(record.getPayload(), "UTF-8"); sb.append(payload + "\n"); } String regNum = sb.toString().substring(3); infoText.setText(regNum); infoText.setTextColor(Color.BLACK); remainingSizeText.setText("Remaining capacity: " + (maxSize - message.getByteArrayLength()) + " bytes"); } else { infoText.setText("Empty tag"); infoText.setTextColor(Color.RED); remainingSizeText.setText("Remaining capacity: " + maxSize + " bytes"); } } catch (IOException e) { e.printStackTrace(); } catch (FormatException e) { e.printStackTrace(); } finally { try { ndef.close(); } catch (IOException e) { e.printStackTrace(); } } } } }
额外优化建议
- 你还可以在跳转至NFC读取Activity时,给Intent设置一个自定义Action,这样在
onCreate里能更清晰地区分是正常跳转还是NFC触发的启动。 - 另外,
onNewIntent中调用readTag是没问题的,因为这个方法只会在NFC触发Activity前台调度时被调用,此时的Intent一定带有NFC相关Action。
内容的提问来源于stack exchange,提问作者Tinovimba Mawoyo
相关产品推荐
相关产品推荐

