Client Android REST, exemple?

115

Même si ce fil a accepté la réponse, n'hésitez pas à proposer d'autres idées, vous utilisez ou aimez


J'ai rencontré ces articles:

Et cela m'amène à cette vidéo Google I / O 2010 sur les applications clientes REST

Depuis, je crée un composant REST en tant que composant statique dans ma classe de contrôleur d'application.

À partir de maintenant, je pense que je devrais changer le modèle. Quelqu'un a souligné que l' application Google IOSched est un excellent exemple de la façon d'écrire des clients REST sur Android. Quelqu'un d'autre a dit que cette méthode était trop compliquée.

Alors, quelqu'un peut-il nous montrer quelle est la meilleure pratique? En bref et simple.
L'application IOSched est trop complexe pour un exemple de cas d'utilisation.

Marek Sebera
la source
Bonjour, En général, je développe un package séparé pour le service Web nommé "ws", j'ai généralisé la classe nommée "WebServicUtils.java". La classe WebServiceUtils.java a des méthodes pour accéder au service Web. Je ne suis pas sûr que ma technique soit la meilleure ou non mais elle est réutilisable à chaque fois que je copie mon package ws dans l'application Android, faites-moi savoir si vous souhaitez en savoir plus sur ma technique.
Ketan Parmar
Je ne pense pas que le commentateur youtube ait une meilleure alternative. Nous devons travailler avec les API d'Android, même si elles sont souvent insensément trop compliquées et verbeuses.
Timmmm
En remarque, Mechanoid, un plugin éclipse open-source pour Android peut générer des clients JSON-REST à l'aide d'un simple DSL, un guide sur la façon de l'utiliser peut être trouvé ici robotoworks.com/mechanoid-plugin/service-client-dsl (Je suis l'auteur de ce plugin, désolé pour le plug sans vergogne!)
Ian Warwick
Cela peut être très utile pour les personnes qui apprennent l'implémentation du client REST Android. Présentation de Dobjanschi transcrite en PDF: drive.google.com/file/d/0B2dn_3573C3RdlVpU2JBWXdSb3c/…
Kay Zed

Réponses:

99

EDIT 2 (octobre 2017):

Nous sommes en 2017. Il suffit d'utiliser Retrofit. Il n'y a presque aucune raison d'utiliser autre chose.

ÉDITER:

La réponse originale a plus d'un an et demi au moment de cette modification. Bien que les concepts présentés dans la réponse originale soient toujours valables, comme le soulignent d'autres réponses, il existe désormais des bibliothèques qui vous facilitent la tâche. Plus important encore, certaines de ces bibliothèques gèrent les changements de configuration de périphérique pour vous.

La réponse originale est conservée ci-dessous pour référence. Mais prenez également le temps d'examiner certaines des bibliothèques clientes Rest pour Android pour voir si elles correspondent à vos cas d'utilisation. Voici une liste de certaines des bibliothèques que j'ai évaluées. Il ne s'agit en aucun cas d'une liste exhaustive.


Réponse originale:

Présentation de mon approche pour avoir des clients REST sur Android. Je ne prétends pas que ce soit le meilleur cependant :) Notez également que c'est ce que j'ai proposé en réponse à mon besoin. Vous devrez peut-être avoir plus de couches / ajouter plus de complexité si votre cas d'utilisation l'exige. Par exemple, je n'ai pas du tout de stockage local; car mon application peut tolérer la perte de quelques réponses REST.

Mon approche utilise juste AsyncTasks sous les couvertures. Dans mon cas, j'appelle ces tâches à partir de mon Activityinstance; mais pour tenir pleinement compte des cas tels que la rotation de l'écran, vous pouvez choisir de les appeler à partir de l'un Serviceou l'autre.

J'ai délibérément choisi mon client REST lui-même comme API. Cela signifie que l'application qui utilise mon client REST n'a même pas besoin de connaître les URL REST réelles et le format de données utilisé.

Le client aurait 2 couches:

  1. Couche supérieure: le but de cette couche est de fournir des méthodes qui reflètent la fonctionnalité de l'API REST. Par exemple, vous pouvez avoir une méthode Java correspondant à chaque URL de votre API REST (ou même deux - une pour les GET et une pour les POST).
    Il s'agit du point d'entrée dans l'API client REST. C'est la couche que l'application utiliserait normalement. Cela pourrait être un singleton, mais pas nécessairement.
    La réponse de l'appel REST est analysée par cette couche dans un POJO et renvoyée à l'application.

  2. Il s'agit de la AsyncTaskcouche de niveau inférieur , qui utilise des méthodes client HTTP pour sortir et effectuer cet appel REST.

