17. Liste de comptes
public static final class Source implements BaseColumns {
public static final String TYPE_ITEM = CURSOR_ITEM_BASE_TYPE + "/" + Source.class.getCanonicalName().toLowerCase();
public static final String TYPE_DIR = CURSOR_DIR_BASE_TYPE + "/" + Source.class.getCanonicalName().toLowerCase();
public static final String FIELD_NAME = "name";
public static final String FIELD_TYPE = "type";
public static final String ID = TABLE_DEFAULT_ID;
private Source() {
}
}
18. Liste des informations affichées
public static class News implements BaseColumns {
public static final String TYPE_ITEM = CURSOR_ITEM_BASE_TYPE + "/" +
News.class.getCanonicalName().toLowerCase();
public static final String TYPE_DIR = CURSOR_DIR_BASE_TYPE + "/" +
News.class.getCanonicalName().toLowerCase(); public static final String FIELD_SOURCE_ID = "source_id";
public static final String FIELD_ORIGINAL_ID = "original_id";
public static final String FIELD_TITLE = "title";
public static final String FIELD_SUMMARY = "summary";
public static final String FIELD_URL = "url";
public static final String FIELD_DATE = "date";
public static final String FIELD_IMAGE = "img";
public static final String ID = TABLE_DEFAULT_ID;
private News() {
}
}
Je suis Simon GUEROUT, je suis en charge de la branche Québécoise - à Montréal - de Sidereo.
Sidereo est une entreprise originaire de France, spécialisée dans le développement de technologies mobiles.
My name is Simon GUEROUT, I am in charge of the new branch of Sidereo in Montreal, QC.
Sidereo started its business in France, and is specialized in mobile technologies.
Qui n’a pas déjà vu ces écrans ?
Aujourd’hui je vais vous parler de différentes choses les concernant :
Un premier rappel concernant les éléments du système qu’ils représentent
Un second rappel concernant la manière dont ils sont liés
Finalement, une présentation d’une utilisation un peu spéciale
Who doesn’t know these screens ?
Today, I am going to explain different things about them :
A first reminder about what they represent inside the system
A second reminder about the way they interact
At last, I’l show how I used the components to handle a specific case
L’Authenticator est le composant qui gère le compte utilisateur.
Son rôle principal consiste :
Fournir l’accès aux différents jetons d’authentification d’un compte,
Tenter d’authentifier l’utilisateur auprès du serveur (typiquement en utilisant ses identifiants),
Proposer à l’utilisateur de se reconnecter au service le cas échéant (en fournissant un Intent approprié);
The Authenticator manages the user account.
Its main role consists in :
Offer acces to the various authentication tokens of an account,
Use the account’s credentials and authenticate the user
Redirect the user to a connection activity, using an Intent;
Ici, on voit la description de 2 Authenticator.
Les informations importantes qui permettent de définir l’Authenticator sont :
son type (nous reviendrons sur ce point plus tard)
son label : qui est présenté à l’utilisateur
les icônes qui seront affichées dans les paramètres
les préférences auxquelles l’utilisateur aura accès
Cette description est faite dans un fichier XML, que l’on référence dans le Manifest lorsque que l’on déclare le service de l’Authenticator.
C’est un exemple intéressant issu du code source d’Android (cf. packages/apps/Email).
On voit la possibilité d’avoir plusieurs Authenticator pour un même type de compte.
We can see the description of 2 Authenticators.
The information defining the Authenticator is :
its type (we’ll get back to that)
its label, which will be displayed to the user
the icons used in the parameters screen
the preferences screen
This description is written in a XML file, which is referenced in the Manifest, when declaring the Authenticator’s service.
http://developer.android.com/training/sync-adapters/creating-authenticator.html
http://developer.android.com/reference/android/accounts/AbstractAccountAuthenticator.html
http://udinic.wordpress.com/2013/04/24/write-your-own-android-authenticator/
Le système représente le compte utilisateur à l’aide de la classe Account.
Cette référence va servir par la suite pour un certain nombre d’opérations.
On va pouvoir y rattacher - via le gestionnaire de comptes “AccountManager” - un certain nombre d’informations:
Des données utilisateurs sous la forme de chaînes de caractères
Des jetons d’authentification, aussi sous la forme de chaînes de caractères
Le mot de passe du compte, qui sert essentiellement à redemander un jeton d’authentification si le précédent est périmé
Ces informations ne sont normalement utilisable que par des paquets signés avec la même clé, afin de garantir un certain niveau sécurité
Si d’autres applications tentent d’accéder aux informations du compte, l’utilisateur sera notifié, et pourra accepter ou non ce partage.
The system represents the user account using the Account class.
This will be used as a reference for various operations.
The application will be able to save many informations, using the AccountManager:
User data, formatted as strings,
Authentication tokens, also formatted as strings,
The account password, which could be used to re-authenticate the user without prompting a login screen,
These informations are only shared to applications with an identical signature, in order to keep it safe.
If other apps try to access it, the user will be asked if he wants to let the them access it or not.
http://developer.android.com/reference/android/accounts/Account.html
http://developer.android.com/reference/android/accounts/AccountManager.html
Le ContentProvider est une classe largement connue et documentée.
Il est souvent utilisé de manière indépendante dans les applications, afin de fournir une abstraction de base de données.
On peut aussi l’exposer, pour partager et/ou mettre en commun des informations (ce qui est fait typiquement avec les contacts ou encore le calendrier).
The ContentProvider is a widely used and documented class.
It is often used independently in applications, in order to provide a database abstraction.
It can be exported, in order to share information : Contacts and Calendars are the best examples.
Le ContentProvider est rattaché à une ou plusieurs autorités, qui permettent de définir le type de données qu’il contient.
Lorsque l’on regarde de près nos comptes sur le périphérique, on peut faire le lien avec les ContentProviders auxquels ceux-ci sont connectés.
Mais justement, comment fait-on le lien entre un compte et des ContentProvider ? On va le voir par la suite !
The ContentProvider is linked to one or many authorities, which describe the type of data it provides.
When we take a look at the list of accounts on a device, it is possible to link the ContentProviders to which they are connected.
But, how can we connect Accounts and ContentProviders ? That is what we are going to see next.
Ce lien est fait avec un composant que l’on appelle un SyncAdapter.
Il est lié à un service, déclaré dans le manifest, et décrit dans un fichier XML.
Cette descirption relie une autorité (ContentProvider) avec un type de compte (Authenticator).
Le composant fait plus que le lien, il est appelé par le systèmes pour synchroniser les données du compte vers le ContentProvider.
C’est là où l’on va effectuer les appels réseaux, en utilisant les informations du compte utilisateur.
This link is done using a component called the SyncAdapter.
It is linked to a serviice, declared in the app’s manifest, and described in a XML file.
This description connects the dots between an authority (ContentProvider) and an account type (Authenticator).
This component does more than a link, it is called by the system in order to sync the account’s data with the ContentProvider.
This is where the calls to the network wil be done, using the user’s account informations.
Vous avez déjà probablement utilisé le ContentResolver pour utiliser un ContentProvider, mais celui-ci ne sert pas qu’à faire des requêtes !
Il permet de définir, entre autres la manière dont vous souhaitez synchroniser un le contenu d’un ContentProvider en fonction d’un compte.
Votre application va pouvoir définir certains paramètres comme l’automatisation de la synchro ou sa périodicité.
I va aussi permettre de demander des synchronisations manuelles, ce qui peut s’avérer utile.
You may haved used the ContentResolve in order to make requests to a ContentProvider, but it is not its only use !
It allows to set how your application will synchronize your service’s content with a ContentProvider, depending on an account.
Your application will be able to set whether you sync will happen automatically and/or its perodicity.
Voici donc un schéma qui récapitule le fonctionnement de l’ensemble des composants.
Here is a diagram that summarizes the operation of all components.
source : http://fr.slideshare.net/AlexTumanoff/android-sync-adapter
Les gros avantages de cette solution sont :
L’intégration au système Android, qui sait bien gérer tout ce qui concerne le comptes utilisateurs et les contenus
La synchronisation est simplifiée et optimisée en fonction de la batterie, de la disponibilité réseau, etc.
Toutefois, comparé, à une solution maison, on a un peu plus de développement à faire.
The advantages of using these component are:
It is part of the Android system, which is able to manage everything about user accouts and contents,
Synchronization is simplified and optimized depending on the battery, network availability, etc.
Though, compared to a homemade solution, you may have to develop a little bit more.
Je vais vous présenter un cas d’usage, qui nous a amené à utiliser ces composants, et la manière dont nous avons pu en tirer profit au maximum.
Nous voulions développer une application, connectée simultanément à différents services, qui fournissent des informations utiles, stockées dans une base de données.
Nous ne voulions pas mettre en place une solution impliquant un service web qui gère le traitement de ces informations.
De plus, l’application doit être capable de gérer plusieurs comptes, parfois pour un même fournisseur.
Et pour finir, on doit toujours obtenir des informations récentes lorsque l’on ouvre l’application.
I am going to show you a use case, which led us to use these components, and how we were able to take full advantage of them.
We wanted to develop an app, connected simultaneaously to different services, offering useful data, which would be stored in a database.
We did not want to set up a data processeing webservice of our own.
Furthermore, the application would have to handle multiple accounts, even of the same provider.
Last, we wanted our app to always have fresh information loaded when the user starts it.
Notre application affiche du contenu de différents réseaux sociaux.
Voici une copie d’écran qui montre des informations venant de Twitter et Facebook.
Our application displays content from social networks.
Here is a screenshot showing data from Twitter and Facebook.
Si on regarde les composants que j’ai présenté au début, c’est exactement ce qui semble adapté à la situation :
On a des comptes utilisateurs, authentifiés auprès de services externes
Les informations de l’application doivent être constamment à jour
On doit stocker cette information dans une base de données
By looking a the components I described before, these are adapted to the situation:
We have user accounts, authenticated to external services,
The information have to be updated on a regular basis
We have to store data in a database
L’application connecte l’utilisateur à plusieurs services, comment est-ce que je vais les représenter ?
Est-ce que je vais créer un Authenticator et un SyncManager pour chacun d’entre eux ?
Ou est-ce que je vais créer un système global, qui saura gérer tous les types de comptes ?
Je vais vous expliquer comment nous avons choisi de développer cette partie de l’application et quelles ont les raisons qui nous y ont poussé.
The application is connected to multiple services, but how am I going to represent them ?
Will I create multiple Authenticator and SyncManager for each of them ?
Or shall I develop a global system, which will handle every kind of account ?
I will give you explanations about the choices we made when developing this application.
Notre base de données contient une table faisant la liste des comptes.
Vous allez me dire que c’est un doublon du système, mais en fait, c’est important de conserver l’information.
En effet, lorsque le système modifie un compte, un Intent est diffusé, mais on ne sait pas ce qui a changé.
Il faut donc faire la différence entre les comptes du système et se propres comptes.
On va donc stocker un minimum d’informations (id, nom du compte, type de compte).
Our database contains a table for the user accounts.
You are going to tell me that the system holds the list of accounts, but I’ll reply that it is important to store a copy of this list.
In fact, when an account is changed, an Intent is broadcasted, but it does not contain information about the change.
The difference between the system’s list and our application’s list has to be made.
We will store a small amount of data about the account : id, name, and type.
Voici ce que l’on stocke en provenance de nos sources d’informations.
On stocke toujours l’id de la source, et l’id d’origine, c’est utile en cas de mise à jour.
This describes the data stored from the social networks.
We always store the original id and the source id, in order to be able to update easily the database.
Le fait de choisir cette solution nous aurait permis d’avoir quelque chose d’assez cloisonné en fonction de chaque source de données.
On gère un Authenticator et un SyncAdapter par source, puis tout va fonctionner comme prévu.
Toutefois, le fait de développer plusieurs Authenticator possède toutefois un désavantage, qui n’est pas technique.
C’est en terme de lisibilité que cela nous a posé problème.
Lorsque l’on va ajouter un compte ou lister les comptes, notre application va apparaître plusieurs fois dans la liste de comptes ou dans les possibilités d’ajout de comptes.
De plus, du fait de la nature de ces comptes, nous ne souhaitions pas créer la confusion (pourquoi plusieurs comptes reliés à Twitter ? etc.)
Nous avons préféré avoir un seul élément dans ces listes, pour ne pas perdre l’utilisateur.
Using multiple Authenticator would have allowed us to split the logic for each data source.
One Authenticator and one SyncAdapter per source could have done the job.
Though, this solution is problematic, but not technically.
The lisibility of the information was a problem.
When the user will add or list the accounts, our application will appear multiple times in the lists.
As the accounts are connected to services that might have their own accounts already in the system, it may be confusing (multiple Twitter accounts ? etc.)
We made the choice of having a single entry in the accounts list.
Nous avons donc choisi de n’avoir avec un seul type de compte.
On ne crée donc qu’un seul Authenticator, et un seul SyncAdapter.
La petite différence est que chaque compte doit être identifié en fonction du service auquel il est connecté.
We decided to have only one type of accoutn.
We will develop only one Authenticator and one SyncAdapter.
The small différence with the previous solution, is that each account has a subtype, representing the service it is connected to.
Notre Authenticator et notre SyncAdapter ne font que gérer ce qui est commun à tous les types de comptes et de sources de données:
lien avec l’AccountManager pour la récupération des jetons d’authentification existants
insertion, suppression et mise à jour des données dans le content provider
Pour le reste, nous avons donc décidé de nous baser sur de la délégation :
récupération de nouveaux jetons de connexion
sauvegarde des jetons de connexion via l’AccountManager
chargement des données et adaptation au modèle communs
Au final, c’est presque identique à la première solution, en terme de développement, mais on y gagne en lisibilité.
Our Authenticator and SyncAdapter are handling the common logic to all types of accounts and data sources :
call the AccountManager to retrieve existing account data,
add, suppress or update data with the ContentProvider
For other operations, we decided to delegate it to service-dependent classes :
retrieving new authentication data,
backup the new authentication tokens with the AccountManager
load the social networks’ data and fit it into a defined model
In the end, our solution, is almost identical to the first possibility in terms of development, but we improved the lisibility.
On a une approche qui est similaire à ce qui est disponible dans le framework aujourd’hui (Contacts, etc.)
On profite des automatismes du système et des optimisations qui ont pu être faites pour ce type de cas.
Lorsque l’on va développer l’affichage, on peut accéder à une base de données unique, et on utilise des mécanismes standards.
Bien que l’on utilise qu’un seul Authenticator, on ne perd pas la flexibilité offerte par le système (plusieurs comptes d’un même type, règles de synchronisation, etc.).
We have used the components of the framework, the same way standard applications do it (Contatcs, Email, …).
We take advantage of the system’s automatisms, and optimizations for this use case.
When developing the applications activities, we will access to a single database, using standard mechanisms.
Although we have a single Authenticator, we still have a flexible system (multiple accounts - even of the same type-, synchronization rules, etc.)