I want to check whether the BluetoothSocket is open for operation or not.....
Here is what I do:
First of all I get an InputStream from my BluetoothSocket, I want to perform some operation with that InputStream, if an IOException occurs my program can determine that socket is disconnected..... And after making sure that socket is connected I want to read some data from it.
For making sure I am calling available() which by default returns 0 or a number of bytes.... if return value is 0 my reading operation throws IOException.
Here are my questions.
Is available() blocking I/O call or an asynchronous one?
Return value >0 only when I give some input from my device while connecting, which will not always be the case. Am I doing any mistake allowing to read if there are 0 available bytes? How to avert this?
First u have to connect with a Bluetooth server. Use connect() to connect, this method will block until a connection is made or the connection fails (resulting in an exception). So make sure to run this on a separate thread.
public void run() {
try {
socket.connect();
InputStream in = socket.getInputStream();
//socket connected, inputStream can be used
//Bluetooth
} catch (IOException e) {
//Socket is refused connection with the server.
}
}
Related
I'm writing an Android bluetooth client application in Kotlin. Now I'm trying to get OutputStream from a connected socket.
When writing in Java, I have to check for IOException:
OutputStream stream;
try
{
stream = socket.getOutputStream();
}
catch(IOException e)
{ ... }
But in Kotlin, it seems that I can directly get the object through getters
val streamOut : OutputStream = socket.outputStream
The question is should I check for IOExecption as well? Or is the outputstream already set in the socket.connect() step?
Java is very strict about exceptions. Whenever you write a code that could throw an exception, you need to either catch it or mark your own method with throws. Kotlin does not require this, you are not enforced to catch exceptions, but that doesn't mean it will auto-magically handle errors for you or something. socket.outputStream may throw an exception, so you need to be prepared for such a situation. If you omit catch {} block, then in the case of an error, it will propagate through the call stack.
I am running a command line argument in my Android application like:
ProcessBuilder pb = new ProcessBuilder(cmds);
Process process = pb.start();
process.waitFor();
Where cmds are a list of arguments to run. My commands probe a remote URL over a http connection. My device is connected to a WiFi network that does not have access to the internet, but does host the URL I want to probe. My device also has a cellular connection that does have access to the internet, but not the URL. My device is running Android 6.0 Marshmallow.
Normally in Lollipop or above, Android defaults to the network with a connection to the internet. To access WiFi networks without internet you need to use NetworkRequest, e.g: https://stackoverflow.com/a/27958106/1847734.
How can I pass an obtained Network to the above Process, so that the connection goes over my WiFi network, not my cellular network?
Do I instead need to use ConnectivityManager#bindProcessToNetwork? How do I join the process to set the network using this method? There doesn't seem to be an option to give the process.
Starting from Lollipop Network is Parcelable so you can write it to a byte array and then read back. Let's start from the writing part.
final Parcel parcel = Parcel.obtain();
try {
// Create a byte array from Network.
parcel.writeParcelable(network, 0);
final byte[] data = parcel.marshall();
// Start a process.
ProcessBuilder pb = new ProcessBuilder(cmds);
Process process = pb.start();
// Send serialized Network to the process.
final DataOutputStream out = new DataOutputStream(process.getOutputStream());
out.write(data.length);
out.write(data);
// Wait until the process terminates.
process.waitFor();
} finally {
parcel.recycle();
}
And the reading part.
// Read data from the input stream.
final DataInputStream in = new DataInputStream(System.in);
final int length = in.readInt();
final byte[] data = new byte[length];
in.readFully(data);
final Parcel parcel = Parcel.obtain();
try {
// Restore Network from a byte array.
parcel.unmarshall(data, 0, data.length);
final Network network = parcel.readParcelable(null);
// Use the Network object to bind the process to it.
connectivityManager.bindProcessToNetwork(network);
} finally {
parcel.recycle();
}
This code will work on Android 6.0 only. If you want it to work on Lollipop you should use ConnectivityManager.setProcessDefaultNetwork(Network) instead of ConnectivityManager.bindProcessToNetwork(Network). And this code is not going to work on devices before Android 5.0.
UPDATE:
For a non-Android process you can create a socket, bind it to the nework with Network.bindSocket(Socket) and pass a socket descriptor to the child process.
If the previous approach doesn't work for you, you can call NDK function android_setsocknetwork from multinetwork.h or even try and do what Android does when you bind a process to a given network. Everything you might be interested in happens in netd client. NetdClient sends a message to fwmarkd here passing a network id. Actual message sending happens here. But I would recommend to use this approach as the last chance way to solve your problem.
I am using HttpUrlConnection for making network calls. I used urlconnection.disconnect() and inputstream.close() for closing connection
try {
HttpURLConnection uc = (HttpURLConnection) getUrlConnection(new URL(mUrl));
uc.setRequestProperty("Content-Type", "application/json");
uc.setDoOutput(true);
uc.setChunkedStreamingMode(0);
OutputStream out = new BufferedOutputStream(uc.getOutputStream());
InputStream in = new BufferedInputStream(uc.getInputStream());
in.close();
} catch (...) {
........
} finally {
if(uc != null)
uc.disconnect();
}
After I run netstat command on server. But still I saw one tcp connection in open state.
Is there any to close HttpUrlConnection
The disconnect() method states:
Releases this connection so that its resources may be either reused or
closed.
Unlike other Java implementations, this will not necessarily close
socket connections that can be reused. You can disable all connection
reuse by setting the http.keepAlive system property to false before
issuing any HTTP requests.
Seems like android always uses different port for opening every new connection. and caches them for some time.
refer this link
I am developing an app, in which I have maintained a infinite socket connection with server. It works pretty well all the time except when device stays in idle mode for longer time say 30 mins or so. After 30 mins if I bring device to wake state, and try to contact to server thro' my app it doesn't throw any exception. Which shows me that my socket connection is in still live state. But when I check at the server end same data is not received here. So I am not able to understand that is there is a known issue on android side or if I am doing anything wrong here. Below is the code piece I am using to setup the socket.
Socket socket = new Socket(url, port);
String request = "some request";
outputStream = socket.getOutputStream();
outputStream.write(request.getBytes());
outputStream.flush();
InputStream is = socket.getInputStream();
while (true) {
StringBuffer sb = new StringBuffer();
int ch = is.read();
while (ch != -1) {
sb.append((char) ch);
ch = is.read();
}
}
You need to send application level keep alives to maintain your socket connection.
Here is an example: http://devtcg.blogspot.com/2009/01/push-services-implementing-persistent.html
Even though it does not directly answer your question but ,I would recommend that you use apache HTTP client api for persistant connection managent.
Here is the link of their tutorial ,specifically connection persistence.
Connection persistance
I'm using the Android development sample project BluetoothChat.
http://developer.android.com/resources/samples/BluetoothChat/index.html
I'm running it on an Archos 43 and trying to communicate with a serial to bluetooth adapter.
To communicate with the adapter I need to use UUID 00001101-0000-1000-8000-00805F9B34FB.
However, when I do that, I get a Null Pointer Exception at this line:
socket = mmServerSocket.accept();
If I use a different UUID I do not have this problem, however I cannot connect to the serial adapter.
If I use a Motorola Droid instead of the Archos 43, I do not have this problem.
From some error messages, I think the Archos is using the bluez stack.
Any ideas why the combination of this UUID and stack would cause an exception when calling the accept() function?
Here's the surrounding code (you can get the whole source from the link above)
public void run() {
if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
setName("AcceptThread");
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "accept() failed", e);
break;
}
Some error messsages from the log:
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): listen() failed
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): java.io.IOException: Not able to register SDP record for BluetoothChat
04-25 21:05:33.278: ERROR/BluetoothChatService(3321): at android.bluetooth.BluetoothAdapter.listenUsingRfcommWithServiceRecord(BluetoothAdapter.java:778)
Did you change the constructor of "class AcceptThread" , where you use this function "listenUsingRfcommWithServiceRecord()" ?
I'm using the same UUID on archos 70 and i dont get any bluetooth connection errors.( Try restarting the archos if its intermittent.) I wanted to add this as comments for some reasons i dont see a comment !
It ends up the problem was solved with a firmware update from Archos.