Le fournisseur d'agenda est un dépôt pour les événements d'agenda d'un utilisateur. La L'API Calendar Provider vous permet d'interroger, d'insérer, de mettre à jour et de supprimer les opérations sur les agendas, les événements, les participants, les rappels, etc.
L'API Calendar Provider peut être utilisée par les applications et les adaptateurs de synchronisation. Les règles varient selon le type de programme qui effectue les appels. Ce document se concentre principalement sur l'utilisation de l'API Calendar Provider en tant qu'application. Pour pour en savoir plus sur les différences entre les adaptateurs de synchronisation, reportez-vous à la section Adaptateurs de synchronisation.
Normalement, pour lire ou écrire des données d'agenda, le fichier manifeste d'une application doit inclure les autorisations appropriées, décrites dans la section Autorisations utilisateur. Pour faciliter l'exécution des opérations courantes, le gestionnaire Le fournisseur propose un ensemble d'intents, comme décrit dans la section Agenda Intents : Ces intents redirigent les utilisateurs vers l'application Agenda pour insérer, afficher et modifier des événements. L'utilisateur interagit avec l'application Agenda, puis revient à l'application d'origine. Ainsi, votre application n'a pas besoin de demander d'autorisations, ni de fournir une interface utilisateur pour afficher ou créer des événements.
Principes de base
Les fournisseurs de contenu stockent les données et les rendent applications. Les fournisseurs de contenu proposés par la plate-forme Android (y compris le fournisseur d'agenda) présentent généralement les données sous la forme d'un ensemble de tableaux basé sur un de base de données relationnelle, où chaque ligne est un enregistrement et chaque colonne est des données un type et une signification particuliers. Grâce à l'API Calendar Provider, les applications et les adaptateurs de synchronisation peuvent obtenir un accès en lecture/écriture aux tables de base de données contenant les données d'agenda d'un utilisateur.
Chaque fournisseur de contenu expose un URI public (encapsulant un objet Uri
) qui identifie de manière unique son ensemble de données. Un fournisseur de contenu qui contrôle plusieurs ensembles de données (plusieurs tables) expose un URI distinct pour chacun d'eux. Tous les URI des fournisseurs commencent par la chaîne "content://". Cela indique que les données sont contrôlées par un fournisseur de contenu. Agenda
Le fournisseur définit des constantes pour les URI de chacune de ses classes (tables). Ces
Les URI sont au format <class>.CONTENT_URI
. Pour
Exemple : Events.CONTENT_URI
.
La figure 1 est une représentation graphique du modèle de données du fournisseur d'agenda. Elle montre les tableaux principaux et les champs qui les relient les uns aux autres.
Un utilisateur peut avoir plusieurs agendas, et différents agendas peuvent être associés à différents types de comptes (Google Agenda, Exchange, etc.).
CalendarContract
définit le modèle de données des informations liées aux agendas et aux événements. Ces données sont stockées dans plusieurs tables, listées ci-dessous.
Table (classe) | Description |
---|---|
Ce tableau contient les informations spécifiques à l'agenda. Chaque ligne de ce tableau contient les détails pour un seul agenda, comme son nom, sa couleur, ses informations de synchronisation, etc. | |
CalendarContract.Events |
Ce tableau contient les informations spécifiques à l'événement. Chaque ligne de ce tableau contient les informations
(par exemple, le titre de l'événement, le lieu, l'heure de début, la fin)
l'heure, etc. L'événement peut se produire une seule fois ou se répéter plusieurs fois. Participants
les rappels et les propriétés étendues sont stockés dans des tables distinctes.
Elles disposent toutes d'un EVENT_ID
qui fait référence à _ID dans le tableau "Événements". |
CalendarContract.Instances |
Ce tableau contient l'heure de début et de fin de chaque occurrence d'un événement. Chaque ligne de ce tableau représente une occurrence d'événement unique. Pour les événements ponctuels, il existe un mappage individuel des instances aux événements. Pour les événements récurrents, plusieurs lignes sont automatiquement générées et correspondent à plusieurs occurrences de cet événement. |
CalendarContract.Attendees |
Ce tableau contient les informations sur les participants (invités) à l'événement. Chaque ligne représente un seul invité . Elle spécifie le type d'invité et sa réponse de participation. pour l'événement. |
CalendarContract.Reminders |
Ce tableau contient les données d'alerte/de notification. Chaque ligne représente une seule alerte pour un événement. Un événement peut avoir plusieurs rappels. Le nombre maximal de rappels par événement est spécifié dans MAX_REMINDERS , qui est défini par l'adaptateur de synchronisation propriétaire de l'agenda donné. Les rappels sont spécifiés quelques minutes avant l'événement
et disposent d'une méthode qui détermine
la façon dont l'utilisateur sera alerté. |
L'API Calendar Provider est conçue pour être flexible et puissante. Au Dans le même temps, il est important d'offrir une expérience utilisateur de qualité protéger l'intégrité du calendrier et de ses données. À cette fin, voici Voici quelques points à garder à l'esprit lorsque vous utilisez l'API:
- Insérer, mettre à jour et afficher des événements d'agenda Pour insérer, modifier et lire directement des événements à partir du fournisseur d'agenda, vous devez disposer des autorisations appropriées. Toutefois, si vous n'êtes pas en train de créer une application d'agenda complète ou un adaptateur de synchronisation, il n'est pas nécessaire de demander ces autorisations. À la place, vous pouvez utiliser des intents compatibles avec l'application Agenda d'Android pour transférer les opérations de lecture et d'écriture à cette application. Lorsque vous utilisez les intents, votre application redirige les utilisateurs vers l'application Agenda pour qu'ils effectuent l'opération souhaitée dans un formulaire prérempli. Une fois qu'il a terminé, il est redirigé vers votre application. En concevant votre application pour qu'elle effectue des opérations courantes via l'agenda, vous fournissez aux utilisateurs une interface utilisateur cohérente et robuste. Il s'agit de la l'approche recommandée. Pour en savoir plus, consultez la page Agenda Intents :
- Adaptateurs de synchronisation Un adaptateur de synchronisation synchronise les données du calendrier sur l'appareil d'un utilisateur avec un autre serveur ou une autre source de données. Dans les tables
CalendarContract.Calendars
etCalendarContract.Events
, des colonnes sont réservées aux adaptateurs de synchronisation. Le fournisseur et les applications ne doivent pas les modifier. En fait, ils ne sont pas visibles à moins qu'ils ne soient accessibles en tant qu'adaptateur de synchronisation. Pour en savoir plus sur adaptateurs de synchronisation, consultez la page Adaptateurs de synchronisation.
Autorisations utilisateur
Pour lire des données d'agenda, une application doit inclure l'autorisation READ_CALENDAR
dans son fichier manifeste. Il
doit inclure l'autorisation WRITE_CALENDAR
pour supprimer, insérer ou mettre à jour des données d'agenda:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android"...> <uses-sdk android:minSdkVersion="14" /> <uses-permission android:name="android.permission.READ_CALENDAR" /> <uses-permission android:name="android.permission.WRITE_CALENDAR" /> ... </manifest>
Tableau des agendas
La table CalendarContract.Calendars
contient des informations sur les calendriers individuels. Les éléments suivants :
Les colonnes d'agendas sont accessibles en écriture à la fois par une application et par un adaptateur de synchronisation.
Pour obtenir la liste complète des champs acceptés, consultez la documentation de référence CalendarContract.Calendars
.
Constante | Description |
---|---|
NAME |
Nom de l'agenda. |
CALENDAR_DISPLAY_NAME |
Nom de cet agenda présenté à l'utilisateur. |
VISIBLE |
Booléen indiquant si l'agenda est sélectionné pour être affiché. Une valeur de 0 indique que les événements associés à cet agenda ne doivent pas s'afficher. La valeur 1 indique que les événements associés à cet agenda doivent
être affichées. Cette valeur a une incidence sur la génération de lignes dans la table CalendarContract.Instances . |
SYNC_EVENTS |
Booléen indiquant si l'agenda doit être synchronisé et si ses événements doivent être stockés sur l'appareil. Une valeur de 0 indique de ne pas synchroniser cet agenda ni de ne pas stocker ses événements sur l'appareil. La valeur 1 indique que les événements de synchronisation de cet agenda et stocker ses événements sur l'appareil. |
Inclure un type de compte pour toutes les opérations
Si vous effectuez une requête sur un Calendars.ACCOUNT_NAME
, vous devez également inclure
Calendars.ACCOUNT_TYPE
dans la sélection. En effet, un compte donné
considéré comme unique compte tenu à la fois de son ACCOUNT_NAME
et de
ACCOUNT_TYPE
ACCOUNT_TYPE
est la chaîne correspondant à l'authentificateur de compte utilisé lors de l'enregistrement du compte auprès de AccountManager
. Il existe également un type de compte
appelé ACCOUNT_TYPE_LOCAL
pour
agendas non associés au compte d'un appareil.
ACCOUNT_TYPE_LOCAL
comptes ne reçoivent pas
synchronisées.
Interroger un agenda
Voici un exemple montrant comment récupérer les agendas appartenant à
utilisateur. Par souci de simplicité, dans cet exemple, l'opération de requête est présentée dans la
thread d'interface utilisateur ("thread principal"). En pratique, cela doit être effectué dans un thread asynchrone plutôt que sur le thread principal. Pour plus d'informations, consultez
Chargeurs : Si vous ne lisez pas seulement les données, mais que vous les modifiez, consultez AsyncQueryHandler
.
Kotlin
// Projection array. Creating indices for this array instead of doing // dynamic lookups improves performance. private val EVENT_PROJECTION: Array<String> = arrayOf( CalendarContract.Calendars._ID, // 0 CalendarContract.Calendars.ACCOUNT_NAME, // 1 CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, // 2 CalendarContract.Calendars.OWNER_ACCOUNT // 3 ) // The indices for the projection array above. private const val PROJECTION_ID_INDEX: Int = 0 private const val PROJECTION_ACCOUNT_NAME_INDEX: Int = 1 private const val PROJECTION_DISPLAY_NAME_INDEX: Int = 2 private const val PROJECTION_OWNER_ACCOUNT_INDEX: Int = 3
Java
// Projection array. Creating indices for this array instead of doing // dynamic lookups improves performance. public static final String[] EVENT_PROJECTION = new String[] { Calendars._ID, // 0 Calendars.ACCOUNT_NAME, // 1 Calendars.CALENDAR_DISPLAY_NAME, // 2 Calendars.OWNER_ACCOUNT // 3 }; // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_ACCOUNT_NAME_INDEX = 1; private static final int PROJECTION_DISPLAY_NAME_INDEX = 2; private static final int PROJECTION_OWNER_ACCOUNT_INDEX = 3;
Dans la partie suivante de l'exemple, vous allez construire votre requête. La sélection spécifie les critères de la requête. Dans cet exemple, la requête recherche
agendas associés au ACCOUNT_NAME
"hera@example.com", l'ACCOUNT_TYPE
"com.example" et l'élément OWNER_ACCOUNT
"hera@example.com". Si vous voulez voir tous les agendas d'un utilisateur
a consulté, et pas seulement les agendas appartenant à l'utilisateur, omettez OWNER_ACCOUNT
.
La requête renvoie un Cursor
que vous pouvez utiliser pour balayer l'ensemble de résultats renvoyé par la base de données
requête. Pour en savoir plus sur l'utilisation des requêtes dans les fournisseurs de contenu, consultez la section Fournisseurs de contenu.
Kotlin
// Run query val uri: Uri = CalendarContract.Calendars.CONTENT_URI val selection: String = "((${CalendarContract.Calendars.ACCOUNT_NAME} = ?) AND (" + "${CalendarContract.Calendars.ACCOUNT_TYPE} = ?) AND (" + "${CalendarContract.Calendars.OWNER_ACCOUNT} = ?))" val selectionArgs: Array<String> = arrayOf("hera@example.com", "com.example", "hera@example.com") val cur: Cursor = contentResolver.query(uri, EVENT_PROJECTION, selection, selectionArgs, null)
Java
// Run query Cursor cur = null; ContentResolver cr = getContentResolver(); Uri uri = Calendars.CONTENT_URI; String selection = "((" + Calendars.ACCOUNT_NAME + " = ?) AND (" + Calendars.ACCOUNT_TYPE + " = ?) AND (" + Calendars.OWNER_ACCOUNT + " = ?))"; String[] selectionArgs = new String[] {"hera@example.com", "com.example", "hera@example.com"}; // Submit the query and get a Cursor object back. cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);
La section suivante utilise le curseur pour parcourir l'ensemble de résultats. Elle utilise le constantes configurées au début de l'exemple pour renvoyer les valeurs pour chaque champ.
Kotlin
// Use the cursor to step through the returned records while (cur.moveToNext()) { // Get the field values val calID: Long = cur.getLong(PROJECTION_ID_INDEX) val displayName: String = cur.getString(PROJECTION_DISPLAY_NAME_INDEX) val accountName: String = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX) val ownerName: String = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX) // Do something with the values... }
Java
// Use the cursor to step through the returned records while (cur.moveToNext()) { long calID = 0; String displayName = null; String accountName = null; String ownerName = null; // Get the field values calID = cur.getLong(PROJECTION_ID_INDEX); displayName = cur.getString(PROJECTION_DISPLAY_NAME_INDEX); accountName = cur.getString(PROJECTION_ACCOUNT_NAME_INDEX); ownerName = cur.getString(PROJECTION_OWNER_ACCOUNT_INDEX); // Do something with the values... ... }
Modifier un agenda
Pour mettre à jour un agenda, vous pouvez fournir l'_ID
de l'agenda en tant qu'ID ajouté à
l'URI
(withAppendedId()
)
ou comme premier élément de sélection. La sélection
doit commencer par "_id=?"
, et le premier
selectionArg
doit être la _ID
de l'agenda.
Vous pouvez également effectuer des mises à jour en encodant l'ID dans l'URI. Cet exemple modifie le nom à afficher d'un agenda à l'aide de l'approche (withAppendedId()
) :
Kotlin
const val DEBUG_TAG: String = "MyActivity" ... val calID: Long = 2 val values = ContentValues().apply { // The new display name for the calendar put(CalendarContract.Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar") } val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Calendars.CONTENT_URI, calID) val rows: Int = contentResolver.update(updateUri, values, null, null) Log.i(DEBUG_TAG, "Rows updated: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long calID = 2; ContentValues values = new ContentValues(); // The new display name for the calendar values.put(Calendars.CALENDAR_DISPLAY_NAME, "Trevor's Calendar"); Uri updateUri = ContentUris.withAppendedId(Calendars.CONTENT_URI, calID); int rows = getContentResolver().update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows);
Insérer un agenda
Les agendas sont conçus pour être principalement gérés par un adaptateur de synchronisation. Vous pouvez donc
doit uniquement insérer les nouveaux agendas comme adaptateur de synchronisation. Dans la plupart des cas,
applications ne peuvent apporter que des modifications superficielles aux agendas, comme changer le nom d'affichage. Si
une application doit créer un agenda local, elle peut le faire
l'insertion d'agenda en tant qu'adaptateur de synchronisation, avec un ACCOUNT_TYPE
défini sur ACCOUNT_TYPE_LOCAL
.
ACCOUNT_TYPE_LOCAL
est un type de compte spécial pour les agendas
associées au compte d'un appareil. Les agendas de ce type ne sont pas synchronisés avec un serveur. Pour en savoir plus sur les adaptateurs de synchronisation, consultez la section Adaptateurs de synchronisation.
Tableau des événements
Le tableau CalendarContract.Events
contient des informations sur les événements individuels. Pour ajouter, mettre à jour ou supprimer des événements, une application doit
inclut l'autorisation WRITE_CALENDAR
dans ses
fichier manifeste.
Les colonnes "Événements" suivantes peuvent être écrites à la fois par une application et un adaptateur de synchronisation. Pour obtenir la liste complète des champs acceptés, consultez la documentation de référence CalendarContract.Events
.
Constante | Description |
---|---|
CALENDAR_ID |
_ID de l'agenda auquel l'événement appartient. |
ORGANIZER |
Adresse e-mail de l'organisateur (propriétaire) de l'événement. |
TITLE |
Titre de l'événement. |
EVENT_LOCATION |
Lieu de l'événement. |
DESCRIPTION |
Description de l'événement. |
DTSTART |
Heure de début de l'événement en millisecondes UTC depuis l'epoch. |
DTEND |
Heure de fin de l'événement en millisecondes UTC depuis l'epoch. |
EVENT_TIMEZONE |
Fuseau horaire de l'événement. |
EVENT_END_TIMEZONE |
Fuseau horaire de l'heure de fin de l'événement. |
DURATION |
Durée de l'événement au format RFC 5545.
Par exemple, une valeur de "PT1H" indique que l'événement doit durer une heure, et une valeur de "P2W" indique une durée de deux semaines. |
ALL_DAY |
Une valeur de 1 indique que cet événement occupe toute la journée, comme défini par le fuseau horaire local. Une valeur de 0 indique qu'il s'agit d'un événement standard susceptible de commencer et se terminent à tout moment de la journée. |
RRULE |
Règle de récurrence pour le format de l'événement. Pour
Exemple : "FREQ=WEEKLY;COUNT=10;WKST=SU" . Pour en savoir plus, cliquez ici. |
RDATE |
Dates de récurrence de l'événement.
Vous utilisez généralement RDATE
conjointement avec RRULE
pour définir un ensemble agrégé
qui se répètent. Pour en savoir plus, consultez la spécification RFC5545. |
AVAILABILITY |
Si cet événement est considéré comme un temps occupé ou s'il s'agit de temps libre qui peut être à venir. |
GUESTS_CAN_MODIFY |
Indique si les invités peuvent modifier l'événement. |
GUESTS_CAN_INVITE_OTHERS |
Indique si les invités peuvent inviter d'autres personnes. |
GUESTS_CAN_SEE_GUESTS |
Indique si les invités peuvent voir la liste des participants. |
Ajout d'événements
Lorsque votre application insère un nouvel événement, nous vous recommandons d'utiliser un
Intent INSERT
, comme décrit dans la section Utiliser un intent pour insérer un événement. Toutefois, si nécessaire, vous pouvez insérer des événements directement. Cette section explique comment procéder.
Voici les règles à respecter pour insérer un événement :
- Vous devez inclure
CALENDAR_ID
etDTSTART
. - Vous devez inclure un
EVENT_TIMEZONE
. Pour obtenir la liste des ID de fuseau horaire installés du système, utilisezgetAvailableIDs()
. Notez que cette règle ne s'applique pas si vous insérez un événement via l'intentINSERT
, décrit dans Utiliser un intent pour insérer un événement. Dans ce cas, un fuseau horaire par défaut est fourni. - Pour les événements non récurrents, vous devez inclure
DTEND
. - Pour les événements périodiques, vous devez inclure un
DURATION
en plus de l'élémentRRULE
ouRDATE
. Notez que cette règle ne s'applique pas si vous insérez un événement via l'intentINSERT
, décrit dans la section Utiliser un intent pour insérer un événement, dans ce vous pouvez utiliser unRRULE
conjointement avecDTSTART
etDTEND
, et l'application Agenda la convertit automatiquement en durée.
Voici un exemple d'insertion d'un événement. Pour plus de simplicité, cette opération est effectuée dans le thread d'UI. En pratique, les insertions et les mises à jour doivent être effectuées
asynchrone pour déplacer l'action dans un thread d'arrière-plan. Pour en savoir plus, consultez AsyncQueryHandler
.
Kotlin
val calID: Long = 3 val startMillis: Long = Calendar.getInstance().run { set(2012, 9, 14, 7, 30) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2012, 9, 14, 8, 45) timeInMillis } ... val values = ContentValues().apply { put(CalendarContract.Events.DTSTART, startMillis) put(CalendarContract.Events.DTEND, endMillis) put(CalendarContract.Events.TITLE, "Jazzercise") put(CalendarContract.Events.DESCRIPTION, "Group workout") put(CalendarContract.Events.CALENDAR_ID, calID) put(CalendarContract.Events.EVENT_TIMEZONE, "America/Los_Angeles") } val uri: Uri = contentResolver.insert(CalendarContract.Events.CONTENT_URI, values) // get the event ID that is the last element in the Uri val eventID: Long = uri.lastPathSegment.toLong() // // ... do something with event ID // //
Java
long calID = 3; long startMillis = 0; long endMillis = 0; Calendar beginTime = Calendar.getInstance(); beginTime.set(2012, 9, 14, 7, 30); startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2012, 9, 14, 8, 45); endMillis = endTime.getTimeInMillis(); ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Events.DTSTART, startMillis); values.put(Events.DTEND, endMillis); values.put(Events.TITLE, "Jazzercise"); values.put(Events.DESCRIPTION, "Group workout"); values.put(Events.CALENDAR_ID, calID); values.put(Events.EVENT_TIMEZONE, "America/Los_Angeles"); Uri uri = cr.insert(Events.CONTENT_URI, values); // get the event ID that is the last element in the Uri long eventID = Long.parseLong(uri.getLastPathSegment()); // // ... do something with event ID // //
Remarque : Découvrez comment cet exemple capture l'ID de l'événement après sa création. Il s'agit du moyen le plus simple d'obtenir un ID d'événement. Souvent l'ID de l'événement est nécessaire pour effectuer d'autres opérations d'agenda (par exemple, pour ajouter les participants ou les rappels d'un événement.
Événements de mise à jour
Lorsque votre application souhaite autoriser l'utilisateur à modifier un événement, nous vous recommandons
que vous utilisez un intent EDIT
,
décrites dans Utiliser un intent pour modifier un événement.
Toutefois, si nécessaire, vous pouvez modifier les événements directement. Pour mettre à jour un événement, vous pouvez fournir le _ID
de l'événement en tant qu'ID ajouté à l'URI (withAppendedId()
) ou en tant que premier élément de sélection.
La sélection doit commencer par "_id=?"
, et le premier
selectionArg
doit être le _ID
de l'événement. Vous pouvez également effectuer des mises à jour à l'aide d'une sélection sans ID. Voici un exemple de mise à jour d'un événement. Elle modifie le titre de l'événement à l'aide de la méthode
withAppendedId()
approche:
Kotlin
val DEBUG_TAG = "MyActivity" ... val eventID: Long = 188 ... val values = ContentValues().apply { // The new title for the event put(CalendarContract.Events.TITLE, "Kickboxing") } val updateUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val rows: Int = contentResolver.update(updateUri, values, null, null) Log.i(DEBUG_TAG, "Rows updated: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long eventID = 188; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); Uri updateUri = null; // The new title for the event values.put(Events.TITLE, "Kickboxing"); updateUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = cr.update(updateUri, values, null, null); Log.i(DEBUG_TAG, "Rows updated: " + rows);
Supprimer des événements
Vous pouvez supprimer un événement soit en ajoutant son identifiant _ID
à l'URI, soit en utilisant
la sélection standard. Si vous ajoutez un ID, vous ne pourrez pas effectuer de sélection en même temps.
Il existe deux versions de la fonction de suppression: en tant qu'application et en tant qu'adaptateur de synchronisation. Une
application delete définit la colonne deleted sur 1. Cet indicateur
qui indique
l'adaptateur de synchronisation que la ligne a été supprimée et que cette suppression doit être
propagées au serveur. La suppression d'un adaptateur de synchronisation entraîne la suppression de l'événement dans
base de données ainsi que
toutes ses données associées. Voici un exemple d'application
Supprimer un événement via son _ID
:
Kotlin
val DEBUG_TAG = "MyActivity" ... val eventID: Long = 201 ... val deleteUri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val rows: Int = contentResolver.delete(deleteUri, null, null) Log.i(DEBUG_TAG, "Rows deleted: $rows")
Java
private static final String DEBUG_TAG = "MyActivity"; ... long eventID = 201; ... ContentResolver cr = getContentResolver(); Uri deleteUri = null; deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); int rows = cr.delete(deleteUri, null, null); Log.i(DEBUG_TAG, "Rows deleted: " + rows);
Tableau des participants
Chaque ligne du tableau CalendarContract.Attendees
représente un participant ou un invité à un événement. Appel en cours
query()
renvoie la liste des participants à la
avec le EVENT_ID
donné.
Ce/Cet/Cette EVENT_ID
doit correspondre au _ID
d'un événement particulier.
Le tableau suivant liste les champs enregistrables. Lorsque vous insérez un participant, vous devez les inclure tous, à l'exception de ATTENDEE_NAME
.
Constante | Description |
---|---|
EVENT_ID |
ID de l'événement. |
ATTENDEE_NAME |
Nom du participant. |
ATTENDEE_EMAIL |
Adresse e-mail du participant. |
ATTENDEE_RELATIONSHIP |
Relation de l'utilisateur avec l'événement. Au choix: |
ATTENDEE_TYPE |
Type de participant. Au choix: |
ATTENDEE_STATUS |
État de participation de l'utilisateur. L'un des éléments suivants : |
Ajouter des participants
Voici un exemple d'ajout d'un seul participant à un événement. Notez que
EVENT_ID
est obligatoire:
Kotlin
val eventID: Long = 202 ... val values = ContentValues().apply { put(CalendarContract.Attendees.ATTENDEE_NAME, "Trevor") put(CalendarContract.Attendees.ATTENDEE_EMAIL, "trevor@example.com") put( CalendarContract.Attendees.ATTENDEE_RELATIONSHIP, CalendarContract.Attendees.RELATIONSHIP_ATTENDEE ) put(CalendarContract.Attendees.ATTENDEE_TYPE, CalendarContract.Attendees.TYPE_OPTIONAL) put( CalendarContract.Attendees.ATTENDEE_STATUS, CalendarContract.Attendees.ATTENDEE_STATUS_INVITED ) put(CalendarContract.Attendees.EVENT_ID, eventID) } val uri: Uri = contentResolver.insert(CalendarContract.Attendees.CONTENT_URI, values)
Java
long eventID = 202; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Attendees.ATTENDEE_NAME, "Trevor"); values.put(Attendees.ATTENDEE_EMAIL, "trevor@example.com"); values.put(Attendees.ATTENDEE_RELATIONSHIP, Attendees.RELATIONSHIP_ATTENDEE); values.put(Attendees.ATTENDEE_TYPE, Attendees.TYPE_OPTIONAL); values.put(Attendees.ATTENDEE_STATUS, Attendees.ATTENDEE_STATUS_INVITED); values.put(Attendees.EVENT_ID, eventID); Uri uri = cr.insert(Attendees.CONTENT_URI, values);
Tableau des rappels
Chaque ligne du tableau CalendarContract.Reminders
représente un seul rappel pour un événement. Appel en cours
query()
renvoie une liste de rappels pour l'événement
avec l'événement
EVENT_ID
Le tableau suivant répertorie les champs accessibles en écriture pour les rappels. Ils doivent tous
être inclus lorsque vous insérez un nouveau rappel. Notez que les adaptateurs de synchronisation spécifient
types de rappels acceptés dans le tableau CalendarContract.Calendars
. Voir
ALLOWED_REMINDERS
pour en savoir plus.
Constante | Description |
---|---|
EVENT_ID |
ID de l'événement. |
MINUTES |
Minutes précédant l'événement pendant lesquelles le rappel doit se déclencher. |
METHOD |
Méthode d'alarme, telle que définie sur le serveur. Au choix: |
Ajoutez des rappels
Cet exemple ajoute un rappel à un événement. Le rappel se déclenche 15 jours quelques minutes avant l'événement.
Kotlin
val eventID: Long = 221 ... val values = ContentValues().apply { put(CalendarContract.Reminders.MINUTES, 15) put(CalendarContract.Reminders.EVENT_ID, eventID) put(CalendarContract.Reminders.METHOD, CalendarContract.Reminders.METHOD_ALERT) } val uri: Uri = contentResolver.insert(CalendarContract.Reminders.CONTENT_URI, values)
Java
long eventID = 221; ... ContentResolver cr = getContentResolver(); ContentValues values = new ContentValues(); values.put(Reminders.MINUTES, 15); values.put(Reminders.EVENT_ID, eventID); values.put(Reminders.METHOD, Reminders.METHOD_ALERT); Uri uri = cr.insert(Reminders.CONTENT_URI, values);
Tableau des instances
La
La table CalendarContract.Instances
contient
les heures de début et de fin des occurrences d'un événement. Chaque ligne de ce tableau
représente une seule occurrence d'événement. Le tableau des instances n'est pas accessible en écriture et ne permet que d'interroger les occurrences d'événements.
Le tableau suivant liste certains des champs sur lesquels vous pouvez interroger une instance. Remarque
ce fuseau horaire est défini par
KEY_TIMEZONE_TYPE
et
KEY_TIMEZONE_INSTANCES
Constante | Description |
---|---|
BEGIN |
Heure de début de l'instance, en millisecondes UTC. |
END |
Heure de fin de l'instance, en millisecondes UTC. |
END_DAY |
Jour de fin julien de l'instance, par rapport au fuseau horaire du calendrier. |
END_MINUTE |
La minute de fin de l'instance, mesurée à partir de minuit dans le Fuseau horaire de l'agenda. |
EVENT_ID |
_ID de l'événement pour cette instance. |
START_DAY |
Jour julien de début de l'instance, par rapport au fuseau horaire du calendrier. |
START_MINUTE |
Minute de début de l'instance mesurée à partir de minuit, par rapport au fuseau horaire du calendrier. |
Interroger la table des instances
Pour interroger la table des instances, vous devez spécifier une période pour la requête
dans l'URI. Dans cet exemple, CalendarContract.Instances
obtient l'accès au champ TITLE
via son
l'implémentation de l'interface CalendarContract.EventsColumns
.
En d'autres termes, TITLE
est renvoyé via une vue de base de données, et non en interrogeant le tableau CalendarContract.Instances
brut.
Kotlin
const val DEBUG_TAG: String = "MyActivity" val INSTANCE_PROJECTION: Array<String> = arrayOf( CalendarContract.Instances.EVENT_ID, // 0 CalendarContract.Instances.BEGIN, // 1 CalendarContract.Instances.TITLE // 2 ) // The indices for the projection array above. const val PROJECTION_ID_INDEX: Int = 0 const val PROJECTION_BEGIN_INDEX: Int = 1 const val PROJECTION_TITLE_INDEX: Int = 2 // Specify the date range you want to search for recurring // event instances val startMillis: Long = Calendar.getInstance().run { set(2011, 9, 23, 8, 0) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2011, 10, 24, 8, 0) timeInMillis } // The ID of the recurring event whose instances you are searching // for in the Instances table val selection: String = "${CalendarContract.Instances.EVENT_ID} = ?" val selectionArgs: Array<String> = arrayOf("207") // Construct the query with the desired date range. val builder: Uri.Builder = CalendarContract.Instances.CONTENT_URI.buildUpon() ContentUris.appendId(builder, startMillis) ContentUris.appendId(builder, endMillis) // Submit the query val cur: Cursor = contentResolver.query( builder.build(), INSTANCE_PROJECTION, selection, selectionArgs, null ) while (cur.moveToNext()) { // Get the field values val eventID: Long = cur.getLong(PROJECTION_ID_INDEX) val beginVal: Long = cur.getLong(PROJECTION_BEGIN_INDEX) val title: String = cur.getString(PROJECTION_TITLE_INDEX) // Do something with the values. Log.i(DEBUG_TAG, "Event: $title") val calendar = Calendar.getInstance().apply { timeInMillis = beginVal } val formatter = SimpleDateFormat("MM/dd/yyyy") Log.i(DEBUG_TAG, "Date: ${formatter.format(calendar.time)}") }
Java
private static final String DEBUG_TAG = "MyActivity"; public static final String[] INSTANCE_PROJECTION = new String[] { Instances.EVENT_ID, // 0 Instances.BEGIN, // 1 Instances.TITLE // 2 }; // The indices for the projection array above. private static final int PROJECTION_ID_INDEX = 0; private static final int PROJECTION_BEGIN_INDEX = 1; private static final int PROJECTION_TITLE_INDEX = 2; ... // Specify the date range you want to search for recurring // event instances Calendar beginTime = Calendar.getInstance(); beginTime.set(2011, 9, 23, 8, 0); long startMillis = beginTime.getTimeInMillis(); Calendar endTime = Calendar.getInstance(); endTime.set(2011, 10, 24, 8, 0); long endMillis = endTime.getTimeInMillis(); Cursor cur = null; ContentResolver cr = getContentResolver(); // The ID of the recurring event whose instances you are searching // for in the Instances table String selection = Instances.EVENT_ID + " = ?"; String[] selectionArgs = new String[] {"207"}; // Construct the query with the desired date range. Uri.Builder builder = Instances.CONTENT_URI.buildUpon(); ContentUris.appendId(builder, startMillis); ContentUris.appendId(builder, endMillis); // Submit the query cur = cr.query(builder.build(), INSTANCE_PROJECTION, selection, selectionArgs, null); while (cur.moveToNext()) { String title = null; long eventID = 0; long beginVal = 0; // Get the field values eventID = cur.getLong(PROJECTION_ID_INDEX); beginVal = cur.getLong(PROJECTION_BEGIN_INDEX); title = cur.getString(PROJECTION_TITLE_INDEX); // Do something with the values. Log.i(DEBUG_TAG, "Event: " + title); Calendar calendar = Calendar.getInstance(); calendar.setTimeInMillis(beginVal); DateFormat formatter = new SimpleDateFormat("MM/dd/yyyy"); Log.i(DEBUG_TAG, "Date: " + formatter.format(calendar.getTime())); } }
Intents Agenda
Votre application n'a pas besoin d'autorisations pour lire et écrire des données d'agenda. À la place, il peut utiliser des intents compatibles avec l'application Agenda d'Android pour transférer les opérations de lecture et d'écriture à cette application. Le tableau suivant répertorie les intents compatibles avec le fournisseur d'agenda:
Action | URI | Description | Bonus |
---|---|---|---|
VIEW |
CalendarContract.CONTENT_URI
Pour obtenir un exemple d'utilisation de cet intent, consultez la section Utiliser des intents pour afficher des données d'agenda.
|
Ouvrir l'agenda à l'heure spécifiée par <ms_since_epoch> . |
Aucun. |
Events.CONTENT_URI .
Pour obtenir un exemple d'utilisation de cet intent, consultez la section Utiliser des intents pour afficher des données d'agenda.
|
Afficher l'événement spécifié par <event_id> . |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
|
EDIT |
Events.CONTENT_URI
Pour obtenir un exemple d'utilisation de cet intent, consultez la section Utiliser un intent pour modifier un événement.
|
Modifiez l'événement spécifié par <event_id> . |
CalendarContract.EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_END_TIME |
EDIT INSERT |
Events.CONTENT_URI
Pour obtenir un exemple d'utilisation de cet intent, consultez la section Utiliser un intent pour insérer un événement.
|
Créez un événement. | Tout élément supplémentaire listé dans le tableau ci-dessous. |
Le tableau suivant répertorie les extras d'intent compatibles avec le fournisseur de calendrier :
Intent Extra | Description |
---|---|
Events.TITLE |
Nom de l'événement. |
CalendarContract.EXTRA_EVENT_BEGIN_TIME |
Heure de début de l'événement en millisecondes à partir de l'epoch. |
CalendarContract.EXTRA_EVENT_END_TIME |
Heure de fin de l'événement en millisecondes depuis l'epoch. |
CalendarContract.EXTRA_EVENT_ALL_DAY |
Valeur booléenne indiquant qu'un événement dure toute la journée. La valeur peut être true ou false . |
Events.EVENT_LOCATION |
Lieu de l'événement. |
Events.DESCRIPTION |
Description de l'événement. |
Intent.EXTRA_EMAIL |
Adresses e-mail des personnes à inviter sous forme de liste d'éléments séparés par une virgule. |
Events.RRULE |
Règle de récurrence de l'événement. |
Events.ACCESS_LEVEL |
Indique si l'événement est privé ou public. |
Events.AVAILABILITY |
Indique si cet événement est considéré comme un temps occupé ou s'il s'agit d'un temps libre sur lequel vous pouvez planifier une activité. |
Les sections suivantes décrivent comment utiliser ces intents.
Utiliser un intent pour insérer un événement
Utiliser l'intent INSERT
permet à votre application de transmettre la tâche d'insertion d'événements à Agenda.
Avec cette approche, il n'est même pas nécessaire que votre application dispose de l'autorisation WRITE_CALENDAR
dans son fichier manifeste.
Lorsque les utilisateurs exécutent une application qui utilise cette approche, l'application envoie
à l'agenda pour finaliser l'ajout de l'événement. L'intent INSERT
utilise des champs supplémentaires pour préremplir un formulaire avec les détails de l'événement dans l'agenda. Les utilisateurs peuvent
puis annulez l'événement, modifiez le formulaire si nécessaire ou enregistrez l'événement
agendas.
Voici un extrait de code qui planifie un événement le 19 janvier 2012, qui se déroule de 7h30 à 8h30. Notez les points suivants concernant cet extrait de code :
- Il spécifie
Events.CONTENT_URI
que l'URI. - Il utilise les champs supplémentaires
CalendarContract.EXTRA_EVENT_BEGIN_TIME
etCalendarContract.EXTRA_EVENT_END_TIME
pour préremplir le formulaire avec l'heure de l'événement. Les valeurs pour ces heures doivent être exprimées en millisecondes UTC de l'époque. - Elle utilise le
Intent.EXTRA_EMAIL
champ supplémentaire pour fournir une liste d'invités séparés par une virgule, spécifiés par l'adresse e-mail.
Kotlin
val startMillis: Long = Calendar.getInstance().run { set(2012, 0, 19, 7, 30) timeInMillis } val endMillis: Long = Calendar.getInstance().run { set(2012, 0, 19, 8, 30) timeInMillis } val intent = Intent(Intent.ACTION_INSERT) .setData(CalendarContract.Events.CONTENT_URI) .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, startMillis) .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endMillis) .putExtra(CalendarContract.Events.TITLE, "Yoga") .putExtra(CalendarContract.Events.DESCRIPTION, "Group class") .putExtra(CalendarContract.Events.EVENT_LOCATION, "The gym") .putExtra(CalendarContract.Events.AVAILABILITY, CalendarContract.Events.AVAILABILITY_BUSY) .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com") startActivity(intent)
Java
Calendar beginTime = Calendar.getInstance(); beginTime.set(2012, 0, 19, 7, 30); Calendar endTime = Calendar.getInstance(); endTime.set(2012, 0, 19, 8, 30); Intent intent = new Intent(Intent.ACTION_INSERT) .setData(Events.CONTENT_URI) .putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis()) .putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis()) .putExtra(Events.TITLE, "Yoga") .putExtra(Events.DESCRIPTION, "Group class") .putExtra(Events.EVENT_LOCATION, "The gym") .putExtra(Events.AVAILABILITY, Events.AVAILABILITY_BUSY) .putExtra(Intent.EXTRA_EMAIL, "rowan@example.com,trevor@example.com"); startActivity(intent);
Utiliser un intent pour modifier un événement
Vous pouvez mettre à jour un événement directement, comme décrit dans Mettre à jour des événements. Toutefois, l'utilisation de l'intent EDIT
permet à une application qui n'est pas autorisée à transférer la modification d'événements à l'application Agenda.
Lorsque les utilisateurs ont terminé de modifier leur événement dans Agenda, ils sont redirigés vers l'application d'origine.
Voici un exemple d'intent qui définit une nouvelle titre d'un événement spécifié et permet aux utilisateurs de le modifier dans l'agenda.
Kotlin
val eventID: Long = 208 val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val intent = Intent(Intent.ACTION_EDIT) .setData(uri) .putExtra(CalendarContract.Events.TITLE, "My New Title") startActivity(intent)
Java
long eventID = 208; Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); Intent intent = new Intent(Intent.ACTION_EDIT) .setData(uri) .putExtra(Events.TITLE, "My New Title"); startActivity(intent);
Utiliser des intents pour afficher des données d'agenda
Le fournisseur de calendrier propose deux méthodes différentes pour utiliser l'intent VIEW
:
- Pour ouvrir l'agenda à une date spécifique.
- Pour afficher un événement :
Voici un exemple illustrant comment ouvrir l'agenda à une date spécifique :
Kotlin
val startMillis: Long ... val builder: Uri.Builder = CalendarContract.CONTENT_URI.buildUpon() .appendPath("time") ContentUris.appendId(builder, startMillis) val intent = Intent(Intent.ACTION_VIEW) .setData(builder.build()) startActivity(intent)
Java
// A date-time specified in milliseconds since the epoch. long startMillis; ... Uri.Builder builder = CalendarContract.CONTENT_URI.buildUpon(); builder.appendPath("time"); ContentUris.appendId(builder, startMillis); Intent intent = new Intent(Intent.ACTION_VIEW) .setData(builder.build()); startActivity(intent);
Voici un exemple montrant comment ouvrir un événement pour le visualiser:
Kotlin
val eventID: Long = 208 ... val uri: Uri = ContentUris.withAppendedId(CalendarContract.Events.CONTENT_URI, eventID) val intent = Intent(Intent.ACTION_VIEW).setData(uri) startActivity(intent)
Java
long eventID = 208; ... Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID); Intent intent = new Intent(Intent.ACTION_VIEW) .setData(uri); startActivity(intent);
Adaptateurs de synchronisation
Il n'existe que de légères différences dans la façon dont une application et un adaptateur de synchronisation accèdent au fournisseur de calendrier :
- Un adaptateur de synchronisation doit spécifier qu'il s'agit d'un adaptateur de synchronisation en définissant
CALLER_IS_SYNCADAPTER
surtrue
. - Un adaptateur de synchronisation doit fournir les éléments
ACCOUNT_NAME
etACCOUNT_TYPE
en tant que paramètres de requête dans l'URI. - Un adaptateur de synchronisation dispose d'un accès en écriture à plus de colonnes qu'une application ou un widget.
Par exemple, une application ne peut modifier que quelques caractéristiques d'un agenda, comme son nom, son nom à afficher, son paramètre de visibilité et si l'agenda est synchronisé. À titre de comparaison, un adaptateur de synchronisation peut accéder non seulement à ces colonnes, mais à de nombreuses autres, telles que la couleur de l'agenda, le fuseau horaire, le niveau d'accès, l'emplacement, etc.
Toutefois, un adaptateur de synchronisation est limité aux
ACCOUNT_NAME
etACCOUNT_TYPE
qu'il spécifie.
Voici une méthode d'assistance que vous pouvez utiliser pour renvoyer un URI à utiliser avec un adaptateur de synchronisation :
Kotlin
fun asSyncAdapter(uri: Uri, account: String, accountType: String): Uri { return uri.buildUpon() .appendQueryParameter(CalendarContract.CALLER_IS_SYNCADAPTER, "true") .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_NAME, account) .appendQueryParameter(CalendarContract.Calendars.ACCOUNT_TYPE, accountType).build() }
Java
static Uri asSyncAdapter(Uri uri, String account, String accountType) { return uri.buildUpon() .appendQueryParameter(android.provider.CalendarContract.CALLER_IS_SYNCADAPTER,"true") .appendQueryParameter(Calendars.ACCOUNT_NAME, account) .appendQueryParameter(Calendars.ACCOUNT_TYPE, accountType).build(); }