Search code examples
android-emulatorhttpclientandroidcookiestore

Android HTTP app working on emulator, not properly on my phone(s)


I have been struggling with android for the last few weeks and got myself a first working app... on my emulator only unfortunately. I really hope someone can help me out to get it working on my android device(s). Emulator runs v2.2, my devices 2.3+.

I have a singleton 'websiteservice'-class that's beeing created by a class which extends 'Application'. The websiteservice-class creates 1 threadsafeconnection-manager, and contains a 'CookieStore'. Each HTTPGet/Post creates a new HTTPClient, with the threadsafeconn.manager attached to it. Everytime I do a post or get, I try to attach the cookies if available. The cookies are once - and only - set when logging in to the secured part of the website. Together with EntitityUtils.ToString and Jsoup, I parse each HTML result of my 'secured' website part. On logging on, I create a sqllite table in android, in which I store only 1 simple record, the user that logged on.

When I run this on my emulator, everything runs just as I'd like it to be, but on my device, something seems to go terribly wrong. I attached the debugger to my phone. The logging in seems to go just fine, and the cookies are being set. The sqllite bit probably goes fine too, as I don't seem to get errors. Upon loading the profile-page, I can see that the HTTPGet-action get's the cookies attached of the CookieStore, but the HTML-result/doc I receive, is 95% of the times the login-page.

I say 95%, because I did get to my profile-page once or twice on my rooted Desire HD, but on another Desire HD I didn't, and on my Sensation XE neither. The times I did get the profile-page loaded (a custom listbox with a hashmap as input), I couldn't start any action. They aborted right away, and probably they had the same issue (getting login-page as result).

Are there any permissions I forgot, is there anything I should check, or do you have any idea what it could be? I'm really confused right now.

Small update
I just rebooted my phone. When I start the program, the first time I log on, my profile page gets loaded. My 'detail' action seems to work. This action does not connect to the internet or so, it simply displays information I stored in a class. My other 2 actions (copy and delete) don't work (I probably get the 'login page' as a result). When I turn my screen (orientation changes), the page 'restarts' and it's trying to load the profile page again. The listbox is cleared, and I don't get my profile page (which is a list of adverts) back.

Update 2 - 08-03 My manifest file only contains the internet-permission, apart from the registration of my activities. A small 'weird' extra. It seems my 'back-up' code is nearly equal to my code posted here. Each time it does seem to attach my cookies, but still it doesn't do anything with it :(. Also, I was playing around a bit yesterday with my phone, I changed orentiation a few times (which reloads the activity automatically), and suddenly, I once or twice had my profile in front. I couldn't do any action on it, but my class containing information was accessable and filled. PS. Just now 8.15 AM my time, I again could load my profile after switching orientation 4-5 times.

Update 08-03-2012 I have been puzzling and tried lots of things in the evening, and now I even got my emulator-version back to square 1. Got a backup, so np, but I think I'm not using my http-client properly. I removed all previous code, here's my current code I use for my 'websiteservice', and my 'Webclient' which I instantiate on each get/post, by simply attaching the connectionmanager.

private static WebsiteService instance;

    ThreadSafeClientConnManager manager;
    HttpContext localContext;
    CookieStore cookies;
    public String returnCode = "";
    public HttpPost httpPost = null;
    public HttpGet httpGet = null;

    public static WebsiteService getInstance()
    {
        // Return the instance
        return instance;
    }

    private WebsiteService()
    {
        DefaultHttpClient client = new DefaultHttpClient();
        ClientConnectionManager mgr = client.getConnectionManager();
        HttpParams params = client.getParams();
        manager = new ThreadSafeClientConnManager(params,mgr.getSchemeRegistry());
        localContext = new BasicHttpContext();
        cookies = new BasicCookieStore();
        localContext.setAttribute(ClientContext.COOKIE_STORE, cookies);
    }

    public static void initInstance()
    {
        if (instance == null)
            instance = new WebsiteService();
    }

    public WebsiteClient postPage(String url, List<NameValuePair> nvps)
    {
        return postPage(url, nvps, true);
    }

    public WebsiteClient getPage(String url) {

        WebsiteClient client = new WebsiteClient(manager);
        DefaultHttpClient httpClient = client.httpClient;

        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
        //HttpProtocolParams.setContentCharset(httpClient.getParams(), "CP1250");

        if(cookies != null)
            httpClient.setCookieStore(cookies);

        httpGet = new HttpGet(url);

        try {
            client.response = httpClient.execute(httpGet,localContext);
        } catch (ClientProtocolException e) {
            System.out.println("HTTPService : ClientProtocolException : "+e.getMessage());
            return null;
        } catch (IOException e) {
            System.out.println("HTTPService : IOException : "+e);
            return null;
        }

        //cookies = httpClient.getCookieStore();
        return client;
    }


    public WebsiteClient postPage(String url, List<NameValuePair> nvps, boolean autoRedirect) {

        WebsiteClient client = new WebsiteClient(manager);
        DefaultHttpClient httpClient = client.httpClient;
        httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);

        if(cookies != null)
            httpClient.setCookieStore(cookies);

        if(!autoRedirect)
        {
            HttpParams params = httpClient.getParams();
            HttpClientParams.setRedirecting(params, false);
        }

        httpPost = new HttpPost(url);
        client.response = null;
