IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Android Discussion :

Retrofit, onResume, access_token absent


Sujet :

Android

  1. #1
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    97
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 97
    Points : 40
    Points
    40
    Par défaut Retrofit, onResume, access_token absent
    Bonjour,

    Pour les web services de mon application Android, j'utilise Retrofit. J'ai créé un singleton qui permet de garder l'access_token et récupérer le service d'appel à mon API, pour avoir une seule instance accessible partout.

    Quand je lance l'appli aucun soucis il fait bien appel aux WS sans soucis. Quand je retourne sur le bureau, que je vais dans le gestionnaire et que je relance l'application direct aucun soucis. Par contre quand je retourne sur le bureau, que je lance 4-5 applications, puis que je vais dans le gestionnaire de tâche pour relancer l'application, à ce moment là je n'ai plus mon access_token, la variable de ma classe statique est vide...Mais une fois que je lui dis ok sur l'erreur il me remet mon appli et tout fonctionne parfaitement (y compris les WS).

    Je soupçonne que le système a du libérer de la mémoire et doit ensuite regénérer ma classe sauf qu'au moment de l'appel au WS la classe ne serait pas regénérée, ou un truc comme ça je ne sais pas trop.

    Si quelqu'un a une idée je suis preneur

    Voici quelques morceaux de mon code :

    Mon service permettant de récupérer l'instance, là où est stocké mon access_token :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
     
    public class FcServiceProvider {
     
        private static FcServiceProvider instance = new FcServiceProvider();
     
        private static FcWebServicesInterface fcService;
     
        public static final String client_id         = "***********";
        public static final String client_secret     = "*********";
     
        //seront remplis par les web services de connexion
        public static String accessTokenClient = "";//sera utilisé pour créer un compte utilisateur et check la version
        public static String accessTokenUser   = "";
     
        private FcServiceProvider(){
     
            Gson gson = new GsonBuilder()
                    .registerTypeAdapterFactory(new ItemTypeAdapterFactory())
                    .setDateFormat("yyyy'-'MM'-'dd'T'HH':'mm':'ss'.'SSS'Z'")
                    .create();
     
            RestAdapter restadapter = new RestAdapter.Builder()
                    .setConverter(new GsonConverter(gson))
                    .setEndpoint("http://192.168.1.9")
                    .setClient(new OkClient())
                    .build();
     
            fcService = restadapter.create(FcWebServicesInterface.class);
     
        }
     
        public static FcServiceProvider getInstance(){
            return instance;
        }
     
        public FcWebServicesInterface getFcService(){
            return fcService;
        }
     
    }

    Ma classe RestError, décrivant une erreur :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    public class RestError {
     
        @SerializedName("code")
        private Integer code;
     
        @SerializedName("message")
        private String message;
     
        public RestError(String message) {
            this.message = message;
        }
     
        public Integer getCode() {
            return code;
        }
     
        public void setCode(Integer code) {
            this.code = code;
        }
     
        public String getMessage() {
            return message;
        }
     
        public void setMessage(String message) {
            this.message = message;
        }
    }

    Ma classe de Callback :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
     
    public abstract class RestCallback<T> implements Callback<T>
    {
        public abstract void failure(RestError restError);
     
        @Override
        public void failure(RetrofitError error)
        {
            String errorDescription = "";
            Log.e("App", "errorDescription : " + errorDescription);
            Log.e("App", "error : " + error.getMessage());
            Log.e("App", "error : " + error.getUrl());
     
            if (error.getKind() == RetrofitError.Kind.NETWORK) {
                errorDescription = "Cette application a besoin d'une connexion internet pour fonctionner, veuillez vous connecter à internet.";
                failure(new RestError(errorDescription));
            } else {
                RestError restError = (RestError) error.getBodyAs(RestError.class);
     
                if (restError != null)
                    failure(restError);
                else
                {
                    failure(new RestError(error.getMessage()));
                }
            }
     
        }
    }

    Et enfin un exemple d'appel :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
     
    AsyncTask<Void, Void, Void> taskProfile = new AsyncTask<Void, Void, Void>(){
                @Override
                protected Void doInBackground(Void... params) {
     
                    FcWebServicesInterface fcService = FcServiceProvider.getInstance().getFcService();
                    try {
                        RestCallback<UserMainInfos> callback = new RestCallback<UserMainInfos>() {
                            @Override
                            public void failure(RestError restError) {
                                Toast.makeText(
                                        getActivity(),
                                        R.string.generic_error,
                                        Toast.LENGTH_LONG).show();
                                Log.e("App", ""+restError.getMessage());
                            }
     
                            @Override
                            public void success(UserMainInfos userMainInfos, Response response) {
                                final UserInfos uf = userMainInfos.getUser().getUserInfos();
                                final FragmentManager fragmentManager = getActivity().getSupportFragmentManager();
     
                                tvMenuRightName.setText(uf.getFullname());
                                tvMenuRightJobSociety.setText(uf.getJobSociety());
                                tvMenuRightJob.setText(uf.getJob());
     
                                Picasso.with(getActivity()).load(uf.getProfilePicture()).transform(new CircleTransform()).into(ivMenuRightPhoto);
     
                                bMenuRightViewMyCard.setOnClickListener(new View.OnClickListener() {
                                    @Override
                                    public void onClick(View v) {
                                        Intent intent = new Intent(getActivity(), UserCardActivity.class);
                                        getActivity().startActivity(intent);
     
                                        //et on ferme le menu
                                        ((MainActivity) getActivity()).getSlidingMenu().toggle();
                                    }
                                });
                            }
                        };
     
                        fcService.getUserConnectedInfos(FcServiceProvider.accessTokenUser, callback);
     
                        return null;
     
                    }
                    catch(RetrofitError re){
                        Log.e("App", "retrofit exception");
                        return null;
                    }
     
                }
            }.execute();


    Merci d'avance pour votre aide.

  2. #2
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    97
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 97
    Points : 40
    Points
    40
    Par défaut
    up, quelqu'un aurait une idée ?

  3. #3
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Il faudrait surtout voir la gestion de la durée de vie de l'activité... ce qui est fait dans onCreate / onStart / onResume ... (et leurs pendant à la destruction).

    IIRC: onSaveInstanceState() / onRestoreInstanceState() devrait permettre de sauvegarder (et relire) le token facilement avant que l'application ne soit supprimée par l'OS.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  4. #4
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    97
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 97
    Points : 40
    Points
    40
    Par défaut
    Salut Nicroman et merci pour tes conseils. Finalement, après quelques recherches je vais stocker l'access_token non pas dans ma classe statique mais plutôt dans les shared_preference en le cryptant, à priori c'est ce qu'il y a de plus populaire et ça résoudrait en même temps mon problème. Je verrais bien

  5. #5
    Expert éminent

    Homme Profil pro
    Ingénieur systèmes et réseaux
    Inscrit en
    Février 2007
    Messages
    4 253
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Rhône (Rhône Alpes)

    Informations professionnelles :
    Activité : Ingénieur systèmes et réseaux
    Secteur : High Tech - Multimédia et Internet

    Informations forums :
    Inscription : Février 2007
    Messages : 4 253
    Points : 7 618
    Points
    7 618
    Billets dans le blog
    3
    Par défaut
    Les "SharedPreferences" permettent de "survivre" à une application vraiment quittée par l'utilisateur... Est-ce le but ?
    Sauvegarder le token dans le bundle de sauvegarde des activité, permet de ne le conserver que le temps ou l'application est toujours "ouverte"

    Les deux font sens.
    N'oubliez pas de cliquer sur mais aussi sur si un commentaire vous a été utile !
    Et surtout

  6. #6
    Membre du Club
    Profil pro
    Inscrit en
    Janvier 2013
    Messages
    97
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2013
    Messages : 97
    Points : 40
    Points
    40
    Par défaut
    Disons que du coup les sharedPreference couvrent les deux problèmes, aussi bien quand on reprend l'application non quittée que quand on relance complètement l'application, du coup un seul code. D'après quelques recherches, c'est ce que font beaucoup de personnes, certains rajoutent même une partie cryptage dessus. Je vais donc probablement partir là dessus.

    Mon idée c'est de stocker l'access_token avec un lifetime et de check ce lifetime et de lancer un refresh du token lorsque celui-ci est périmé.

    Merci beaucoup pour les conseils =)

Discussions similaires

  1. Requête absente pour fusion avec Word
    Par stéphane_ais2 dans le forum Access
    Réponses: 5
    Dernier message: 05/12/2006, 15h08
  2. Réponses: 10
    Dernier message: 31/05/2005, 10h41
  3. Changement d'image si l'originale absente
    Par MitchDap dans le forum Général JavaScript
    Réponses: 8
    Dernier message: 16/03/2005, 09h06
  4. PHP SQL =>erreur de syntaxe (operateur absent)
    Par snipes dans le forum Langage SQL
    Réponses: 3
    Dernier message: 23/02/2005, 14h09

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo