Should I get BluetoothGatt.GATT_SUCCESS also when disconnecting from a device? - android

I am working with custom devices and I am struggling to manage the Bluetooth LE correctly.
My only concern is not getting 0 (BluetoothGatt.GATT_SUCCESS) when I read the status value along with value 2 on newState variable (what means BluetoothProfile.STATE_DISCONNECTED) at method onConnectionStateChange. Instead, I get an 8, what can't be tracked in the BluetoothGatt nor BluetoothProfile classes.
All connection works fine, I read and write values perfectly.
(1) Is this supposed to be like that? Why do I read an eight?
I have seen many status values at my onConnectionStateChange method: 8, 19, 133 etc.
(2) Where can I check this values?
Thanks in advance
EDIT: There are many values in the api.h file, we were looking in the wrong place.
8: 0x08 = GATT CONN TIMEOUT
19: 0x13 = GATT CONN TERMINATE PEER USER
133: 0x85 = GATT_ERROR

The int error codes need to be converted to HEX and mapped to the values in the following file:
https://android.googlesource.com/platform/external/bluetooth/bluedroid/+/android-5.1.1_r13/stack/include/gatt_api.h
In the cases you mentioned:
8 = GATT_INSUF_AUTHORIZATION
19 = GATT_RSP_WRITE
133 = GATT_ERROR

Answer is no.
I wasn't getting BluetoothGatt.GATT_SUCCESS because the connection was closed by the other end. If gatt.disconnect() is executed I read status = BluetoothGatt.GATT_SUCCESS.

Related

NTAG213: Android throws IOException when trying to authenticate with wrong password

I am writing an Android app which is supposed to authenticate with a write protected NTAG213 NFC tag from NXP. Using the proper password everything works fine and I get the PACK in return.
Trying to authenticate with a wrong password, my code does not behave as expected. According to the tag's description I should receive a NAK in this case but instead I get a TagLostException. Or do I get it wrong and everything behaves as expected? How can I then distinguish between a wrong password and an actual TagLostException?
I would be grateful, if anyone was able to tell me what I am doing wrong.
try {
nfcA.connect();
byte[] response = nfcA.transceive(new byte[]{
NTAG213_PWD_AUTH, mTagPassword[0], mTagPassword[1],
mTagPassword[2], mTagPassword[3]
});
// checking if response was a NAK
if (((byte) 0x00 == response[0]) ||
((byte) 0x01 == response[0]) ||
((byte) 0x04 == response[0]) ||
((byte) 0x05 == response[0])) {
nfcA.close();
result.setErrorCode(WRONG_PASSWORD);
return result;
}
}catch (TagLostException e){
result.setErrorCode(TAG_LOST_EXCEPTION);
e.printStackTrace();
return result;
}catch (IOException e){
result.setErrorCode(IO_EXCEPTION);
e.printStackTrace();
return result;
}
You are right that the tag will answer with a NACK response if the authentication command fails. This is just the same as for the case when a tag does not support a command.
Unfortunately, the various Android NFC stack implementations handle a NACK response in different ways. They either return the NACK value in the response byte array, return an empty response (?), or they generate an IOException (typically a TagLostException). Consequently, you cannot reliably distingush between cases where authentication failed, the command was not supported, or the communication with the tag as actually interrupted.
In order to detect if the tag is still there (and thus, it was just the command that failed for whatever reason), you could issue a READ command (or some other command that you would expect to succeed for your specific tag type) afterwards. If that fails as well, you can be certain that communication with the tag was lost.
Note that you need to disconnect (NfcA.close()) and reconnect (NfcA.connect()) the tag after a failed command and before you continue to send other commands. This should be done regardless of whether you received an IOException or an actual NACK response value from the transceive() method. This is usually necessary in order to reset the state of the tag after any command failure.

Can I use socket() on frameworks/native/service on Android?

