I am writing an Android application that connects to a cpanel server page (Apache 2.2.22) that is password protected. When the authentication details are correct, I have no connection problems. However, when the credentials are incorrect, my Android app seems to freeze in the HttpURLConnection.getResponseCode() method. Logs on the server show hundreds of requests sent from my Android device, all return 401 as expected, but for some reason this is not reflected in my application.
Here is my code executed from AsyncTask:
@Override protected Integer doInBackground(String... bookInfoString) { // Stop if cancelled if(isCancelled()){ return null; } Log.i(getClass().getName(), "SendToDatabase.doInBackground()"); String apiUrlString = getResources().getString(R.string.url_vages_library); try{ NetworkConnection connection = new NetworkConnection(apiUrlString); connection.appendPostData(bookInfoString[0]); int responseCode = connection.getResponseCode(); Log.d(getClass().getName(), "responseCode: " + responseCode); return responseCode; } catch(IOException e) { return null; } }
This code uses my own NetworkConnection class, which is just the base wrapper class around HttpURLConnection, to avoid code repeating. Here he is:
public class NetworkConnection { private String url; private HttpURLConnection connection; public NetworkConnection(String urlString) throws IOException{ Log.i(getClass().getName(), "Building NetworkConnection for the URL \"" + urlString + "\""); url = urlString; // Build Connection. try{ URL url = new URL(urlString); connection = (HttpURLConnection) url.openConnection(); connection.setRequestMethod("GET"); connection.setReadTimeout(1000 /* 1 seconds */); connection.setConnectTimeout(1000 /* 1 seconds */); } catch (MalformedURLException e) { // Impossible: The only two URLs used in the app are taken from string resources. e.printStackTrace(); } catch (ProtocolException e) { // Impossible: "GET" is a perfectly valid request method. e.printStackTrace(); } } public void appendPostData(String postData) { try{ Log.d(getClass().getName(), "appendPostData() called.\n" + postData); Log.d(getClass().getName(), "connection.getConnectTimeout(): " + connection.getConnectTimeout()); Log.d(getClass().getName(), "connection.getReadTimeout(): " + connection.getReadTimeout()); // Modify connection settings. connection.setRequestMethod("POST"); connection.setDoOutput(true); connection.setRequestProperty("Content-Type", "application/json"); // Get OutputStream and attach POST data. OutputStreamWriter writer = new OutputStreamWriter(connection.getOutputStream(), "UTF-8"); writer.write(postData); if(writer != null){ writer.flush(); writer.close(); } } catch (SocketTimeoutException e) { Log.w(getClass().getName(), "Connection timed out."); } catch (ProtocolException e) { // Impossible: "POST" is a perfectly valid request method. e.printStackTrace(); } catch (UnsupportedEncodingException e) { // Impossible: "UTF-8" is a perfectly valid encoding. e.printStackTrace(); } catch (IOException e) { // Pretty sure this is impossible but not 100%. e.printStackTrace(); } } public int getResponseCode() throws IOException{ Log.i(getClass().getName(), "getResponseCode()"); int responseCode = connection.getResponseCode(); Log.i(getClass().getName(), "responseCode: " + responseCode); return responseCode; } public void disconnect(){ Log.i(getClass().getName(), "disconnect()"); connection.disconnect(); } }
And finally, here is some of the logcat logs:
05-03 11:01:16.315: D/vages.library.NetworkConnection(3408): connection.getConnectTimeout(): 1000 05-03 11:01:16.315: D/vages.library.NetworkConnection(3408): connection.getReadTimeout(): 1000 05-03 11:01:16.585: I/vages.library.NetworkConnection(3408): getResponseCode() 05-03 11:04:06.395: I/vages.library.MainActivity$SendToDatabase(3408): SendToDatabase.onPostExecute(null)
You can see that the method seems to just return null after a random time. The longest I expected was exactly 15 minutes. There are also several memory logs (GC_CONCURRENT) from dalikvm between the last two informational logs that I skipped.
I must also say that at the moment I am not using https, although I do not believe that this should cause any problems. I would be very grateful for any feedback on this, be it a complete answer or just a comment telling me that the problem is not , as I'm still not sure if this problem is server-side or client -side.
Thanks a lot, William
EDIT: I forgot to mention this before, I am attaching my authentication credentials with my own java.net.Authenticator :
public class CustomAuthenticator extends Authenticator { Context mContext; public CustomAuthenticator(Context context){ super(); mContext = context; } @Override protected PasswordAuthentication getPasswordAuthentication() { SharedPreferences sharedPreferences = PreferenceManager.getDefaultSharedPreferences(mContext); String username = sharedPreferences.getString(SettingsActivity.KEY_USERNAME_PREFERENCE, null); String password = sharedPreferences.getString(SettingsActivity.KEY_PASSWORD_PREFERENCE, null); return new PasswordAuthentication(username, password.toCharArray()); } }
which I set in the onCreate() method of activity:
Authenticator.setDefault(new CustomAuthenticator(mContext));
In addition, I used curl to request a password protected resource, and got 401 as expected. I now assume that the problem is with the client side.