How to accept Self Signed Certificates on Android - 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

Related

Issues with http request in Android

I am new to this website, so if i do something wrong please tell me.
I am trying to establish a connection between my node.js server and my android app. For example, I'm trying to connect a page called showWithAuth, where i need to authenticate with digest stategy.
For this purpose i use Authenticator :
Authenticator.setDefault(new Authenticator()
{
#Override
protected PasswordAuthentication getPasswordAuthentication()
{
return new PasswordAuthentication (username, password.toCharArray());
// System.out.println(pa.getUserName() + ":" + new String(pa.getPassword()));
}
});
My real issue is when i try to establish the connection :
try {
URL url = new URL(strURL);
HttpURLConnection connection = (HttpURLConnection) url.openConnection();
in = new BufferedReader(new InputStreamReader(connection
.getInputStream()));
String line;
while ((line = in.readLine()) != null) {
sb.append(line);
}
System.out.println(sb);
/*connection.setInstanceFollowRedirects(false);
int status = connection.getResponseCode();
InputStream is;
if (status >= 400 && status <= 499) {
throw new Exception("Bad authentication status: " + status); //provide a more meaningful exception message
}
else
{*/
//connection.setRequestProperty("User-Agent","Mozilla/5.0 ( compatible ) ");
//connection.setRequestProperty("Accept", "*/*");
/*is = connection.getInputStream();
}
byte[] buffer = new byte[8196];
int readCount;
final StringBuilder builder = new StringBuilder();
while ((readCount = is.read(buffer)) > -1) {
builder.append(new String(buffer, 0, readCount));
}
String response = builder.toString();
System.out.println(response);*/
} catch (java.net.ProtocolException e) {
sb.append("User Or Password is wrong!");
e.printStackTrace();
} catch (Exception e) {
e.printStackTrace();
}
The issue i have is a filenotfoundexception, at this line :.getInputStream()));
The response of the server is a 401 : bad authentication status
I saw some people having the same issue i deal with, but i tried every single solution without getting anything better.
If you could help me to get what i do wrong ! Thank you !
PS: the commented code was also tried.
PS2: sorry for being so long.
Edit: Just to say also that this code is working on Netbeans with Java only, but not in Android Studio
Please try by adding the
<uses-permission android:name="android.permission.INTERNET" />
To your AndroidManifest.xml file, this may solve your problem.

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.

Not able to POST to REST API

Today I'm making my first attempt of sending a POST request with a JSON to save some data, and I'm not being able to do so.
My app works by signing in, and then save, modify and delete data. It's already done in iOS, but since I'm new to Android, I'm not sure how to do it.
Here's my POST function:
public String POST(String targetURL, String urlParameters, String user, String pwd) {
URL url;
String u = targetURL;
HttpURLConnection connection = null;
try {
// Create connection
// u=URLEncoder.encode(u, "UTF-8");
url = new URL(u);
connection = (HttpURLConnection) url.openConnection();
// cambiarlo luego al usuario q esta logeado
String login = user + ":" + pwd;
String encoding = new String(org.apache.commons.codec.binary.Base64.encodeBase64(org.apache.commons.codec.binary.StringUtils.getBytesUtf8(login)));
connection.setRequestMethod("POST");
connection.setRequestProperty("Authorization", "Basic " + encoding);
connection.setRequestProperty("Content-Type", "plain/text");// hace q sirva con el string de json
connection.setRequestProperty("Content-Length", "" + Integer.toString(urlParameters.getBytes().length));
connection.setRequestProperty("Content-Language", "en-US");
connection.setUseCaches(false);
connection.setDoInput(true);
connection.setDoOutput(true);
connection.setReadTimeout(120000);
// Send request
DataOutputStream wr = new DataOutputStream(connection.getOutputStream());
wr.writeBytes(urlParameters);
wr.flush();
wr.close();
// Get Response
InputStream is = connection.getInputStream();
BufferedReader rd = new BufferedReader(new InputStreamReader(is));
String line;
StringBuffer response = new StringBuffer();
this.setResponseCode(connection.getResponseCode());
while ((line = rd.readLine()) != null) {
response.append(line);
response.append('\r');
}
rd.close();
return response.toString();
} catch (Exception e) {
e.printStackTrace();
return null;
} finally {
if (connection != null) {
connection.disconnect();
}
}
}
The method above is executed with Asynctask, and even if I use it to Login using Spring security, it works, and even I can save for internal usage the username, password, and secret token.
I dunno if I need to put the token in a header or something, because I already did that, with no positive results.
I'm supposing that the only permission I need to execute this is the internet one, so in my manifest file I specified that permission.
I'm going crazy with this issue, please help!
Thanks in advance.
EDIT:
Sorry guys, I'm kinda new to this way of asking, and also, not an English native speaker :P
The output I receive after sending the request, is the HTML of the page that handles logging in into the web app... I need like a json response or something like that to make sure the request was saved correctly
Try handling your cookies
CookieManager cookieManager = new CookieManager();
CookieHandler.setDefault(cookieManager);
This should be a singleton.