I want to implement socket function in the Android frameworks/native/service/surfaceFlinger for sending screen information.
So, I made my source code about networking by using socket(), and inserted into the Android framework source tree.
However, it couldn't create socket descriptor.
It always returned -1 and errno is 13
So I added permission code like this:
// framework/frameworks/native/services/surfaceflinger/mynetwork.cpp
if (PermissionCache::checkCallingPermission("android.permission.INTERNET") < 0)
...
fd = socket(AF_INET, SOCK_DGRAM, 0);
But still doesn't work.
Any body know about this issue?
and know soution?
Thank you.

java.net.ProtocolException: unexpected end of stream

I am facing a strange issue, and I am not able to debug it out. I have implemented a logic for uploading stream of data and am using Volley for the same, I have customized a logic little bit in HurlStack, addBodyIfExists api,so that body of type "application/octet-stream" can be handled.
My logic is to post progress to user, so that UI can be updated indicating user progress in upload, below my logic for same.
int toRead = length; // File length
byte[] data = new byte[4096];
connection.setDoOutput(true);
if(length != -1) {
connection.setFixedLengthStreamingMode(length);
} else {
connection.setChunkedStreamingMode(4096);
}
OutputStream os;
int i;
int count;
os = connection.getOutputStream();
int progress= 0;
try {
for(i = 0; (count= is.read(data)) > 0; ++i) { // is, is not null and contains a valid input stream
os.write(data, 0, count); // at this line am getting unexpected end of stream
progress+= count;
if(i % 20 == 0) {
rs.deliverProgress(progress, 0L);
progress= 0;
}
}
os.flush();
} finally {
if(is != null) {
is.close();
}
if(os != null) {
os.close();
}
}
on executing above code am getting this, although I have verified, output stream is not null, neither do input stream, it fails in first iteration of read loop itself, am seeing it has read 4096 bytes and then trying to write the same.
java.net.ProtocolException: unexpected end of stream
at com.android.okhttp.internal.http.HttpConnection$FixedLengthSink.close(HttpConnection.java:326)
at com.android.okio.RealBufferedSink.close(RealBufferedSink.java:174)
at com.android.okio.RealBufferedSink$1.close(RealBufferedSink.java:142)
any help in debugging above will he highly appreciated.
This may help you :
That exception is thrown by FixedLengthInputStream when the expected number of bytes (usually set in the content-length header of the response) is larger than the actual data in the response.
Check that the content-length header is correct. (If you're supplying your own value for the content length, make sure it is correct.)
It would help to see your code that sets up the input stream.
Already Fixed it, please add "Accept-Encoding", "identity" in header, then the server-side will get command that it will not modify the response, then send back to Clients.
If you have checked everywhere in your code and tried every solution in stackoverflow and github but the issue still occurs, and you have only tested your code on emulator, then, you should try to run your code on your real device instead. Maybe it will work, or maybe it won't, but if you feel desperate, just have a try, seriously. I was astonished when I happened to find that my code ran with bugs on emulator everytime but successfully on my mobile phone. Besides, the code also ran sucessfully on others' android emulators. So I guess there is something wrong in my android studio configuration that I can't find out. I have no idea why this happen, just like we don't know why "Clean Project/Invalidate caches" sometimes works better than any solution.
It is a little strange that your data length might be unknown.
Is it a media file? Or a live stream?
Anyway, I tried to upload my live stream data. And it happened in the same error.
I added this setting to the Connection and solved my problem.
Transfer-Encoding : chunked
("setChunkedStreamingMode" didn't work. I still don't know why.)
This happens for me on android emulator and doesn't happen on my physical android device.
I was doing GET request to flask server running on 0.0.0.0 on my laptop from the android app.
To fix it on the emulator, add the servers ip address in the emulators proxy.
see How to set up Android emulator proxy settings
The exact problem i had was unexpected end of stream retrofit

Errno 97 with Android NDK socket programming

I've searched all over google and can't find a solution to this problem:
I'm trying to do some basic socket programming (client/server apps) on my Android device and I'm not having any luck starting the Server app. In my native code, I call bind(...) and I see from the log that it returns -1. When I check errno, the value is 97 (EAFNOSUPPORT), which indicates "Address family not supported by protocol." When I checked the values for sin_family, it was AF_INET, which is IPv4. Is this not supported by the Android NDK? If not, what else could be the cause of this error?
Socket is initialized as:
sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP));
listenAddr is a sockaddr_in struct that's initialized with:
sin_family = AF_INET;
sin_port = htons(9099);
sin_addr.s_addr = INADDR_NONE;
Call to bind:
bindResult = bind(sock, (sockaddr *)listenAddr, sizeof(listenAddr))
Bind result returns -1. Subsequent call to errno returns 97.
Use INADDR_ANY (or a specific interface's address) rather than INADDR_NONE.
INADDR_NONE is an unsigned constant with the same bit pattern as the signed value -1, returned as an indication of error from certain calls.

Android URLConnection class cannot get content lenght using 3G internet connection

I've got the following piece of code:
URL url = new URL("http://myserver.com/getFile.php");
URLConnection conexion = url.openConnection();
conexion.connect();
int lenghtOfFile = conexion.getContentLength();
Everything works fine until I work with WiFi connection. If I try to run this code when there is only GPRS/3G connection available, conexion.getContentLength() returns -1.
Any idea why?
EDIT:
I've check the headers using getHeaderFields(). They are different if I use 3G network. Basically there is no Content-Length in this case. Any idea why server returns different headers? I'm not using any special script to provide the file, I only get the file that is placed at given location.
Entire header for the WiFi case:
{Accept-Ranges=[bytes], Connection=[Keep-Alive], Content-Length=[628254], Content-Type=[text/plain; charset=UTF-8], Date=[Tue, 29 Nov 2011 11:22:50 GMT], ETag=["7a0c7-9961e-4af3f38778500"], Keep-Alive=[timeout=15], Last-Modified=[Fri, 14 Oct 2011 09:52:52 GMT], Server=[Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_python/3.3.1 Python/2.6.6 mod_ssl/2.2.9 OpenSSL/0.9.8o mod_wsgi/3.3 mod_perl/2.0.4 Perl/v5.10.0]}
Entire header for the case when using 3G:
{Accept-Ranges=[bytes], Connection=[Keep-Alive], Content-Type=[text/plain; charset=UTF-8], Date=[Tue, 29 Nov 2011 11:20:33 GMT], ETag=["7a0c7-9961e-4af3f38778500"], Keep-Alive=[timeout=15], Last-Modified=[Fri, 14 Oct 2011 09:52:52 GMT], Server=[Apache/2.2.9 (Debian) PHP/5.2.6-1+lenny9 with Suhosin-Patch mod_python/3.3.1 Python/2.6.6 mod_ssl/2.2.9 OpenSSL/0.9.8o mod_wsgi/3.3 mod_perl/2.0.4 Perl/v5.10.0], Transfer-Encoding=[chunked], Warning=[214 warkaz-fe07 "Transformation applied"]}
Are you sure that the server provides the content length by sending the Content-Length header in the response?
From the headers it's clear that your provider has some kind of proxy in place that does a transformation, stripping the content-length in the process. The warning header clearly indicates this. You could try returning a different type of content type (you are now getting text/plain), maybe this particular proxy won't touch it. It's not a great solution of course, there are a lot things carriers may have to "optimize" their network in some way.
You could also try a HEAD request using a range header to get a ballpark of the content size. In that case you'd guess a few ranges, like 100k, 1000k etc to see if the server thinks that's an acceptable range. You could use that fake range for your progress. Again, this isn't a very good solution but if you really need the progress, it's something to try.
In the end it's best to just show the progress as unknown if there's no length known.
Since you are using
new URL("http://myserver.com/getFile.php");
I suppose you are using a personal server that you have set up, and when using WiFi your phone is in your local network and thereby can see your server, but when you are trying to connect via GPRs/3G you are trying to access your local server from the internet.
It is probably due to a limitation from your carrier. Try to avoid needing this value. (for example, by reading the inputStream until you cannot read it).

Categories

Resources