De plus, j'ai choisi d'utiliser un mécanisme de rappel pour communiquer le résultat des AsyncTasks à l'application.

Assez de texte. Voyons maintenant du code. Prenons une URL API REST hypothétique - http://myhypotheticalapi.com/user/profile

La couche supérieure pourrait ressembler à ceci:

   /**
 * Entry point into the API.
 */
public class HypotheticalApi{   
    public static HypotheticalApi getInstance(){
        //Choose an appropriate creation strategy.
    }
    
    /**
     * Request a User Profile from the REST server.
     * @param userName The user name for which the profile is to be requested.
     * @param callback Callback to execute when the profile is available.
     */
    public void getUserProfile(String userName, final GetResponseCallback callback){
        String restUrl = Utils.constructRestUrlForProfile(userName);
        new GetTask(restUrl, new RestTaskCallback (){
            @Override
            public void onTaskComplete(String response){
                Profile profile = Utils.parseResponseAsProfile(response);
                callback.onDataReceived(profile);
            }
        }).execute();
    }
    
    /**
     * Submit a user profile to the server.
     * @param profile The profile to submit
     * @param callback The callback to execute when submission status is available.
     */
    public void postUserProfile(Profile profile, final PostCallback callback){
        String restUrl = Utils.constructRestUrlForProfile(profile);
        String requestBody = Utils.serializeProfileAsString(profile);
        new PostTask(restUrl, requestBody, new RestTaskCallback(){
            public void onTaskComplete(String response){
                callback.onPostSuccess();
            }
        }).execute();
    }
}


/**
 * Class definition for a callback to be invoked when the response data for the
 * GET call is available.
 */
public abstract class GetResponseCallback{
    
    /**
     * Called when the response data for the REST call is ready. <br/>
     * This method is guaranteed to execute on the UI thread.
     * 
     * @param profile The {@code Profile} that was received from the server.
     */
    abstract void onDataReceived(Profile profile);
    
    /*
     * Additional methods like onPreGet() or onFailure() can be added with default implementations.
     * This is why this has been made and abstract class rather than Interface.
     */
}

/**
 * 
 * Class definition for a callback to be invoked when the response for the data 
 * submission is available.
 * 
 */
public abstract class PostCallback{
    /**
     * Called when a POST success response is received. <br/>
     * This method is guaranteed to execute on the UI thread.
     */
    public abstract void onPostSuccess();

}

Notez que l'application n'utilise pas le JSON ou XML (ou tout autre format) renvoyé directement par l'API REST. Au lieu de cela, l'application ne voit que le bean Profile.

Ensuite, la couche inférieure (couche AsyncTask) pourrait ressembler à ceci:

/**
 * An AsyncTask implementation for performing GETs on the Hypothetical REST APIs.
 */
public class GetTask extends AsyncTask<String, String, String>{
    
    private String mRestUrl;
    private RestTaskCallback mCallback;
    
    /**
     * Creates a new instance of GetTask with the specified URL and callback.
     * 
     * @param restUrl The URL for the REST API.
     * @param callback The callback to be invoked when the HTTP request
     *            completes.
     * 
     */
    public GetTask(String restUrl, RestTaskCallback callback){
        this.mRestUrl = restUrl;
        this.mCallback = callback;
    }
    
    @Override
    protected String doInBackground(String... params) {
        String response = null;
        //Use HTTP Client APIs to make the call.
        //Return the HTTP Response body here.
        return response;
    }
    
    @Override
    protected void onPostExecute(String result) {
        mCallback.onTaskComplete(result);
        super.onPostExecute(result);
    }
}

    /**
     * An AsyncTask implementation for performing POSTs on the Hypothetical REST APIs.
     */
    public class PostTask extends AsyncTask<String, String, String>{
        private String mRestUrl;
        private RestTaskCallback mCallback;
        private String mRequestBody;
        
        /**
         * Creates a new instance of PostTask with the specified URL, callback, and
         * request body.
         * 
         * @param restUrl The URL for the REST API.
         * @param callback The callback to be invoked when the HTTP request
         *            completes.
         * @param requestBody The body of the POST request.
         * 
         */
        public PostTask(String restUrl, String requestBody, RestTaskCallback callback){
            this.mRestUrl = restUrl;
            this.mRequestBody = requestBody;
            this.mCallback = callback;
        }
        
        @Override
        protected String doInBackground(String... arg0) {
            //Use HTTP client API's to do the POST
            //Return response.
        }
        
        @Override
        protected void onPostExecute(String result) {
            mCallback.onTaskComplete(result);
            super.onPostExecute(result);
        }
    }
    
    /**
     * Class definition for a callback to be invoked when the HTTP request
     * representing the REST API Call completes.
     */
    public abstract class RestTaskCallback{
        /**
         * Called when the HTTP request completes.
         * 
         * @param result The result of the HTTP request.
         */
        public abstract void onTaskComplete(String result);
    }

