I am making a NFC application that use ISO-DEP (ISO 14443-4) as TagTechnology.
I try to execute a authentication with a DESFire EV1.
The authentication work well if the chaining of the command is without pause.
But if for exemple, I make something that take time (like the Thread.Sleep after NATIVE_AUTHENTICATION_COMMAND_P1) I got an error 0x911C ("Command code not supported") during the authentication command part 2 from the card.
Normaly the error come when the authentication has been canceled. Like if the card got another command during the authentication procedure that have nothing about it.
The problem is that my application do nothing else that sending the selectApplication, Authentication Part 1, Sleep and the Part 2.
I have try the same code in C++ with a PCSC Reader and the Sleep is not the probleme, even with 5 second sleep the authentication have work on my computer.
So I would like to know if Android is "playing" with the card even after giving the Intent to the application or if the Frame Waiting Time (ISO 14443-4) is not working or NDEF "pull" broke the authentication or...
(The value of NATIVE_AUTHENTICATION_COMMAND_P2 is a exemple)
final byte[] NATIVE_AUTHENTICATION_COMMAND_P1 = new byte[]{(byte)0x90, (byte)0x0A, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00};
final byte[] NATIVE_AUTHENTICATION_COMMAND_P2 = new byte[]{(byte)0x90, (byte)0xAF, (byte)0x00, (byte)0x00, (byte)0x10, (byte)0xAB, (byte)0xB4, (byte)0x66, (byte)0xA4, (byte)0xE9, (byte)0x99, (byte)0xFF, (byte)0x5C, (byte)0xD7, (byte)0xF3, (byte)0xA7, (byte)0x81, (byte)0x62, (byte)0x2F, (byte)0xFA, (byte)0x16, (byte)0x00};
final byte[] NATIVE_SELECT_COMMAND = new byte[]{(byte)0x90,(byte)0x5A,(byte)0x00,(byte)0x00,(byte)0x03,(byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00};
IsoDep tag = IsoDep.get(tagFromIntent);
tag.connect();
byte[] result;
result = tag.transceive(NATIVE_SELECT_COMMAND); //SUCCESS
result = tag.transceive(NATIVE_AUTHENTICATION_COMMAND_P1); //SUCCESS
// Thread.sleep(1000);
result = tag.transceive(NATIVE_AUTHENTICATION_COMMAND_P2); //result = 0x90AE without Sleep and with Sleep 0x911C ("Command code not supported")
tag.close();
If someone have an idea because I am totally lost :)
UPDATE:
After the help of michael-roland and his tips; I have use the reader-mode API with NDEF check disable and delay presence check to 10 second to get my chaining command working perfectly !
#Override
protected void onResume() {
super.onResume();
Bundle options = new Bundle();
options.putInt(NfcAdapter.EXTRA_READER_PRESENCE_CHECK_DELAY, 10000);
mAdapter.enableReaderMode(this, this, NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_SKIP_NDEF_CHECK, options);
}
#Override
public void onPause() {
super.onPause();
mAdapter.disableReaderMode(this);
}
You ran into a known problem with the NFC stack for Broadcom's NFC chipset. The issue is known for quite a while (see this Android bug report, something similar applies to non APDU-based tags too).
In your case, the problem is that while the connection between the phone and the tag is idle, Android automatically performs a presence check. While this presence check is correctly implemented for NXP's NFC stack, the Broadcom version uses a READ BINARY command (for IsoDep cards) or an equivalent READ command (for other tag technologies).
So, if your command sequence is slow, Android might send a READ BINARY APDU somewhere in between your commands.
Unfortunately, this bug still exists in Android 4.4.2 and to me it seems unclear if Google will eventually do something about it. UPDATE: There is a new presence check mechanism starting with Android 5.
If you use Android 4.4, there is, however, something you can do to avoid the bug: Use the new reader-mode API to tweak the presence-check timeout. If you do not use NDEF, you could even completely disable the presence-check.
Related
I am trying to create a advertiser on Android L and my other android device is scanning that device and trying to make a connection with it.
but every time i call connectGatt i am getting BluetoothProfile.STATE_DISCONNECTED in gatt callback.
this is how i have created the advertisement
// advertisement settings
AdvertiseSettings.Builder builderSetting= new AdvertiseSettings.Builder();
builderSetting.setAdvertiseMode(AdvertiseSettings.ADVERTISE_MODE_BALANCED);
builderSetting.setConnectable(true);
builderSetting.setTimeout(0);
builderSetting.setTxPowerLevel(AdvertiseSettings.ADVERTISE_TX_POWER_HIGH);
//advertisement data
AdvertiseData.Builder builderData = new AdvertiseData.Builder();
builderData.addServiceUuid(new
ParcelUuid(UUID.fromString("00002a29-0000-1000-8000-00805f9b34fb")));
byte mServiceData[] =
{ (byte)0xff, (byte)0xfe, (byte)0x00, (byte)0x01, (byte)0x02, (byte)0x03, (byte)0x04 };
// i tried with addding service data
builderData.addServiceData(new
ParcelUuid(UUID.fromString("00002a29-0000-1000-8000-00805f9b34fb")), mServiceData);
//start advertising
mBTAdvertiser.startAdvertising(
builderSetting.build(),
builderData.build(), mAdvCallback);
Since i can't comment yet ill try to make it an answer.
In your example i only see the Advertising enabled. However to offer GATT services, you also need to create a GATT-server which handles the requests.
Check out the documentation to BluetoothManager.openGattServer(...).
Good luck!
I am developing a google glass/android application. It is a video streaming application that has a server/client setup where the phone/glasses is the server and hooks the pc up with the session description for playing the video. It works great on the android and everything runs fine but as soon as I try to test it on the google glass it throws an error at this line
sSocket = new ServerSocket(sPort);
The exception message says "EADDRINUSE" which I'm assuming means the port is already opened but I never opened it. Even if I had opened it and my program didn't close it I changed the port a couple of times and it still says it's in use.
Thanks
Tyler,
Google Glass, like android, consistently will have many of it's ports occupied by applications running in the background. When creating a socket for your server to listen on, you have two choices:
1) Have a predetermined list of ports you can choose to have your server listen on.
If you choose to do this, then you can simply have a datastructure (list, queue, heap [if you have some priority of which ports you would like to use], etc) which contain all of your ports, then you can simply traverse them until you find an open port.
This can be achieved in the following manner:
private ServerSocket allocatePort(List<Integer> myArray) throws IOException {
for (int individualPort : myArray) {
try {
return new ServerSocket(individualPort);
} catch (IOException io) {
continue; // An exception will be thrown if this port is currently in use. It's OK, let's try another port.
}
}
// When no ports are available, let's throw an exception stating we were unable to find an open port.
throw new IOException("we were unable to find an open port");
}
Then simply invoke this method within your as follows:
int[] arrayOfPorts = {5000, 5001, 5002, 8000, 8001, 8002, 8003};
List<Integer> myArray = new ArrayList<>();
myArray = IntStream.of(arrayOfPorts).boxed().collect(Collectors.toList());
ServerSocket sSocket = allocatePort(myArray);
2) If you don't mind which port to listen in on, you can use the constructor to pick any available port.
This can be achieved as follows:
ServerSocket sSocket = new ServerSocket(0);
You can read up more on ServerSocket's Javadocs. Notice under the parameter's subsection:
port - the port number, or 0 to use a port number that is automatically allocated.
Please let me know if you have any questions!
I am working on an application that uses BluetoothChat sample application.
In my main activity I am using a webview in which I load an external page. I am handling Bluetooth functionality via a javascript that loads with the external page. Basically I add a bridge between Javascript and native code via the following line:
myWebView.addJavascriptInterface(new WebAppInterface(this,myWebView), "Android");//I pass a refference to the context and a refference to the webview.
WebAppInterface is the class that has all the public methods I can call from Javascript. In this class I have methods like: enableBluetooth, disableBluetooth, listBoundedDevices, connect etc.
I am using BluetoothSerialService class from BluetoothChat sample application. My device has to connect to an embedded device which receives commands and answers back differently depending on the input I give. An example would be like: when I press a button on the webview I call the following native code:
while(true){
out.write(requestKey);//send command - where "out" is the OutputStream
key = in.read();//get response - where "in" is the InputStream
if(key==KEY1){
out.write(activateRFID);//send command - activateRFID
rfidTag = in.read();//get response - RFID Tag
updateUI(rfidTag);//perform function - update the UI with the tag
}
else if(key==KEY2){
out.write(deactivateRFID);//send command - deactivate RFID
response = in.read();//get response
}
else if(key==KEY3){
out.write(anotherCommand);//send command -
response = in.read();//get response
}
}
What I am trying to achieve is sending commands to another device(request the pressed key) and perform functions. This has to happen always (pooling the device for the key pressed and perform a particular function).
How can I start 1 SINGLE THREAD that pools the device (write to the OutputStream and read the response from the InputStream)? The BluetoothChat sample application works a little different: whenever I call BluetoothChatSevice.write() I get a response via ConnectedThread run method that sends messages to UI via a mHandler.
All suggestions are welcome.
I did it today. I suggest that you do a boolean function readWrite() that whenever you write to outputStream you also read from the inputStream and send the readBuffer to UI with mHandler. If both read and write are ok, than return true, if one of them went wrong than return false and use resetConection before closing your ConnectedThread. See my answer here for the resetConnection. Application using bluetooth SPP profile not working after update from Android 4.2 to Android 4.3
But the answer about pooling is the following:
In the ConnectedThread run() method do a while(true), call a method similar to readWrite(byte[] data) inside the loop, where in the first place you write something to the device, and then you read the data from the input stream (from the device). In this readWrite() method, if writing to outpustream went fine, then continue to read from the inputstream. if you got any data to the input stream, send the data to UI for processing with the mHandler (or do some processing before sending to the UI).
It worked very nice for me.
I'm trying to connect a USB-Device ( build by myself ) to communicate with my development board ( ODROID-X )
Unfortunately, the examples are very little, as far as the asynchronous communication. I'd some problems with the interrupt driven data exchange - how to build the connection by using the asynchronous interrupt mode?
In one direction, the transmission was possible ... but in both it doesn't work. Is there an example like this:
send a ByteBuffer with endpoint_OUT
get a message from device on endpoint_IN
both in interrupt mode.
Thanks a lot for your support.
Hardy
Perhaps I am misunderstanding the question here.
The sample missile lanucher app that is part of the API package from level 12 onwards uses the queue() and requestWait() methods to handle interrupt type endpoints.
Requests are either In or Out and depend on the direction of the EndPoint.
The code for a pretty noddy request->reply looks something like this. You would want to structure real code differently but this gives you the gist of what needs to happen (I hope)
public void run() {
int bufferMaxLength=mEndpointOut.getMaxPacketSize();
ByteBuffer buffer = ByteBuffer.allocate(bufferMaxLength);
UsbRequest request = new UsbRequest(); // create an URB
request.initialize(mConnection, mEndpointOut);
buffer.put(/* your payload here */;
// queue the outbound request
boolean retval = request.queue(buffer, 1);
if (mConnection.requestWait() == request) {
// wait for confirmation (request was sent)
UsbRequest inRequest = new UsbRequest();
// URB for the incoming data
inRequest.initialize(mConnection, mEndpointIn);
// the direction is dictated by this initialisation to the incoming endpoint.
if(inRequest.queue(buffer, bufferMaxLength) == true){
mConnection.requestWait();
// wait for this request to be completed
// at this point buffer contains the data received
}
}
}
If you are actually looking for a way to run this IO in an asynchronous manner without binding a thread to it, then I think you need to consider using the DeviceConnection.getFilehandle() method to return a standard file handle which in theory you can then use as if it were any other file type resource. I would note however that I have not tried this.
If neither of these addresses the issue please revise the question to clarify what you are struggling to find examples of.
I hope this helps.
I need to know UUID on API 8 (2.2) or possibly 2.3.3.
As I understand the documentation, this should be allowed:
phoneDevice = blueAdapter.getRemoteDevice(phoneAddress);
ParcelUuid[] phoneUuids = phoneDevice.getUuids(); // Won't compile
Eclipse gives me:
"The method getUuids() is undefined for the type BluetoothDevice."
But see:
http://developer.android.com/reference/android/bluetooth/BluetoothDevice.html#getUuids()
Also, I would like to know how the UUIDs are "parceled" inside the ParcelUuid[]. In case I ever manage to get there, how do I retrieve a UUID from a parcelUuid[]? Documentation for Android bluetooth seems to be very poor, in my opinion.
What a joke!
Now I try to get it from the intent, but this too gives: *"EXTRA_UUID cannot be resolved or is not a field"*:
intent.getParcelableExtra(BluetoothDevice.EXTRA_UUID);
You have to use reflection to use the getUuids() and fetchUuidsWithSdp() on android version < 3. So, try the code:
Method method = phoneDevice.getClass().getMethod("getUuids", null);
ParcelUuid[] phoneUuids = (ParcelUuid[]) method.invoke(phoneDevice, null);
//this will support from API level 15 and above.
Broadcast Action: This intent is used to broadcast the UUID wrapped as a ParcelUuid of the remote device after it has been fetched. This intent is sent only when the UUIDs of the remote device are requested to be fetched using Service Discovery Protocol
Always contains the extra field EXTRA_DEVICE
Always contains the extra field EXTRA_UUID
Requires BLUETOOTH to receive.
Constant Value: "android.bluetooth.device.action.UUID"
//no way to degrade its hardware related. there is no supporting jar also. http://developer.android.com/sdk/compatibility-library.html
Unfortunately, I don't think there is any good way to get the UUID's supported by a BluetoothDevice with API level < 15. I guess that's why they added the new functions in API 15.
Note, from the docs for BluetoothClass
BluetoothClass is useful as a hint to roughly describe a device (for
example to show an icon in the UI), but does not reliably describe
which Bluetooth profiles or services are actually supported by a
device. Accurate service discovery is done through SDP requests, which
are automatically performed when creating an RFCOMM socket with
createRfcommSocketToServiceRecord(UUID) and
listenUsingRfcommWithServiceRecord(String, UUID).
So, perhaps the device class could be used as a hint as to what services will be available until you perform one of the listed functions. Certainly it doesn't hurt to check the class since this won't require any additional bluetooth operations.
Note that the service class is also available (it is part of the device class) but this is just a general class, not a listing of specific services (like from SDP).
try BluetoothAdapter class
any question, read: http://developer.android.com/reference/android/bluetooth/BluetoothAdapter.html
In case you can not get UUID from getUuids() method. Please try the other way.
After scanned successfully, you should receive byte[] (scanRecord), so from this result, if you can recognize UUID format you can split step by step to get correct UUID as these codes.
P/s : Important thing, you should know UUID format to get from index correctly.
// Put item into hash map
// UUID from index 10 to 24 : 12233445566778899aabbccddeeff0
StringBuilder mSbUUID = new StringBuilder();
for (int i = 0; i < scanRecord.length; i++) {
// UUID
if (i >= 10 & i <= 24) {
if (Integer.toHexString(
scanRecord[i]).contains("ffffff")) {
mSbUUID.append(Integer.toHexString(scanRecord[i]).replace("ffffff", "") + "-");
} else {
mSbUUID.append(Integer.toHexString(scanRecord[i]) + "-");
}
}
}