I'm trying to implement a nfc-p2p comunication Android app.
I'd want to exchange strings between two devices at the same time.
Starting from this post #25963691 I've found that the easy way is to use the method android.nfc.NfcAdapter.invokeBeam() to call again the Android Beam after the first broadcast, to let the receiving user to just tap the display and starting the second broadcast (without move and place near again the devices).
I've tried to apply this to an example app from online tutorial.
My app at the moment does not work : after the first string transfer the Android Beam does not start again, even if in debug mode I can check that the method invokeBeam is called.
Can some one help me?
This are my manifest permissions:
<uses-permission android:name="android.permission.NFC" />
<uses-feature android:name="android.hardware.nfc" android:required="true"/>
And this is my Activity:
public class MainActivity extends Activity implements NfcAdapter.OnNdefPushCompleteCallback, NfcAdapter.CreateNdefMessageCallback {
//The array lists to hold our messages
private ArrayList<String> messagesToSendArray = new ArrayList<>();
private ArrayList<String> messagesReceivedArray = new ArrayList<>();
//Text boxes to add and display our messages
private EditText txtBoxAddMessage;
private TextView txtReceivedMessages;
private TextView txtMessagesToSend;
private NfcAdapter mNfcAdapter;
private Boolean checkSent;
private Boolean checkReceived;
public void addMessage(View view) {
String newMessage = txtBoxAddMessage.getText().toString();
messagesToSendArray.add(newMessage);
txtBoxAddMessage.setText(null);
updateTextViews();
Toast.makeText(this, "Added Message", Toast.LENGTH_LONG).show();
}
@Override
public void onNdefPushComplete(NfcEvent event) {
messagesToSendArray.clear();
//This is called when the system detects that our NdefMessage was
//Successfully sent
checkSent = true;
}
public NdefRecord[] createRecords() {
NdefRecord[] records = new NdefRecord[messagesToSendArray.size() + 1];
//To Create Messages Manually if API is less than
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
for (int i = 0; i < messagesToSendArray.size(); i++){
byte[] payload = messagesToSendArray.get(i).
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[i] = record;
}
}
//Api is high enough that we can use createMime, which is preferred.
else {
for (int i = 0; i < messagesToSendArray.size(); i++){
byte[] payload = messagesToSendArray.get(i).
getBytes(Charset.forName("UTF-8"));
NdefRecord record = NdefRecord.createMime("text/plain",payload);
records[i] = record;
}
}
records[messagesToSendArray.size()] = NdefRecord.createApplicationRecord(getPackageName());
return records;
}
@Override
public NdefMessage createNdefMessage(NfcEvent event) {
//This will be called when another NFC capable device is detected.
if (messagesToSendArray.size() == 0) {
return null;
}
//We'll write the createRecords() method in just a moment
NdefRecord[] recordsToAttach = createRecords();
//When creating an NdefMessage we need to provide an NdefRecord[]
return new NdefMessage(recordsToAttach);
}
private void handleNfcIntent(Intent NfcIntent) {
if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(NfcIntent.getAction())) {
Parcelable[] receivedArray =
NfcIntent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if(receivedArray != null) {
messagesReceivedArray.clear();
NdefMessage receivedMessage = (NdefMessage) receivedArray[0];
NdefRecord[] attachedRecords = receivedMessage.getRecords();
for (NdefRecord record:attachedRecords) {
String string = new String(record.getPayload());
//Make sure we don't pass along our AAR (Android Applicatoin Record)
if (string.equals(getPackageName())) { continue; }
messagesReceivedArray.add(string);
}
Toast.makeText(this, "Received " + messagesReceivedArray.size() +
" Messages", Toast.LENGTH_LONG).show();
updateTextViews();
}
else {
Toast.makeText(this, "Received Blank Parcel", Toast.LENGTH_LONG).show();
}
}
}
@Override
public void onNewIntent(Intent intent) {
handleNfcIntent(intent);
}
@Override
public void onResume() {
super.onResume();
updateTextViews();
if(checkReceived){
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) {
mNfcAdapter.invokeBeam(MainActivity.this);
//Toast.makeText(this, "invocato", Toast.LENGTH_SHORT).show();
Log.e("DEBUG ---", "invocato");
}
}
handleNfcIntent(getIntent());
}
private void updateTextViews() {
txtMessagesToSend.setText("Messages To Send:\n");
//Populate Our list of messages we want to send
if(messagesToSendArray.size() > 0) {
for (int i = 0; i < messagesToSendArray.size(); i++) {
txtMessagesToSend.append(messagesToSendArray.get(i));
txtMessagesToSend.append("\n");
}
}
txtReceivedMessages.setText("Messages Received:\n");
//Populate our list of messages we have received
if (messagesReceivedArray.size() > 0) {
for (int i = 0; i < messagesReceivedArray.size(); i++) {
txtReceivedMessages.append(messagesReceivedArray.get(i));
txtReceivedMessages.append("\n");
}
checkReceived = true;
}
}
//Save our Array Lists of Messages for if the user navigates away
@Override
public void onSaveInstanceState(@NonNull Bundle savedInstanceState) {
super.onSaveInstanceState(savedInstanceState);
savedInstanceState.putStringArrayList("messagesToSend", messagesToSendArray);
savedInstanceState.putStringArrayList("lastMessagesReceived",messagesReceivedArray);
}
//Load our Array Lists of Messages for when the user navigates back
@Override
public void onRestoreInstanceState(@NonNull Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
messagesToSendArray = savedInstanceState.getStringArrayList("messagesToSend");
messagesReceivedArray = savedInstanceState.getStringArrayList("lastMessagesReceived");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
checkSent = false;
checkReceived = false;
//Check if NFC is available on device
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter != null) {
//This will refer back to createNdefMessage for what it will send
mNfcAdapter.setNdefPushMessageCallback(this, this);
//This will be called if the message is sent successfully
mNfcAdapter.setOnNdefPushCompleteCallback(this, this);
}
else {
Toast.makeText(this, "NFC not available on this device",
Toast.LENGTH_SHORT).show();
}
txtBoxAddMessage = (EditText) findViewById(R.id.txtBoxAddMessage);
txtMessagesToSend = (TextView) findViewById(R.id.txtMessageToSend);
txtReceivedMessages = (TextView) findViewById(R.id.txtMessagesReceived);
Button btnAddMessage = (Button) findViewById(R.id.buttonAddMessage);
btnAddMessage.setText("Add Message");
updateTextViews();
if (getIntent().getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED)) {
handleNfcIntent(getIntent());
}
}
}