Voici comment une application peut utiliser l'API (dans un Activityou Service):

HypotheticalApi myApi = HypotheticalApi.getInstance();
        myApi.getUserProfile("techie.curious", new GetResponseCallback() {

            @Override
            void onDataReceived(Profile profile) {
                //Use the profile to display it on screen, etc.
            }
            
        });
        
        Profile newProfile = new Profile();
        myApi.postUserProfile(newProfile, new PostCallback() {
            
            @Override
            public void onPostSuccess() {
                //Display Success
            }
        });

J'espère que les commentaires sont suffisants pour expliquer le design; mais je serais heureux de fournir plus d'informations.

curieux
la source
J'aime plus cette réponse en raison d'exemples de code assez sympa. Merci
Marek Sebera
1
Cela ne vaut probablement rien, cela ne suit pas vraiment un modèle RESTful MVC approprié, tel que décrit par Virgil Dobjanschi. Vous devrez incorporer une couche ContentProvider complète, qui utilise une base de données SQLite que l'application utilise directement. Sinon, il s'agit d'un bon client REST léger pour Android.
Cooper
1
Une petite chose, vous devrez appeler execute sur ces Get / PostTask's
Mo Kargas
1
C'est vraiment génial. Comment pourrais-je rendre le GetResponseCallback plus générique, afin qu'il ne renvoie pas seulement un profil, ou suggéreriez-vous de créer un GetResponseCallback séparé pour chaque type de données de l'API?
1
@MichaelHerbig Oui, il existe des moyens de rendre GetResponseCallbackplus générique. Celui que je préfère est d'utiliser une interface de marqueur : Comme interface IGetResopnse{} pour désigner toutes les classes qui pourraient être des réponses. Ensuite, j'ai class Profile implements IGetResponseetc. Enfin, faire GetResponseCallbackgénérique IGetResponsecomme la borne supérieure : public abstract class GetResponseCallback<? extends IGetResponse>.
curioustechizen
11

«Développer des applications client Android REST» par Virgil Dobjanschi a donné lieu à de nombreuses discussions, car aucun code source n'a été présenté pendant la session ou fourni par la suite.

La seule implémentation de référence que je connaisse (veuillez commenter si vous en savez plus) est disponible sur Datadroid (la session Google IO est mentionnée sous / présentation). C'est une bibliothèque que vous pouvez utiliser dans votre propre application.

