XMLHttpRequest in Android

2,111 views
Skip to first unread message

David Golightly

unread,
May 4, 2009, 5:17:57 PM5/4/09
to phonegap
Searched this group for answers, but wasn't able to find any, though
perhaps I'm missing something and somebody can point me in the right
direction...

According to my initial testing, XMLHttpRequest works fine in PhoneGap/
iPhone Simulator but fails ("Permission denied") in Android (v1.1)
emulator. Has anybody seen this? The same client code (HTML/JS)
works on iPhone but not Android. For reference, here's what I've
added to the initial reference project under:

Used download link:
http://download.github.com/sintaxi-phonegap-bf1f025ec6e8f6fe0f9b9059451a73af1012d1be.tar.gz

Added to the bottom of index.html:
<script type="text/javascript">
var HTTP = {
get: function (url, file, success, failure) {
var xhr = new XMLHttpRequest();
xhr.open('GET', url, true);
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
success(xhr);
} else {
failure(xhr);
}
}
};
xhr.send(null);
}
};


function success(xhr) {
alert('SUCCESS!\n'+xhr.responseText);
}

function failure(xhr) {
alert('FAILURE');
}

try {
HTTP.get('http://www.gotime.com/api/places', null, success,
failure);
} catch (ex) {
alert('ERROR: '+ex.name+': '+ex.message);
}
</script>

Thanks,
David

David Golightly

unread,
May 4, 2009, 5:30:50 PM5/4/09
to phonegap
PS I saw on http://phonegap.pbworks.com/JavaScript-API that there
should be an "HTTP" object with a "get" method (as I have replicated
in this example), but when I remove my version of HTTP from the
example, I get: "ReferenceError: Can't find variable: HTTP". Am I
missing something in my build?

On May 4, 2:17 pm, David Golightly <davig...@gmail.com> wrote:
> Searched this group for answers, but wasn't able to find any, though
> perhaps I'm missing something and somebody can point me in the right
> direction...
>
> According to my initial testing,XMLHttpRequestworks fine in PhoneGap/
> iPhone Simulator but fails ("Permission denied") inAndroid(v1.1)
> emulator.  Has anybody seen this?  The same client code (HTML/JS)
> works on iPhone but notAndroid.  For reference, here's what I've
> added to the initial reference project under:
>
> Used download link:http://download.github.com/sintaxi-phonegap-bf1f025ec6e8f6fe0f9b90594...

PanMan

unread,
May 4, 2009, 6:15:20 PM5/4/09
to phonegap
I can imagine that the actual android device doesn't allow connections
to remote servers?
I found, strangely enough, that the iPhone doesn't adhere to this when
pages are served from localhost (so pages that are served from
localhost, can reach all sites).
Does this also happen with JSONP requests? Or if you serve the page
from the same host?

PanMan.

On May 4, 11:17 pm, David Golightly <davig...@gmail.com> wrote:
> Searched this group for answers, but wasn't able to find any, though
> perhaps I'm missing something and somebody can point me in the right
> direction...
>
> According to my initial testing, XMLHttpRequest works fine in PhoneGap/
> iPhone Simulator but fails ("Permission denied") in Android (v1.1)
> emulator.  Has anybody seen this?  The same client code (HTML/JS)
> works on iPhone but not Android.  For reference, here's what I've
> added to the initial reference project under:
>
> Used download link:http://download.github.com/sintaxi-phonegap-bf1f025ec6e8f6fe0f9b90594...

David Golightly

unread,
May 4, 2009, 7:35:29 PM5/4/09
to phonegap
JSONP appears to work fine; though it's a lovely format, the backend
I'm working with is already in XML so I'd prefer to use XHR if
possible, though it appears we do have a workaround in JSONP.

-David

PanMan

unread,
May 4, 2009, 8:53:39 PM5/4/09
to phonegap
You could use a simple proxy script that translates the XML to JsonP.
If you can't host this yourself, you could also use Yahoo Pipes for
this (XML 2 Json would be a REALLY simple pipe, as Pipes supports
JsonP natively).
I think this is a bit a gray area: It's not really clear how cross
side scripts should behave when run from files/localhost. Different
browsers handle this different (also on the desktop: Firefox doesn't
allow this, Safari does, which makes debugging more dificult).
Let's hope for more standards here!
PanMan.

Nathan Freitas

unread,
May 4, 2009, 9:29:37 PM5/4/09
to phon...@googlegroups.com
I ended up adding an "ajaxGet" call to PhoneGap.java on Android to handle the HTTP request in Java code:


 public String ajaxGet (String url)
    {
        //ajaxGet
        String resp = "";
       
        try {
            Log.d("ajaxGet", url);
            resp = HttpManager.doGet(url, null);
            Log.d("ajaxGet", resp);
           
            //resp = URLEncoder.encode(resp, "utf-8");
        }
        catch (Exception e)
        {
            e.printStackTrace();
        }
       
        return resp;
    }



/*
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package com.phonegap.demo;

import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;

import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.NameValuePair;
import org.apache.http.client.HttpClient;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.message.BasicNameValuePair;
import org.apache.http.protocol.HTTP;

import android.util.Log;

/*
 * General HTTP handler class
 */
public class HttpManager {
   
    private final static String TAG = "HttpManager";
   
