I am trying to send a string message from Android to Arduino with the PN532 module. When I approach the smartphone (with the app open) to the module, the "tap to beam" UI shows up, but after I tap on the screen, the phone tells me to approach the two devices again. After I approach them again (with the "approach the devices again" message still displayed on the screen), nothing happens and arduino prints out "failed".
Here is the Kotlin code:
package com.cerowski.nfcclient
import android.nfc.NdefMessage
import android.nfc.NdefRecord
import android.nfc.NfcAdapter
import android.os.Bundle
import android.widget.TextView
import android.widget.Toast
import androidx.appcompat.app.AppCompatActivity
import androidx.viewpager.widget.ViewPager
import com.cerowski.nfcclient.databinding.ActivityMainBinding
import com.cerowski.nfcclient.ui.main.SectionsPagerAdapter
import com.google.android.material.floatingactionbutton.FloatingActionButton
import com.google.android.material.snackbar.Snackbar
import com.google.android.material.tabs.TabLayout
import java.io.File
import java.io.UnsupportedEncodingException
class MainActivity : AppCompatActivity() {
private lateinit var binding: ActivityMainBinding
override fun onCreate(savedInstanceState: Bundle?) {config(); sendid();
super.onCreate(savedInstanceState)
binding = ActivityMainBinding.inflate(layoutInflater)
setContentView(binding.root)
val sectionsPagerAdapter = SectionsPagerAdapter(this, supportFragmentManager)
val viewPager: ViewPager = binding.viewPager
viewPager.adapter = sectionsPagerAdapter
val tabs: TabLayout = binding.tabs
tabs.setupWithViewPager(viewPager)
val fab: FloatingActionButton = binding.fab
fab.setOnClickListener { view ->
Snackbar.make(view, "Replace with your own action", Snackbar.LENGTH_LONG)
.setAction("Action", null).show()
}
}
fun config(){
val dir = getExternalFilesDir(null);
val file = File(dir,"config");
var msgtext="";
val msg = TextView (this)
if (dir!=null) {
if (!file.exists()) {msgtext = "config not found, attempting to create..."; file.createNewFile(); if(file.exists()) {msgtext = "config created successfully"; file.writeText(idgenerator())} else {msgtext = "problem creating file"}}
else {msgtext = (file.readText())}
} else {msgtext = "app directory not found"}
}
fun idgenerator() : String {
val allowedChars = ('a'..'z') + ('A'..'Z') + ('0'..'9')
return (1..16)
.map { allowedChars.random() }
.joinToString("")
}
fun sendid() {
val dir = getExternalFilesDir(null);
val file = File(dir,"config");
//var bytes = file.readBytes();
//var nfcmsg = NdefMessage(bytes);
//var msgtext="";
var nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (nfcAdapter != null) {
val msg: String = file.readText().toString()
val languageCode: ByteArray
val msgBytes: ByteArray
try {
languageCode = "en".toByteArray(charset("US-ASCII"))
msgBytes = msg.toByteArray(charset("UTF-8"))
} catch (e: UnsupportedEncodingException) {
return
}
val messagePayload = ByteArray(
1 + languageCode.size
+ msgBytes.size
)
messagePayload[0] = 0x02.toByte() // status byte: UTF-8 encoding and
// length of language code is 2
// length of language code is 2
System.arraycopy(
languageCode, 0, messagePayload, 1,
languageCode.size
)
System.arraycopy(
msgBytes, 0, messagePayload, 1 + languageCode.size,
msgBytes.size
)
val message: NdefMessage
val records = arrayOfNulls<NdefRecord>(1)
val textRecord = NdefRecord(
NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, byteArrayOf(), messagePayload
)
records[0] = textRecord
message = NdefMessage(records)
nfcAdapter.setNdefPushMessage(message, this);
}
else {Toast.makeText(this, "NFC is not available", Toast.LENGTH_LONG).show();}
}
}
And here is the code for my Arduino Uno with the PN532 module (the red one, if you search for photos online):
// Receive a NDEF message from a Peer
// Requires SPI. Tested with Seeed Studio NFC Shield v2
#include "SPI.h"
#include "PN532_SPI.h"
#include "snep.h"
#include "NdefMessage.h"
PN532_SPI pn532spi(SPI, 10);
SNEP nfc(pn532spi);
uint8_t ndefBuf[128];
void setup() {
Serial.begin(9600);
Serial.println("NFC Peer to Peer Example - Receive Message");
}
void loop() {
Serial.println("Waiting for message from Peer");
int msgSize = nfc.read(ndefBuf, sizeof(ndefBuf));
if (msgSize > 0) {
NdefMessage msg = NdefMessage(ndefBuf, msgSize);
msg.print();
Serial.println("\nSuccess");
} else {
Serial.println("Failed");
}
delay(3000);
}
The little switches on the NFC module are in the right positions and the module is connected to the board as it should be (for SPI), So I do not know what is the thing that causes it to fail.
Any help is much appreciated.
First check if it's even a) available, b) enabled and c) register & implement the callbacks. In Java:
MainActivity extends AppCompatActivity implements
NfcAdapter.CreateNdefMessageCallback,
NfcAdapter.OnNdefPushCompleteCallback,
NfcAdapter.CreateBeamUrisCallback {
...
if (
Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR1 &&
Build.VERSION.SDK_INT < Build.VERSION_CODES.Q
) {
NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this);
if (!nfcAdapter.isEnabled()) {
startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
} else if (!nfcAdapter.isNdefPushEnabled()) {
startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
} else {
nfcAdapter.setNdefPushMessageCallback(this);
nfcAdapter.setOnNdefPushCompleteCallback(this);
nfcAdapter.setNdefPushMessage(nfcMessage, this);
}
}
Deprecated in Build.VERSION_CODES.Q
means still available; maybe <=
.
These callbacks might also provide you with more detail, why it even fails.
Else you'll send a NDEF message and it will not know what to do next...
Alike this you might also be able to produce a proper error message.
Also see: https://developer.android.com/training/beam-files/send-files
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.