package anywheresoftware.b4a.objects;
import java.io.UnsupportedEncodingException;
import java.nio.charset.Charset;
import java.util.Arrays;
import android.content.Intent;
import android.net.Uri;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.os.Parcelable;
import anywheresoftware.b4a.AbsObjectWrapper;
import anywheresoftware.b4a.BA.Permissions;
import anywheresoftware.b4a.BA.ShortName;
import anywheresoftware.b4a.BA.Version;
import anywheresoftware.b4a.objects.collections.List;
/**
* Supports reading NDEF (NFC Data Exchange Format) tags.
*See this <link>tutorial|http://www.b4x.com/forum/basic4android-getting-started-tutorials/14931-reading-ndef-data-nfc-tags.html</link> for more information.
*/
@Version(1.0f)
@ShortName("NFC")
@Permissions(values={"android.permission.NFC"})
public class NFC {
/**
* Tests whether the Intent contains data read from an NDef tag.
*/
public boolean IsNdefIntent(Intent Intent) {
if (Intent == null)
return false;
return Intent.hasExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
}
/**
* Retrieves the NdefRecords stored in the Intent object.
*/
public List GetNdefRecords(Intent Intent) {
List l = new List();
l.Initialize();
Parcelable[] rawMsgs = Intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
if (rawMsgs != null) {
for (int i = 0; i < rawMsgs.length; i++) {
NdefMessage nm = (NdefMessage) rawMsgs[i];
for (NdefRecord r : nm.getRecords()) {
l.Add( r);
}
}
}
return l;
}
@ShortName("NdefRecord")
public static class NdefRecordWrapper extends AbsObjectWrapper<NdefRecord> {
/**
* Returns the whole payload.
*/
public byte[] GetPayload() {
return getObject().getPayload();
}
private static java.util.List<String> UriTypes = Arrays.asList(
""
, "http://www."
, "https://www."
, "http://"
, "https://"
, "tel:"
, "mailto:"
, "ftp://anonymous:anonymous@"
, "ftp://ftp."
, "ftps://"
, "sftp://"
, "smb://"
, "nfs://"
, "ftp://"
, "dav://"
, "news:"
, "telnet://"
, "imap:"
, "rtsp://"
, "urn:"
, "pop:"
, "sip:"
, "sips:"
, "tftp:"
, "btspp://"
, "btl2cap://"
, "btgoep://"
, "tcpobex://"
, "irdaobex://"
, "file://"
, "urn:epc:id:"
, "urn:epc:tag:"
, "urn:epc:pat:"
, "urn:epc:raw:"
, "urn:epc:"
, "urn:nfc:");
/**
* Reads the payload and returns the stored text.
*/
public String GetAsTextType() throws UnsupportedEncodingException {
byte[] payload = getObject().getPayload();
String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
int languageCodeLength = payload[0] & 0077;
@SuppressWarnings("unused")
String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
String text =
new String(payload, languageCodeLength + 1,
payload.length - languageCodeLength - 1, textEncoding);
return text;
}
/**
* Reads the payload and returns the stored Uri.
*/
public String GetAsUriType() {
byte[] payload = getObject().getPayload();
String prefix = UriTypes.get(payload[0]);
byte[] prefixBytes = prefix.getBytes(Charset.forName("UTF-8"));
byte[] fullUri = new byte[prefixBytes.length + payload.length - 1];
System.arraycopy(prefixBytes, 0, fullUri, 0, prefixBytes.length);
System.arraycopy(payload, 1, fullUri, prefixBytes.length, payload.length - 1);
Uri uri = Uri.parse(new String(fullUri, Charset.forName("UTF-8")));
return uri.toString();
}
}
}
What you are looking for is NFC Beaming. This feature is not yet implemented in B4A.(1) I am an absolute newbee to android programming.
(2) By any chance, is there someone around trying to make the NFC peer-2-peer mode work with B4A? My intention is to set up a demo application that can communicate between two devices.
(3) Did I get this right, if I need a function that is provided by the android OS but not available in B4A I will have to write a java module, compile this with the help of the Java SDK and put it into the B4A folder? Or to put it this way: I will still need Java to have full access to the OS functions?
Many thanks in advance,
Christian
:sign0085:
Here's the file:
Sub Activity_Resume
Dim rString As String
Dim bType() As Byte
Dim bPayload As Byte
Dim rPack As PackStruct
rPack.Valid = False
Log("Main Resume called..")
If NFC.IsNdefIntent(Activity.GetStartingIntent) Then
Log("NFC tag found.....")
Dim records As List
records = NFC.GetNdefRecords(Activity.GetStartingIntent)
rPack = DataProcessing.ParsingNDEF(records)
ToastMessageShow("Reading tag....",True)
End If
End Sub
Here's what I've added so far :
B4X:In class NFC: /* * Return NFC tag UID */ public byte [] GeTagtUID (Intent Intent) { return Intent.getByteArrayExtra(NfcAdapter.EXTRA_ID); }
If you need a feature that is not covered by any library then you will need to implement a Java library.
There are several tutorial available for creation of new libraries.
Sub Read()
Dim key(16) As Byte
Dim block_data() As Byte
Dim bc As ByteConverter
Dim i As Int
For i = 0 To 15
key(i) = 255 '0xff
Next
'btnClear
Dim mfc As MiFare
Log("Check if the card is MF classic")
If NFC.IsMifareClassic(Activity.GetStartingIntent) Then
Dim StrData As String
mfc.Initialize(Activity.GetStartingIntent)
If True = mfc.ReadSector(0,key,0) Then' Read sector 0, key, type 0(as keyA)
Log("Read sector done")
For i = 0 To 2 'read 3 blocks of data
block_data = mfc.GetBlockData(i)
StrData = bc.HexFromBytes(block_data)
Log( "data:" & StrData)
If i = 0 Then
Label1.Text = StrData
Else If i = 1 Then
Label2.Text = StrData
Else If i = 2 Then
Label3.Text = StrData
End If
Next
End If
End If
End Sub
<meta-data android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/filter_nfc" />