//
        httpPost.setHeader("User-Agent", "Mozilla/5.0 (X11; U; Linux " +
                "i686; en-US; rv:1.8.1.6) Gecko/20061201 Firefox/2.0.0.6 (Ubuntu-feisty)");
        httpPost.setHeader("Accept", "text/html,application/xml," +
                "application/xhtml+xml,text/html;q=0.9,text/plain;q=0.8,image/png,*/*;q=0.5");
        httpPost.setHeader("Content-Type", "application/x-www-form-urlencoded");

        try {
            if(nvps != null)
                httpPost.setEntity(new UrlEncodedFormEntity(nvps, HTTP.ISO_8859_1));
        } catch (UnsupportedEncodingException e) {
            // TODO Auto-generated catch block
            System.out.println("HTTPHelp : UnsupportedEncodingException : "+e);
        }
        //httpPost.setEntity(tmp);

        try {
            client.response = httpClient.execute(httpPost, localContext);
        } catch (ClientProtocolException e) {
            System.out.println("HTTPService : ClientProtocolException : "+e.getMessage());
            return null;
        } catch (IOException e) {
            System.out.println("HTTPService : IOException : "+e);
            return null;
        } 

        cookies = httpClient.getCookieStore();
        return client;
    }
}

My websiteclient:

public DefaultHttpClient httpClient;
public HttpResponse response = null;

public WebsiteClient(ThreadSafeClientConnManager manager)
{
    DefaultHttpClient client = new DefaultHttpClient();
    HttpParams params = client.getParams();
    httpClient = new DefaultHttpClient(manager, params);
}

I must be doing something wrong with cookies, or should not use the same Httpget/Httppost or so. Hopefully I'll be able to solve this with a clear mind again tomorrow.

Ideas and input is appreciated!


Solution

  • I've been able to solve this very awkward problem I had, and will post the solution below. I unfortunately do not know the exact cause, but it is a combination of things surely.

    Instead of creating a DefaultHttpClient again each time with my connection manager, I have created only 1 DefaultHttpClient, which I reuse all the time. Also, each time I do a post or get, I create a new HTTPGet/HTTPPost, instead of reusing/recreating it from an existing.

    Final constructor for my websiteservice-class:

    private WebsiteService()
    {
        CookieManager.getInstance().setAcceptCookie(true);
        httpclient = new DefaultHttpClient();
        ClientConnectionManager mgr = httpclient.getConnectionManager();
        HttpParams params = httpclient.getParams();
        manager = new ThreadSafeClientConnManager(params,mgr.getSchemeRegistry());
        localContext = new BasicHttpContext();
        cookies = new BasicCookieStore();
        localContext.setAttribute(ClientContext.COOKIE_STORE, cookies);
    }
    

    A simple 'GetPage' call looks like this now:

    httpClient.getParams().setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.BROWSER_COMPATIBILITY);
    
            if(cookies != null)
                httpClient.setCookieStore(cookies);
    
            HttpGet httpGet = new HttpGet(url);
    
            try {
                client.response = httpClient.execute(httpGet,localContext);
            } catch (ClientProtocolException e) {
                System.out.println("HTTPService : ClientProtocolException : "+e.getMessage());
                return null;
            } catch (IOException e) {
                System.out.println("HTTPService : IOException : "+e);
                return null;
            }
    

    I'm not 100% sure, but I think I can even leave out the setCookies bit. The cookies is in my situation a private declared CookieStore, which I fill after a post.

    The last part which was annoying, is that upon rotating, it recreates the activity. To solve this, I extended the class which extends 'Application'. In this class, I put a list of my objects. In my 'OnCreate', I check if the list of objects exists, and use that list if available. Upon logging off, or refreshing, I recreate that list. The trick was just these few lines: (I left out the piece I added in the 'extends Application' class):

        if(((ApplicationInstance)getApplication()).getProfile() == null)
            this.initProfileItems();
        else
        {
            this.ProfileItems =((ApplicationInstance)getApplication()).getProfile(); 
            this.initListView();
        }
    

    ApplicationInstance is my class which extends Application. My 'initList' processes the objects. My initProfileItems does an actual data get :-)

    Hope I saved someone a headache :), and thanks for your time, @androidnoob!