    private final static String POST_MIME_TYPE = "application/x-www-form-urlencoded";
       
    private final static String POST_MIME_TYPE_FILE = "multipart/form-data";
   
    public static String doGet (String serviceEndpoint, Properties props) throws Exception
    {

        HttpClient httpClient = new DefaultHttpClient();

        StringBuilder uriBuilder = new StringBuilder(serviceEndpoint);
   
        StringBuffer sbResponse = new StringBuffer ();
       
        if (props != null)
        {
        Enumeration<Object> enumProps = props.keys();
        String key, value = null;
       
        uriBuilder.append('?');
       
        while (enumProps.hasMoreElements())
        {
            key = (String)enumProps.nextElement();
            value = (String)props.get(key);
            uriBuilder.append(key);
            uriBuilder.append('=');
            uriBuilder.append(java.net.URLEncoder.encode(value));
            uriBuilder.append('&');
           
        }
        }
       

        HttpGet request = new HttpGet(uriBuilder.toString());
        HttpResponse response = httpClient.execute(request);

        int status = response.getStatusLine().getStatusCode();

        ByteArrayOutputStream ostream = new ByteArrayOutputStream();
        // we assume that the response body contains the error message
        if (status != HttpStatus.SC_OK) {
           
            //ByteArrayOutputStream ostream = new ByteArrayOutputStream();
            response.getEntity().writeTo(ostream);
            Log.e("HTTP CLIENT", ostream.toString());
           
           
            return null;
           
        } else {
            /*
            InputStream content = response.getEntity().getContent();
            // <consume response>
           
            BufferedReader reader = new BufferedReader (new InputStreamReader(content));
            String line;
           
            while ((line = reader.readLine())!=null)
                sbResponse.append(line);
           
            content.close(); // this will also close the connection
            */
           
            response.getEntity().writeTo(ostream);
        }
       
        return ostream.toString();
       
    }
   
    public static String doPost (String serviceEndpoint, Properties props) throws Exception
    {

        HttpClient httpClient = new DefaultHttpClient();
       
        HttpPost request = new HttpPost(serviceEndpoint);
        HttpResponse response = null;
        HttpEntity entity = null;
         
        StringBuffer sbResponse = new StringBuffer ();
       
        Enumeration<Object> enumProps = props.keys();
        String key, value = null;
       
         List <NameValuePair> nvps = new ArrayList <NameValuePair>();
       
        while (enumProps.hasMoreElements())
        {
            key = (String)enumProps.nextElement();
            value = (String)props.get(key);
            nvps.add(new BasicNameValuePair(key, value));
           
            Log.i(TAG,"adding nvp:" + key + "=" + value);
        }
       
        UrlEncodedFormEntity uf = new UrlEncodedFormEntity(nvps, HTTP.UTF_8);
       
        Log.i(TAG, uf.toString());
       
        request.setEntity(uf);
        
        request.setHeader("Content-Type", POST_MIME_TYPE);
       
        Log.i(TAG, "http post request: " + request.toString());
       
         // Post, check and show the result (not really spectacular, but works):
         response = httpClient.execute(request);
         entity = response.getEntity();
        
        int status = response.getStatusLine().getStatusCode();

        // we assume that the response body contains the error message
        if (status != HttpStatus.SC_OK) {
            ByteArrayOutputStream ostream = new ByteArrayOutputStream();
            entity.writeTo(ostream);
           
            Log.e(TAG, " error status code="+status);
            Log.e(TAG, ostream.toString());
               
            return null;
        } else {
            InputStream content = response.getEntity().getContent();
            // <consume response>
           
            BufferedReader reader = new BufferedReader (new InputStreamReader(content));
            String line;
           
            while ((line = reader.readLine())!=null)
                sbResponse.append(line);
           
            content.close(); // this will also close the connection
           
            return sbResponse.toString();
        }
       
       
       
    }
   
    /*
    public static String uploadFile (String serviceEndpoint, Properties properties, String fileParam, String file) throws Exception
    {


        HttpClient httpClient = new DefaultHttpClient();

        HttpPost request = new HttpPost(serviceEndpoint);
        MultipartEntity entity = new MultipartEntity();
           
        Iterator<Map.Entry<Object,Object>> i = properties.entrySet().iterator();
        while (i.hasNext())
        {
               Map.Entry<Object,Object> entry = (Map.Entry<Object,Object>) i.next();
               String key = (String) entry.getKey();
               String val = (String) entry.getValue();
               entity.addPart(key, new StringBody(val));
         }
        File upload = new File(file);
        Log.i("httpman","upload file (" + upload.getAbsolutePath() + ") size=" + upload.length());
       
        entity.addPart(fileParam, new FileBody(upload));
        request.setEntity(entity);
       
       
        HttpResponse response = httpClient.execute(request);
        int status = response.getStatusLine().getStatusCode();

        if (status != HttpStatus.SC_OK) {
   
        } else {
           
        }

        return response.toString();
       
    }*/

David Golightly

unread,
May 4, 2009, 10:19:41 PM5/4/09
to phonegap
Good, except I'm not talking about accessing local files- I'm talking
about accessing files over the web, which should be supported,
especially in the context of a native app that is supposed to have
access to all the device's hardware; web security restrictions should
not apply here.
Reply all
Reply to author
Forward
0 new messages