我正在开发一个带有 NFC 的应用程序。我正在使用一个示例,其中发送和接收数据由同一 Activity 承载。现在我需要将发送转移到另一台,由于某种原因,接收不再起作用。
这是我的主要内容:
<uses-permission android:name="android.permission.NFC" />
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
<activity
android:name=".Screens.LogIn.LogInActivity"
android:launchMode="singleTop">
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
以及接收 Activity :
public class LogInActivity extends AppCompatActivity {
public static final String TAG = LogInActivity.class.getSimpleName();
private String messagesToReceive= null;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_log_in);
replaceFragment();
if (getIntent().getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED)) {
handleNfcIntent(getIntent());
}
}
private void replaceFragment() {
android.support.v4.app.FragmentTransaction ft = this.getSupportFragmentManager().beginTransaction();
LogInFragment fragment = new LogInFragment();
ft.replace(R.id.fragmentFrame, fragment, LogInFragment.TAG);
ft.commit();
}
@Override
public void onResume() {
super.onResume();
handleNfcIntent(getIntent());
}
@Override
public void onNewIntent(Intent intent) {
handleNfcIntent(intent);
}
private void handleNfcIntent(Intent NfcIntent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(NfcIntent.getAction())) {
Parcelable[] receivedArray =
NfcIntent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if(receivedArray != null) {
NdefMessage receivedMessage = (NdefMessage) receivedArray[0];
NdefRecord[] attachedRecords = receivedMessage.getRecords();
for (NdefRecord record:attachedRecords) {
String string = new String(record.getPayload());
if (string.equals(getPackageName())) { continue; }
messagesToReceive = string;
}
Toast.makeText(this, "Received " +
" Messages", Toast.LENGTH_LONG).show();
}
else {
Toast.makeText(this, "Received Blank Parcel", Toast.LENGTH_LONG).show();
}
}
}
问题是,NfcIntent.getAction()
始终等于 android.intent.action.MAIN
,即使应用程序在我使用 NFC 发送数据时打开。如您所见, list 中有操作 NDEF_DISCOVERED
。
这是我发送的内容:
public NdefRecord[] createRecords() {
NdefRecord[] records = new NdefRecord[2];
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
byte[] payload = messagesToSend.
getBytes(Charset.forName("UTF-8"));
NdefRecord record = new NdefRecord(
NdefRecord.TNF_WELL_KNOWN, //Our 3-bit Type name format
NdefRecord.RTD_TEXT, //Description of our payload
new byte[0], //The optional id for our Record
payload); //Our payload for the Record
records[0] = record;
}
else {
byte[] payload = messagesToSend.//messagesToSendArray.get(i).
getBytes(Charset.forName("UTF-8"));
NdefRecord record = NdefRecord.createMime("text/plain",payload);
records[0] = record;
}
records[1] = NdefRecord.createApplicationRecord(getActivity().getPackageName());
return records;
}
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
if (messagesToSend != null && !messagesToSend.equals("")) {
return null;
}
NdefRecord[] recordsToAttach = createRecords();
return new NdefMessage(recordsToAttach);
}
最佳答案
接收 NFC 事件的 Intent 操作 MAIN
而不是 NDEF_DISCOVERED
通常清楚地表明发送方发送了包含 Android 应用程序记录的 NDEF 消息,并且您未过滤该 NDEF 消息的第一条记录。
由于您的接收端有一个 NDEF_DISCOVERED
Intent 过滤器,因此问题很可能位于发送端。查看您的代码,这可能有几个原因:
发送方在
createNdefMessage()
中创建NDEF消息。在那里,您可以测试messagesToSend
是否为 null 或为空。如果它既不是 null 也不是空,则从 NDEF 消息创建回调返回null
:if (messagesToSend != null && !messagesToSend.equals("")) { return null; }
由于您没有透露
messagesToSend
是否为 null 或为空,因此没有人可以知道您是否真正到达了创建自己的 NDEF 消息的阶段。但是,messagesToSend
很可能为 null/空,因为从createNdefMessage()
返回null
会完全禁用 Beam。您没有透露发送方的剩余代码。因此,无法判断您是否确实注册了
createNdefMessage()
回调。你应该点个赞nfcAdapter.setNdefPushMessageCallback(this, this);
在
onCreate()
中。如果不是这种情况,Android 将使用默认的 NDEF 消息。默认 NDEF 消息通常包含应用程序的 URI 记录和 AAR。这可以解释为什么接收方会看到 Intent 操作 MAIN,因为您的 Activity 没有注册接收该特定 URI 记录。在 Jelly Bean 以下的 Android 版本上,该情况
(Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN)
计算结果为
true
,因此您将命中 if 语句的该分支。在此分支中,您将创建一个具有无效结构的 NFC 论坛文本记录。这可能会导致接收设备无法将 NDEF 记录解码为有效的文本记录。因此,接收设备可能无法将此记录与text/plain
类型的NDEF_DISCOVERED
Intent 过滤器相匹配。为了解决此问题,您需要创建有效的文本记录。文本 RTD 需要以以下形式编码的有效负载(另请参阅 this post )
+----------+---------------+--------------------------------------+ | Status | Language Code | Text | | (1 byte) | (n bytes) | (m bytes) | +----------+---------------+--------------------------------------+
whereStatus
equals to the lengthn
of theLanguage Code
if theText
is UTF-8 encoded andLanguage Code
is an IANA language code (e.g. "en" for English). Consequently, the proper way to encode that record would be:public static NdefRecord createTextRecord(String language, String text) { byte[] languageBytes; byte[] textBytes; try { languageBytes = language.getBytes("US-ASCII"); textBytes = text.getBytes("UTF-8"); } catch (UnsupportedEncodingException e) { throw new AssertionError(e); } byte[] recordPayload = new byte[1 + (languageBytes.length & 0x03F) + textBytes.length]; recordPayload[0] = (byte)(languageBytes.length & 0x03F); System.arraycopy(languageBytes, 0, recordPayload, 1, languageBytes.length & 0x03F); System.arraycopy(textBytes, 0, recordPayload, 1 + (languageBytes.length & 0x03F), textBytes.length); return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, null, recordPayload); }
当在线调用
createRecords()
方法时NdefRecord[] recordsToAttach = createRecords();
messagesToSend
要么为 null,要么为空(因为否则您将返回null
)。如果messagesToSend
特别是null
并且您点击了该行byte[] payload = messagesToSend.getBytes(Charset.forName("UTF-8"));
在
createRecords()
中,这将导致NullPointerException
(因为您尝试访问 null 实例的方法)。由于您从未捕获此异常,因此回调createNdefMessage()
将因相同的异常而失败。在这种情况下,Android 将处理此异常,并自动使用默认的 NDEF 消息(由应用程序的 URI 记录和 AAR 组成)。由于您的接收方不会过滤该 URI 记录(默认 NDEF 消息的第一个记录),因此您的接收方将仅由 AAR 标记,并且您将收到 Intent 操作 MAIN,因为 Android 假定您的 Activity 已准备好接收该记录具体的 NDEF 消息。
关于android - 接收 Intent 操作 MAIN 而不是 NDEF 消息,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45556316/