I'm writing an Eddystone-url BLE advertiser for android. However I have problems with encoding the url correctly. According to the specifications (https://github.com/google/eddystone/tree/master/eddystone-url), the scheme prefix (e.g. http://www.) can be set with a single byte (e.g. 0x00). The same is supposed to happen at the expansion (e.g. .com/ = 0x00). There is a whole list for different prefixes and expansions.
While the prefix is working, the expansion behaves strangely.
If I enter:
url = "http://www.orf.at/"
a BLE scanner retrieves exactly this url.
If I enter:
url = "http://www.orf.at"
without the "/" at the end, the BLE scanner tells me that a ".com" is added like:
"http://www.orf.at.com"
If I enter:
url = "http://www.orf.at/test"
The retrieved url looks like the original again.
How do I use the expansion encoding? Or how can I disable it? It seems to be very unreliable.
My according code:
private AdvertiseData buildEddystoneURLData(String url) throws UnsupportedEncodingException {
ByteArrayOutputStream os = new ByteArrayOutputStream();
//frame type
os.write((byte) 0x10);
//TX Power
os.write((byte) 0xB5);
//URL scheme code
/*
0 0x00 http://www.
1 0x01 https://www.
2 0x02 http://
3 0x03 https://
*/
if(url.startsWith("http://www.")){
os.write((byte) 0x00);
url = url.substring(11,url.length());
log("starts with http://www.");
log("cutting to: "+url);
}else if(url.startsWith("https://www.")){
os.write((byte) 0x01);
url = url.substring(12,url.length());
log("starts with https://www.");
log("cutting to: "+url);
}
else if(url.startsWith("http://")){
os.write((byte) 0x02);
url = url.substring(7,url.length());
log("starts with http://");
log("cutting to: "+url);
}
else if(url.startsWith("https://")){
os.write((byte) 0x03);
url = url.substring(8,url.length());
log("starts with https://");
log("cutting to: "+url);
}
byte [] advertiseBytes = string2byte(url);
//0-17: url
for (Byte bt: advertiseBytes) {
os.write(bt);
}
byte[] serviceData = os.toByteArray();
ParcelUuid SERVICE_UUID = ParcelUuid.fromString("0000FEAA-0000-1000-8000-00805F9B34FB");
AdvertiseData.Builder builder = new AdvertiseData.Builder();
if(serviceData!=null) {
builder.addServiceData(SERVICE_UUID, serviceData)
.addServiceUuid(SERVICE_UUID)
.setIncludeTxPowerLevel(false)
.setIncludeDeviceName(false); //don't include device name - it does not work
return builder.build();
}
else
return null;
}
Update string2byte:
private byte[] string2byte(String st) throws UnsupportedEncodingException {
return st.getBytes("UTF-8");
}
And printing the bytes in logcat shows this: for "http://www.orf.at/":
starts with http://www.
cutting to: orf.at/
getServiceData at: 0000feaa-0000-1000-8000-00805f9b34fb
byte: 16
byte: -75
byte: 0
byte: 111
byte: 114
byte: 102
byte: 46
byte: 97
byte: 116
byte: 47
getServiceData as String: ���orf.at/
And this for: "http://www.orf.at":
starts with http://www.
cutting to: orf.at
getServiceData at: 0000feaa-0000-1000-8000-00805f9b34fb
byte: 16
byte: -75
byte: 0
byte: 111
byte: 114
byte: 102
byte: 46
byte: 97
byte: 116
getServiceData as String: ���orf.at
You cannot disable expansion -- it is part of the spec. Receivers will expand any bytes that match expansion patterns. So you need to ensure that any bytes transmitted do not inadvertently contain expansion bytes.
I suspect there is a bug in the string2byte
function which is adding an extra 0 byte at the end of "http://www.orf.at" when converting it to bytes. This would cause the symptoms you see.
If you post the definition of this function and a logged output of the actual bytes put into the output stream, this may help diagnose the problem.
EDIT: Alternatively, it is possible that the BLE Scanner app you are using to decode the transmission is not decompressing properly. If you have an Android device, you might try my Locate Beacon app: https://play.google.com/store/apps/details?id=com.radiusnetworks.locate&hl=en