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
Related
I use gRPC from Google for work with server, but after some time I notices that streams are allocated on server and only when I close my app they closes.
GatewayGrpc.GatewayBlockingStub stub = getGatewayBlockingStub();
Gw.GetRequest request = new Gw.GetRequest();
request.authToken = authToken;
request.requestId = requestId;
Gw.GetResponse response = stub.get(request);
How to release this connections?
If by "hundreds of streams" you meant "hundreds of connections," then you probably aren't shutting down the ManagedChannel. getGatewayBlockingStub() is probably internally creating a ManagedChannel. You need to call ManagedChannel.shutdown().
Normally Channels are to be reused. Channels lazily initialize any TCP connections and don't reconnect unless there are new RPCs.
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.
My university has an open wifi access point, however it requires you to enter your e-mail before it allows you to use the web. My problem is that the Wifi is stupid in that it seems to drop my connection and force me to enter my e-mail again every 10 minutes.
I wanted to create my own app that I can use to automatically do this step for me, but I cannot seem to find any documentation for a nice and easy way to detect if a Wifi access point has a browser login page. Is there a way in Android to get this information, or is it just to see if my connection to something is always redirected to 1.1.1.1?
See the "Handling Network Sign-On" section of the HttpUrlConnection documentation:
Some Wi-Fi networks block Internet access until the user clicks through a sign-on page. Such sign-on pages are typically presented by using HTTP redirects. You can use getURL() to test if your connection has been unexpectedly redirected. This check is not valid until after the response headers have been received, which you can trigger by calling getHeaderFields() or getInputStream().
They have a snippet of sample code there. Whether this will cover your particular WiFi AP, I can't say, but it is worth a shot.
Ping an external IP address (like google.com) to see if it responds.
try {
Runtime runtime = Runtime.getRuntime();
Process proc = runtime.exec("ping -c 1 " + "google.com");
proc.waitFor();
int exitCode = proc.exitValue();
if(exitCode == 0) {
Log.d("Ping", "Ping successful!";
} else {
Log.d("Ping", "Ping unsuccessful.");
}
}
catch (IOException e) {}
catch (InterruptedException e) {}
The only downside is this would also indicate that a web login is required when there is simply no internet connectivity on the WiFi access point.
#CommonsWare I believe this is a better answer than opening a UrlConnection and checking the host, since the host doesn't always change even when displaying the redirect page. For example, I tested on a Belkin router and it leaves whatever you typed in the browser as is, but still displays its own page. urlConnection.getUrl().getHost() returns what it should because of this.
I think #FlyWheel is on the right path, but I would use http://clients1.google.com/generate_204 and if you don't get a 204, you know you are behind a captive portal. You can run this in a loop until you do get a 204 in which case you know you are not behind a captive portal anymore.
#FlyWheel wrote: The only downside is this would also indicate that a web login is required when there is simply no internet connectivity on the WiFi access point.
You can solve this by registering a receiver to android.net.conn.CONNECTIVITY_CHANGE. You can check if Wifi is ON and is connected by looking at the Supplicant State of the connection.
Here is a snippet, but I didn't run it:
WifiManager wm = (WifiManager) context.getSystemService(Context.WIFI_SERVICE);
WifiInfo wifiInfo = wm.getConnectionInfo();
SupplicantState suppState = wifiInfo.getSupplicantState();
if (wm.isWifiEnabled()) {
if (suppState == SupplicantState.COMPLETED){
// TODO - while loop checking generate_204 (FlyWheels code)Using intent service.
}
}
I can't remember if the SupplicantState is COMPLETED or ASSOCIATED, you will have to check that. You should use an IntentService for checking the generate_204 since broadcast receivers have a short lifetime.
I used the following code using google's 204 endpoint.
private boolean networkAvailable() {
ConnectivityManager mManager = (ConnectivityManager) getApplicationContext().getSystemService(Context.CONNECTIVITY_SERVICE);
if(mManager != null) {
NetworkInfo activeNetwork = mManager.getActiveNetworkInfo();
if(activeNetwork== null || !activeNetwork.isConnectedOrConnecting()){
return false;
}
}
OkHttpClient client = new OkHttpClient();
Request request = new Request.Builder()
.url("http://clients1.google.com/generate_204")
.build();
try {
Response response = client.newCall(request).execute();
if(response.code() != 204)
return false; // meaning it either responded with a captive html page or did a redirection to captive portal.
return true;
} catch (IOException e) {
return true;
}
}
Many applications including Google Chrome use http://clients1.google.com/generate_204 to verify that the the connection is not locked under captive portal.
The issue might rather be - today at least - that newer Android versions (5.1+?) keep the 3G/4G connection up and running until the wifi login actually leads to a fully functional wifi connection.
I haven't tried it, but maybe with the enum value CAPTIVE_PORTAL_CHECK of NetworkInfos DetailedState one can try to detect such a mode properly?
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.
}
}
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