Android - How can I open a persistent HTTP connection that receives chunked responses?

I'm trying to establish a persistent HTTP connection to an API endpoint that publishes chunked JSON responses as new events occur. I would like to provide a callback that is called each time the server sends a new chunk of data, and keep the connection open indefinitely. As far as I can tell, neither HttpClient nor HttpUrlConnection provide this functionality.
Is there a way to accomplish this without using a TCP socket?
One solution would be to use a delimeter such as \n\n to separate each json event. You could remove blank lines from original json before sending. Calling setChunkedStreamingMode(0) allows you to read content as it comes in (rather than after the entire request has been buffered). Then you can simply go through each line, storing them, until a blank line is reached, then parse the stored lines as JSON.
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setChunkedStreamingMode(0);
conn.connect();
InputStream is = conn.getInputStream();
BufferedReader reader = new BufferedReader(new InputStreamReader(is, "UTF-8"));
StringBuffer sBuffer = new StringBuffer();
String line;
while ((line = reader.readLine()) != null) {
if (line.length() == 0) {
processJsonEvent(sBuffer.toString());
sBuffer.delete(0, sBuffer.length());
} else {
sBuffer.append(line);
sBuffer.append("\n");
}
}
As far as I can tell, Android's HttpURLConnection doesn't support receiving chunks of data across a persistent HTTP connection; it instead waits for the response to fully complete.
Using HttpClient, however, works:
HttpClient httpClient = new DefaultHttpClient();
try {
HttpUriRequest request = new HttpGet(new URI("https://www.yourStreamingUrlHere.com"));
} catch (URISyntaxException e) {
e.printStackTrace();
}
try {
HttpResponse response = httpClient.execute(request);
InputStream responseStream = response.getEntity().getContent();
BufferedReader rd = new BufferedReader(new InputStreamReader(responseStream));
String line;
do {
line = rd.readLine();
// handle new line of data here
} while (!line.isEmpty());
// reaching here means the server closed the connection
} catch (Exception e) {
// connection attempt failed or connection timed out
}

Making large REST requests

I have a REST service I can't alter, with methods for uploading an image, encoded as a Base64 string.
The problem is that the images can go up to sizes of 5-10MB, perhaps more. When I try to construct a Base64 representation of an image of this size on the device, I get an OutOfMemory exception.
I can however encode chunks of bytes at a time (3000 let's say), but this is useless as I would need the whole string to create a HttpGet/HttpPost object:
DefaultHttpClient client = new DefaultHttpClient();
HttpGet httpGet = new HttpGet("www.server.com/longString");
HttpResponse response = client.execute(httpGet);
Is there a way of going around this?
Edit: trying to use Heiko Rupp's suggestions + the android doc, I get an exception ("java.io.FileNotFoundException: http://www.google.com") at the following line: InputStream in = urlConnection.getInputStream();
try {
URL url = new URL("http://www.google.com");
HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();
urlConnection.setDoOutput(true);
urlConnection.setChunkedStreamingMode(0);
OutputStream out = new BufferedOutputStream(urlConnection.getOutputStream());
out.write("/translate".getBytes());
InputStream in = urlConnection.getInputStream();
BufferedReader r = new BufferedReader(new InputStreamReader(in));
StringBuilder total = new StringBuilder();
String line;
while ((line = r.readLine()) != null) {
total.append(line);
}
System.out.println("response:" + total);
} catch (MalformedURLException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
Am I missing something? The GET request that I need to execute looks like this:
"http://myRESTService.com/myMethod?params=LOOONG-String", so the idea was to connect to http://myRESTService.com/myMethod and then output a few characters of the long string at a time. Is this correct?
You should try to use the URLConnection instead of the apache http client, as this does not require you to hold the object to send in memory, but instead you can do something like:
pseudocode!
HttpUrlConnection con = restUrl.getConnection();
while (!done) {
byte[] part = base64encode(partOfImage);
con.write (part);
partOfImage = nextPartOfImage();
}
con.flush();
con.close();
Also in Android after 2.2 Google recommends the URLConnection over the http client. See the description of DefaultHttpClient.
The other thing you may want to look into is the amount of data to be sent. 10 MB + base64 will take quite a while to transfer (even with gzip compression, which the URLConnection transparently enables if the server side accepts it) over a mobile network.
You must read docs for this REST service, no such service will require you to send such long data in GET. Images are always sent as POST. POST data is always at the end of request and allows to be added iteratively.

Categories

Resources