Le deuxième lien demande le «meilleur» framework REST, qui est largement discuté sur stackoverflow. Pour moi, la taille de l'application est importante, suivie des performances de l'implémentation.

  • Normalement, j'utilise l'implémentation simple org.json, qui fait partie d'Android depuis le niveau d'API 1 et n'augmente donc pas la taille de l'application.
  • Pour moi, les informations trouvées sur les performances des analyseurs JSON dans les commentaires étaient très intéressantes : à partir d'Android 3.0 Honeycomb, l'analyseur de streaming de GSON est inclus sous android.util.JsonReader. Malheureusement, les commentaires ne sont plus disponibles.
  • Spring Android (que j'utilise parfois) prend en charge Jackson et GSON. La documentation du module Spring Android RestTemplate pointe vers un exemple d'application .

Par conséquent, je m'en tiens à org.json ou GSON pour des scénarios plus complexes. Pour l'architecture d'une implémentation org.json, j'utilise une classe statique qui représente les cas d'utilisation du serveur (par exemple, findPerson, getPerson). J'appelle cette fonctionnalité à partir d'un service et j'utilise des classes utilitaires qui font le mappage (spécifique au projet) et le réseau IO (mon propre modèle REST pour GET ou POST). J'essaye d'éviter l'usage de la réflexion.

ChrLipp
la source
4
Le livre O'Reilly, Programming Android, propose une implémentation complète du modèle RESTful MVC de Dobjanschi (chapitres 12-13).
Cooper
Merci pour l'indication: j'ai trouvé cette déclaration sur Amazon: "Les chapitres 12 et 13 traitent des fournisseurs de contenu. Le traitement approfondi des fournisseurs de contenu avec un exemple de code et un exemple d'application m'a fourni plusieurs nouvelles informations sur le fonctionnement de cette technologie et sur la manière dont elle peut être utilisé dans des situations de programmation réelles. Le cadre du fournisseur de contenu pour stocker et référencer des données à l'aide d'URI est l'une des nouvelles fonctionnalités du système d'exploitation Android. Excellent travail pour expliquer la technologie étape par étape! "
ChrLipp
2
Le code est sur github.com/bmeike/ProgrammingAndroid2Examples (mais des chapitres manquent, vous pouvez les trouver dans le code de la première édition github.com/bmeike/ProgrammingAndroidExamples )
ChrLipp
Quelqu'un a-t-il pu faire fonctionner ce code sur ICS +? Le fichier todo sous l'exemple FinchVideo indique succinctement "- Crashes under ICS". J'ai été quelque peu déçu après avoir acheté le livre pour découvrir que les exemples de code sont cassés ...
eageranalyst
7

N'utilisez jamais AsynTask pour effectuer une requête réseau ou quoi que ce soit qui doit être persistant. Les tâches asynchrones sont fortement liées à votre activité et si l'utilisateur change l'orientation de l'écran depuis la recréation de l'application, la tâche AsyncTask sera arrêtée.

Je vous suggère d'utiliser le modèle de service avec Intent Service et ResultReceiver. Jetez un œil à RESTDroid . C'est une bibliothèque qui vous permet d'effectuer tout type de requête REST de manière asynchrone et de notifier votre interface utilisateur avec des écouteurs de requête implémentant le modèle de service de Virgil Dobjanschi.

Pierre Criulanscy
la source
3

Il existe une autre bibliothèque avec une API beaucoup plus propre et des données de type sécurisé. https://github.com/kodart/Httpzoid

Voici un exemple d'utilisation simple

Http http = HttpFactory.create(context);
http.post("http://example.com/users")
    .data(new User("John"))
    .execute();

Ou plus complexe avec des rappels

Http http = HttpFactory.create(context);
http.post("http://example.com/users")
    .data(new User("John"))
    .handler(new ResponseHandler<Void>() {
        @Override
        public void success(Void ignore, HttpResponse response) {
        }

        @Override
        public void error(String message, HttpResponse response) {
        }

        @Override
        public void failure(NetworkError error) {
        }

        @Override
        public void complete() {
        }
    }).execute();

C'est tout nouveau, mais semble très prometteur.

Arthur
la source
Il semble fonctionner sur AsyncTask, ce qui n'est pas bon pour les demandes de longue durée et les commutations entre les activités, car AsyncTask sera tué lorsque l'activité se termine.
Malachiasz
1

Il existe de nombreuses bibliothèques et j'utilise celle-ci: https://github.com/nerde/rest-resource . Cela a été créé par moi, et, comme vous pouvez le voir dans la documentation, c'est beaucoup plus propre et plus simple que les autres. Ce n'est pas axé sur Android, mais je l'utilise et cela fonctionne plutôt bien.

Il prend en charge HTTP Basic Auth. Il fait le sale boulot de sérialisation et de désérialisation des objets JSON. Vous l'aimerez, surtout si votre API est comme Rails.

Diego
la source
1

Clause de non-responsabilité: je suis impliqué dans le projet open source rest2mobile

Une autre alternative en tant que client REST consiste à utiliser rest2mobile .

L'approche est légèrement différente car elle utilise des exemples de repos concrets pour générer le code client pour le service REST. Le code remplace l'URL REST et les charges utiles JSON par des méthodes Java natives et des POJO. Il gère également automatiquement les connexions serveur, les appels asynchrones et POJO vers / depuis les conversions JSON.

Notez que cet outil est disponible en différentes versions (cli, plugins, support android / ios / js) et vous pouvez utiliser le plugin android studio pour générer l'API directement dans votre application.

Tout le code peut être trouvé sur github ici .

Manu
la source
3
Veuillez remplacer le premier lien par la cible réelle au lieu de faire de la publicité pour votre site.
Skydan
0

Nous avons ouvert notre bibliothèque cliente REST asynchrone légère pour Android, vous pourriez la trouver utile si vous avez des exigences minimales et que vous ne voulez pas gérer vous-même le multithreading - c'est très bien pour les communications de base mais pas un client REST complet bibliothèque.

Il s'appelle libRESTfulClient et peut être trouvé sur GitHub .

bk138
la source