How to call a RESTful web service from Android?

2019-01-05 09:45发布

I have written a REST web service in Netbean IDE using Jersey Framework and Java.

For every request the user needs to provide a username and a password, I know that this authentication is not a best practice (using a curl command like: curl -u username:password -X PUT http://localhsot:8080/user).

Now I want to call a REST web service from an Android Class.

How should I do it?

I have an Android Class which uses DefaultHttpClient and CredentialUsernameAndPassword, but when I run it in Eclipse, sometimes I get a runtime exception or SDK exception.

11条回答
欢心
2楼-- · 2019-01-05 09:57

Recently discovered that a third party library - Square Retrofit can do the job very well.


Defining REST endpoint

public interface GitHubService {
   @GET("/users/{user}/repos")
   List<Repo> listRepos(@Path("user") String user,Callback<List<User>> cb);
}

Getting the concrete service

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .build();
GitHubService service = restAdapter.create(GitHubService.class);

Calling the REST endpoint

List<Repo> repos = service.listRepos("octocat",new Callback<List<User>>() { 
    @Override
    public void failure(final RetrofitError error) {
        android.util.Log.i("example", "Error, body: " + error.getBody().toString());
    }
    @Override
    public void success(List<User> users, Response response) {
        // Do something with the List of Users object returned
        // you may populate your adapter here
    }
});

The library handles the json serialization and deserailization for you. You may customize the serialization and deserialization too.

Gson gson = new GsonBuilder()
    .setFieldNamingPolicy(FieldNamingPolicy.LOWER_CASE_WITH_UNDERSCORES)
    .registerTypeAdapter(Date.class, new DateTypeAdapter())
    .create();

RestAdapter restAdapter = new RestAdapter.Builder()
    .setEndpoint("https://api.github.com")
    .setConverter(new GsonConverter(gson))
    .build();
查看更多
混吃等死
3楼-- · 2019-01-05 09:57

Using Spring for Android with RestTemplate https://spring.io/guides/gs/consuming-rest-android/

// The connection URL 
String url = "https://ajax.googleapis.com/ajax/" + 
    "services/search/web?v=1.0&q={query}";

// Create a new RestTemplate instance
RestTemplate restTemplate = new RestTemplate();

// Add the String message converter
restTemplate.getMessageConverters().add(new StringHttpMessageConverter());

// Make the HTTP GET request, marshaling the response to a String
String result = restTemplate.getForObject(url, String.class, "Android");
查看更多
Melony?
4楼-- · 2019-01-05 09:59

I use this REST Client for my android. This looks really cool. Nice work by Luke.

http://lukencode.com/2010/04/27/calling-web-services-in-android-using-httpclient/

查看更多
Emotional °昔
5楼-- · 2019-01-05 10:02

Stop with whatever you were doing ! :)

Implement the RESTful client as a SERVICE and delegate the intensive network stuff to activity independent component: a SERVICE.

Watch this insightful video http://www.youtube.com/watch?v=xHXn3Kg2IQE where Virgil Dobjanschi is explaining his approach(es) to this challenge...

查看更多
三岁会撩人
6楼-- · 2019-01-05 10:04

This is an sample restclient class

public class RestClient
{
    public enum RequestMethod
    {
        GET,
        POST
    }
    public int responseCode=0;
    public String message;
    public String response;
    public void Execute(RequestMethod method,String url,ArrayList<NameValuePair> headers,ArrayList<NameValuePair> params) throws Exception
    {
        switch (method)
        {
            case GET:
            {
                // add parameters
                String combinedParams = "";
                if (params!=null)
                {
                    combinedParams += "?";
                    for (NameValuePair p : params)
                    {
                        String paramString = p.getName() + "=" + URLEncoder.encode(p.getValue(),"UTF-8");
                        if (combinedParams.length() > 1)
                            combinedParams += "&" + paramString;
                        else
                            combinedParams += paramString;
                    }
                }
                HttpGet request = new HttpGet(url + combinedParams);
                // add headers
                if (headers!=null)
                {
                    headers=addCommonHeaderField(headers);
                    for (NameValuePair h : headers)
                        request.addHeader(h.getName(), h.getValue());
                }
                executeRequest(request, url);
                break;
            }
            case POST:
            {
                HttpPost request = new HttpPost(url);
                // add headers
                if (headers!=null)
                {
                    headers=addCommonHeaderField(headers);
                    for (NameValuePair h : headers)
                        request.addHeader(h.getName(), h.getValue());
                }
                if (params!=null)
                    request.setEntity(new UrlEncodedFormEntity(params, HTTP.UTF_8));
                executeRequest(request, url);
                break;
            }
        }
    }
    private ArrayList<NameValuePair> addCommonHeaderField(ArrayList<NameValuePair> _header)
    {
        _header.add(new BasicNameValuePair("Content-Type","application/x-www-form-urlencoded"));
        return _header;
    }
    private void executeRequest(HttpUriRequest request, String url)
    {
        HttpClient client = new DefaultHttpClient();
        HttpResponse httpResponse;
        try
        {
            httpResponse = client.execute(request);
            responseCode = httpResponse.getStatusLine().getStatusCode();
            message = httpResponse.getStatusLine().getReasonPhrase();
            HttpEntity entity = httpResponse.getEntity();

            if (entity != null)
            {
                InputStream instream = entity.getContent();
                response = convertStreamToString(instream);
                instream.close();
            }
        }
        catch (Exception e)
        { }
    }

    private static String convertStreamToString(InputStream is)
    {
        BufferedReader reader = new BufferedReader(new InputStreamReader(is));
        StringBuilder sb = new StringBuilder();
        String line = null;
        try
        {
            while ((line = reader.readLine()) != null)
            {
                sb.append(line + "\n");
            }
            is.close();
        }
        catch (IOException e)
        { }
        return sb.toString();
    }
}
查看更多
看我几分像从前
7楼-- · 2019-01-05 10:04

There are tons of libraries available for doing this

Retrofit replaces the traditional AsyncTask and it has its own background task so you really don't have to worry about it. The performance is also very good relative to AsyncTask.

Check it here,

http://square.github.io/retrofit/

A complete example of Retrofit could be found here,

https://futurestud.io/blog/retrofit-getting-started-and-android-client/

Volley is also efficient and easy to use. You can take a look here:

https://github.com/mcxiaoke/android-volley

There a bunch of resources on the web on how to use it:

http://www.androidhive.info/2014/05/android-working-with-volley-library-1

AsyncTask

OR You should use implement an AsyncTask and then override the method doInTheBackground() - where you can implement the REST call.

Then you can use onPostExecute() to let the UI thread process the results that were returned in the previous step.

This answer provides a good example of how to implement AsyncTask. see AsyncTask Android example

Per Ruffles's comment below, here's a more relevant example of REST call using AsyncTask: http://alvinalexander.com/android/android-asynctask-http-client-rest-example-tutorial

查看更多
登录 后发表回答