SocketTimeoutException after converting from http to https in android app - android

I am getting some problems after trying to convert my android app to use SSL to transport information between my android app and web server. (SocketTimeOutException)
I have bought a Positive SSL certificate from a Certificate Authority (CA) and configured my server to work with it correctly. I have tested it in my web browser and its working correctly.
Now I am trying to modify my android app to use https instead of http but as this is the first time I have used https myself, I am a little confused as to what steps I need to implement in the java code.
Currently I am working on my settings page where I configure my app to use the correct url. For example I have 2 text fields on an activity where I enter the website url (http://www.mydomain.com) and the application folder that the relevant pages are stored in (myappfolder)
I then use the following code to connect and test that the connection variables are configured correctly where validateurl.aspx is a webpage that returns a JSON string if the page exists:
protected boolean validateConnectionSettings() {
String result = "";
boolean validated = false;
try {
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(tvWebsiteURLValue.getText() + File.separator + tvApplicationMiddlewareValue.getText() + File.separator + "validateurl.aspx");
URL url = new URL(urlBuilder.toString());
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
url = uri.toURL();
URLConnection urlConn = url.openConnection();
BufferedReader in = new BufferedReader( new InputStreamReader(urlConn.getInputStream()));
String inputLine;
while((inputLine = in.readLine()) != null){
result += inputLine;
}
in.close();
if(result.equals("exists")) {
validated = true;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
return validated;
}
Now when I try converting the (http://www.mydomain.com) variable to use https I get the above mentioned java.net.SocketTimeoutException.
I have googled this issue and seen that I should be implementing HttpsURLConnection instead of URLConnection in the above code so I have modified my code accordingly to the following:
protected boolean validateConnectionSettings() {
String result = "";
boolean validated = false;
try {
StringBuilder urlBuilder = new StringBuilder();
urlBuilder.append(tvWebsiteURLValue.getText() + File.separator + tvApplicationMiddlewareValue.getText() + File.separator + "validateurl.aspx");
URL url = new URL(urlBuilder.toString());
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
url = uri.toURL();
// URLConnection urlConn = url.openConnection();
HttpsURLConnection urlConn = (HttpsURLConnection)url.openConnection();
BufferedReader in = new BufferedReader( new InputStreamReader(urlConn.getInputStream()));
String inputLine;
while((inputLine = in.readLine()) != null){
result += inputLine;
}
in.close();
if(result.equals("exists")) {
validated = true;
}
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
} catch (Exception e) {
e.printStackTrace();
Log.e(TAG, e.getMessage());
}
return validated;
}
However I still recieve the java.net.SocketTimeoutException. Any Ideas what Im doing wrong?

Ok i found the issue that was causing the SocketTimeOutException.
It seems that the problem was that I am working from my home and the phone is using the same network that the server is located on. It cannot seem to get to the server using https when this is the case. I turned the phones wireless network off and connected using the phones 3G connnection and hey presto the app connected and validated my URL.
I had similar problems with testing the https connection directly from the server and my work laptop in a web browser. In each case I fixed the issue by adding the www.mydomain.com address into the host file.
I'm now going to look into editing my android phones host file to see if this will solve it as I dont want to use the phones G3 connection for testing as I expect ill get lots of charges...
Ill post a comment below later to say how it goes
I hope this helps anyone else that has similar problems

Related

Android to Django - always showing 401

I am trying to connect to my Django backend server from my app. While in local/dev with http connection the android app is getting connected to the server, it is rreturning HTT 401 error for all API calls via the app (except the login call). However, funny thing is using Postman, I'm being able to reach the prod server.
Following is one of the code snippets (android):
try{
URL targetUrl = new URL(targetURL);
httpConnection = (HttpURLConnection) targetUrl.openConnection();
httpConnection.setRequestMethod("GET");
httpConnection.setRequestProperty("Authorization", "jwt " + mToken);
httpConnection.setConnectTimeout(10000); //10secs
httpConnection.connect();
Log.i(TAG, "response code:" + httpConnection.getResponseCode());
if (httpConnection.getResponseCode() != 200){
Log.e(TAG, "Failed : HTTP error code : " + httpConnection.getResponseCode());
return Constants.Status.ERR_INVALID;
}
//Received Response
InputStream is = httpConnection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
while((line = rd.readLine()) != null) {
response.append(line);
//response.append('\r');
}
rd.close();
Log.i(TAG, response.toString());
// Save the tenant details
return parseTenantInfo(response.toString());
}catch (MalformedURLException e) {
e.printStackTrace();
return Constants.Status.ERR_NETWORK;
} catch (SocketTimeoutException e) {
e.printStackTrace();
return Constants.Status.ERR_NETWORK;
}
catch (IOException e) {
e.printStackTrace();
return Constants.Status.ERR_UNKNOWN;
}finally {
if(httpConnection != null) {
httpConnection.disconnect();
}
}
Following is the target url:
private static final String targetURL = Constants.SERVER_ADDR + APIs.tenant_get;
Here, SERVER_ADDR is https://www.example.com/ and tenant_get is apitogettenantinfo/
I am always getting 401 error. Kindly help me out!!! Thanks.
The most irritating thing is Postman works, android login works. So it is seemingly no issue with server (else how would postman work?). And I can't understand what the android issue is.
EDIT:
Following is the screenshot of my postman. A few things are blacked out for security & privacy:
http://imageshack.com/a/img923/231/wUrOuS.png
401 indicates unauthorised request, make sure you are sending correct token.
Also remove httpConnection.connect();

API call far faster on iOs and browser than on android

I have a trouble with my HttpsConnection on android.
First of all, no it is not a duplicate. I try almost all the solutions on SO, like changing the keep-alive option or the timeout ( and some of them indeed optimized a part of my code a little bit ) but it is still 5 to 10 times ( probably more ) slower on android than on iOS.
Sending a request to my server takes several seconds on android while it's almost instant on iOS and from a browser. I am sure that the server is not in cause. But it seems that getting the inputstream is terribly slow!
This line:
in=conn.getInputStream();
is the most delaying one, taking several seconds by itself.
My aim is to get a JSON from my server. My code is supposed to be technically as optimized as possible ( and it can probably help some people with HttpsConnection on the same time ):
protected String getContentUrl(String apiURL)
{
StringBuilder builder = new StringBuilder();
String line=null;
String result="";
HttpsURLConnection conn= null;
InputStream in= null;
try {
URL url;
// get URL content
url = new URL(apiURL);
System.setProperty("http.keepAlive", "false");
trustAllHosts();
conn = (HttpsURLConnection) url.openConnection();
conn.setHostnameVerifier(DO_NOT_VERIFY);
conn.setRequestMethod("GET");
conn.setRequestProperty(MainActivity.API_TOKEN, MainActivity.ENCRYPTED_TOKEN);
conn.setRequestProperty("Connection", "close");
conn.setConnectTimeout(1000);
in=conn.getInputStream();
// open the stream and put it into BufferedReader
BufferedReader br = new BufferedReader(new InputStreamReader(in));
while ((line=br.readLine())!= null) {
builder.append(line);
}
result=builder.toString();
//System.out.print(result);
br.close();
} catch (MalformedURLException e) {
result=null;
} catch (IOException e) {
result=null;
} catch (Exception e) {
result=null;
}
finally {
try {
in.close();
}catch(Exception e){}
try {
conn.disconnect();
}catch(Exception e){}
return result;
}
}
However, it keeps taking several seconds.
So I would like to know: is there a way to improve the speed of this API call? The problem is not the server or the JSON parsing but for sure the function above. Thanks a lot.

How to accept Self Signed Certificates on Android

After a couple of days of fruitless searching and trying various suggestions and examples im still struggling with this.
The situation is we are developing an Android app against a DEVELOPMENT system (ie not open to use outside IT). It has a self signed certificate. The live system will have a "proper" certificate so I dont really want to be disabling the certificate check just to develop it.
The error I am receiving is a 401 Authorization error. I have tried the request with the Authorization credentials through fiddler and the REST service is chugging away nicely.
The certificate is in the Trusted credentials store on the device under user.
Here is the code that makes the connection.
try {
StringBuilder pathName = new StringBuilder();
StringBuilder data = new StringBuilder();
pathName.append(getApiCall()+ path);
URL url = new URL(pathName.toString());
HttpsURLConnection urlConnection = (HttpsURLConnection) url.openConnection(Proxy.NO_PROXY);
urlConnection.setRequestProperty("Autorization", getCredentials());
urlConnection.setDoInput(true);
urlConnection.setRequestMethod("GET");
urlConnection.setRequestProperty("Content-Type", "application/json");
try
{
InputStream in = urlConnection.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(in));
while ( r.readLine() != null)
{
String dataLine = r.readLine();
data.append(dataLine);
}
}
catch (Exception ex2)
{
int freda = urlConnection.getResponseCode();
String fred = urlConnection.getResponseMessage();
data.append("ERROR");
}
finally
{
urlConnection.disconnect();
}
return data.toString();
}
catch (Exception e)
{
return "ERROR";
}
If anyone could point me in the right direction I would be extremely grateful.
Thanks
Steve

Asterisk Manager Interface from Android Device

I have set up the Asterisk Server properly for allowing GUI interface, to check this I have tried & tested an already available Application for Android & tested the same with my browser.
I am able to login & view the files.
eg.
http://192.168.8.x:8088/asterisk/rawman?action=getconfig&filename=users.conf
this commands shows me the user.conf file.
However the same commands does not works from my Android Application. It results in
Response: Error
Message: Permission denied
my code:
1st button click:
try{
new mygoogleSearch().execute(http://192.168.8.x:8088/asterisk/rawman?action=login&username=tismo&secret=tismo123);
}
catch(Exception e) {
Log.v("Exception google search","Exception:"+e.getMessage());
}
this returns:
03-27 17:27:09.468: E/GoogleSearch(21686): Response: SuccessMessage: Authentication accepted
On 2nd Button click:
try{
new Execute().execute("http://192.168.8.4:8088/asterisk/rawman?action=getconfig&filename=test.conf");
} catch(Exception e) {
Log.v("Exception google search","Exception:"+e.getMessage());
}
class mygoogleSearch extends AsyncTask {
protected String doInBackground(String... searchKey) {
;
String cmd = searchKey[0];
try {
return action(cmd);
} catch(Exception e) {
Log.v("Exception ",
"Exception:"+e.getMessage());
return "";
}
}
private String action(String uRL)
throws MalformedURLException, IOException {
String newFeed= uRL;
StringBuilder response = new StringBuilder();
URL url = new URL(newFeed);
HttpURLConnection httpconn = (HttpURLConnection) url.openConnection();
httpconn.setUseCaches(false);
//httpconn.setRequestProperty("Cache", "false");
if(httpconn.getResponseCode()==HttpURLConnection.HTTP_OK) {
BufferedReader input = new BufferedReader(
new InputStreamReader(httpconn.getInputStream()),
8192);
String strLine = null;
while ((strLine = input.readLine()) != null) {
response.append(strLine);
}
input.close();
}
return response.toString();
}
this returns:
03-27 17:28:31.808: E/GoogleSearch(21800): Response: ErrorMessage: Permission denied
You need a CookieManager to connect to the same session.
Quote from the asteriskbook "the definitive Guide"
"The LOGIN command authenticates credentials for the Manager interface’s HTML view.
Once you are logged in, Asterisk stores a cookie on your browser (valid for the length of the httptimeout setting). This cookie is used to connect to the same session."
Update: Examples of a CookieManager Storage to mimic the Browser:
How to use Cookies with HttpUrlConnection, persist Cookies using HttpUrlConnection

Android: Quick web requests

For my application I need to have the latest data from an webpage that is hosted on a server on my local network.
So I request the latest page with a HTTP GET and when the data is received, I send another request.
With my current implementation I reach around the 100 - 120 ms per request. Is there a possibility to make this quicker because it's the same url that is requested.
For example keep the connection open to the page and grep the latest data without setting up a new connection?
This page is around the 900-1100 bytes.
HTTP get code:
public static String makeHttpGetRequest(String stringUrl) {
try {
URL url = new URL(stringUrl);
HttpURLConnection con = (HttpURLConnection) url.openConnection();
con.setReadTimeout(300);
con.setConnectTimeout(300);
con.setDoOutput(false);
con.setDoInput(true);
con.setChunkedStreamingMode(0);
con.setRequestMethod("GET");
return readStream(con.getInputStream());
} catch (IOException e) {
Log.e(TAG, "IOException when setting up connection: " + e.getMessage());
}
return null;
}
Reading inputstream
private static String readStream(InputStream in) {
BufferedReader reader = null;
StringBuilder total = new StringBuilder();
try {
String line = "";
reader = new BufferedReader(new InputStreamReader(in));
while ((line = reader.readLine()) != null) {
total.append(line);
}
} catch (IOException e) {
Log.e(TAG, "IOException when reading InputStream: " + e.getMessage());
} finally {
if (reader != null) {
try {
reader.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
return total.toString();
}
As I know there isn't an implementation like you are asking for. I've been dealing a lot with http requests and the best thing you can do is your code. There is another thing which need some attention...your connection maybe slow and depending on that connection time can be more or in some cases which I've been dealing a lot the connection's timeout isn't enough big, but that's server problem.
In my opinion you should use what you have now.

Categories

Resources