lightbulb_outline Help shape the future of the Google Play Console, Android Studio, and Firebase. Start survey

Provedor de agenda

O Provedor de agenda é um repositório para eventos da agenda do usuário. A Calendar Provider API permite consultar, inserir, atualizar e excluir operações em agendas, eventos, participantes, lembretes etc.

A Calender Provider API pode ser usada por aplicativos e adaptadores de sincronização. As regras variam conforme o tipo de programa que realiza as chamadas. Este documento se concentra principalmente no uso da API do Provedor de Agenda como um aplicativo. Veja uma discussão sobre as diferenças entre os adaptadores de sincronização em Adaptadores de sincronização.

Normalmente, para ler ou programar dados da agenda, o manifesto de um aplicativo deve conter as permissões adequadas descritas em Permissões do usuário. Para facilitar a realização de operações comuns, o Provedor de Agenda fornece um conjunto de intents conforme descrito em Intents do Agenda. Esses intents levam os usuários ao aplicativo Agenda para inserir, exibir e editar eventos. O usuário interage com o aplicativo Agenda e, em seguida, retorna ao aplicativo original. Assim, o aplicativo não precisa solicitar permissões nem fornecer uma interface do usuário para exibir ou criar eventos.

Conceitos básicos

Os provedores de conteúdo armazenam dados e disponibilizam-nos para aplicativos. Os provedores de conteúdo oferecidos pela plataforma do Android (inclusive o Provedor de Agenda) normalmente expõem dados como um conjunto de tabelas baseadas em um modelo de banco de dados relacional, em que cada linha é um registro e cada coluna são dados de um tipo e significado específico. Por meio da Calender Provider API, aplicativos e adaptadores de sincronização podem obter acesso de leitura/gravação às tabelas do banco de dados que armazenam dados da agenda do usuário.

Todo provedor de conteúdo expõe um URI público (agrupado como um objeto Uri ) que identifica exclusivamente seu conjunto de dados. Um provedor de conteúdo que controla diversos conjuntos de dados (diversas tabelas) expõe uma URI separada para cada um. Todos os URIs de provedores começam com a string “content://”. Ela identifica os dados como controlados por um provedor de conteúdo. O Provedor de Agenda define constantes para as URIs de cada uma das classes (tabelas). Essas URIs têm o formato <class>.CONTENT_URI. Por exemplo, Events.CONTENT_URI.

A figura 1 exibe uma representação gráfica do modelo de dados do Provedor de Agenda. Ela ilustra as tabelas e os campos principais que as vinculam entre si.

Modelo de dados do Provedor de Agenda.

Imagem 1. Modelo de dados do Provedor de Agenda.

Cada usuário pode ter diversas agendas e diferentes agendas podem ser associadas a diferentes tipos de conta (Google Agenda, Exchange etc.).

O CalendarContract define o modelo de dados de informações relacionadas a eventos e agendas. Esses dados são armazenados em diversas tabelas, que são listadas a seguir.

Tabela (classe) Descrição

CalendarContract.Calendars

Essa tabela contém as informações específicas da agenda. Cada linha nessa tabela contém os detalhes de uma única agenda, como nome, cor, informações de sincronização etc.
CalendarContract.Events Essa tabela contém as informações específicas do evento. Cada linha nessa tabela tem as informações de um único evento — por exemplo, título do evento, local, horário de início, horário de término etc. O evento pode ocorrer uma vez ou diversas vezes. Participantes, lembretes e propriedades estendidas ficam armazenados em tabelas separadas. Cada um deles tem um EVENT_ID que referencia o _ID na tabela Eventos.
CalendarContract.Instances Essa tabela contém os horários de início e término de cada ocorrência de um evento. Cada linha nessa tabela representa uma única ocorrência do evento. Para eventos de ocorrência única, há um mapeamento 1:1 de instâncias para eventos. Para eventos recorrentes, diversas linhas correspondentes a diversas ocorrências daquele evento são geradas automaticamente.
CalendarContract.Attendees Essa tabela contém as informações dos participantes (convidados) do evento. Cada linha representa um único convidado de um evento. Ela especifica o tipo de convidado e a resposta quanto à participação do convidado no evento.
CalendarContract.Reminders Essa tabela contém os dados de alerta/notificação. Cada linha representa um único alerta de um evento. Um evento pode ter vários lembretes. O número máximo de lembretes por evento é especificado em MAX_REMINDERS, que é definido pelo adaptador de sincronização que detém a agenda em questão. Os lembretes são especificados em minutos antes do evento e têm um método que determina a forma de alertar o usuário.

A Calender Provider API é projetada para ser flexível e poderosa. Ao mesmo tempo, é importante fornecer uma boa experiência ao usuário final e proteger a integridade da agenda e seus dados. Para isso, eis alguns pontos a considerar ao usar a API:

  • Inserção, atualização e exibição de eventos da agenda. Para inserir, modificar e ler eventos diretamente do provedor de agenda, é necessário ter as permissões apropriadas. Contudo, se o aplicativo em criação não for um aplicativo de agenda totalmente desenvolvido nem um adaptador de sincronização, não será necessário solicitar essas permissões. Em vez disso, podem-se usar intents compatíveis com o aplicativo Agenda do Android para entregar operações de leitura e gravação a esse aplicativo. Ao usar os intents, o aplicativo envia usuários ao aplicativo Agenda para realizar a operação desejada em um formulário pré-preenchido. Após finalizarem a operação, eles serão direcionados de volta ao aplicativo. Ao projetar seu aplicativo para realizar operações comuns através do Agenda, os usuários têm uma experiência em uma interface do usuário robusta e consistente. Essa é a abordagem recomendada. Para obter mais informações, consulte Intents do Agenda.

  • Adaptadores de sincronização. Os adaptadores de sincronização sincronizam os dados da agenda em um dispositivo do usuário com outro servidor ou fonte de dados. Nas tabelas CalendarContract.Calendars e CalendarContract.Events, há colunas reservadas para os adaptadores de sincronização usarem. O provedor e os aplicativos não devem modificá-las. De fato, elas não são visíveis a menos que sejam acessadas como um adaptador de sincronização. Para obter mais informações sobre adaptadores de sincronização, consulte Adaptadores de sincronização.

Permissões do usuário

Para ler dados da agenda, o aplicativo deve conter a permissão READ_CALENDAR no arquivo de manifesto. Ele deve conter a permissão WRITE_CALENDAR para excluir, inserir ou atualizar dados da 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>

Tabela de agendas

A tabela CalendarContract.Calendars contém informações de agendas individuais. As colunas Agendas a seguir são graváveis tanto por aplicativos quanto por adaptadores de sincronização. Para obter uma lista completa de campos compatíveis, consulte a referência de CalendarContract.Calendars.

Constante Descrição
NAME O nome da agenda.
CALENDAR_DISPLAY_NAME O nome dessa agenda exibido ao usuário.
VISIBLE Um booleano que indica se a agenda foi selecionada para exibição. Um valor de 0 indica que eventos associados a essa agenda não devem ser exibidos. Um valor de 1 indica que eventos associados a essa agenda devem ser exibidos. Esse valor afeta a geração de linhas na tabela CalendarContract.Instances.
SYNC_EVENTS Booleano que indica se a agenda deve ser sincronizada e armazenar os eventos no dispositivo. Um valor de 0 indica a não sincronização dessa agenda e o não armazenamento dos eventos no dispositivo. Um valor de 1 indica a sincronização dos eventos dessa agenda e o armazenamento deles no dispositivo.

Consulta em uma agenda

A seguir, há um exemplo que mostra como obter as agendas de propriedade de determinado usuário. Para simplificar o exemplo, a operação de consulta é exibida no encadeamento da interface do usuário ("encadeamento principal"). Na prática, isso deve ser feito em um encadeamento assíncrono em vez de no encadeamento principal. Para ver mais discussões, consulte Carregadores. Se você não estiver somente lendo dados, mas modificando-os, consulte AsyncQueryHandler.

// 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;

Na próxima parte do exemplo, você construirá a consulta. A seleção especifica os critérios da consulta. Neste exemplo, a consulta busca agendas que tenham o ACCOUNT_NAME "sampleuser@google.com", o ACCOUNT_TYPE "com.google" e o OWNER_ACCOUNT "sampleuser@google.com". Para ver todas as agendas que um usuário tenha exibido, não somente as que ele tem, omita o OWNER_ACCOUNT. A consulta retorna um objeto Cursor que pode ser usado para cruzar o conjunto de resultados retornado pela consulta do banco de dados. Para ver mais informações sobre o uso de consultas em provedores de conteúdo, consulte Provedores de conteúdo.

// 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[] {"sampleuser@gmail.com", "com.google",
        "sampleuser@gmail.com"};
// Submit the query and get a Cursor object back.
cur = cr.query(uri, EVENT_PROJECTION, selection, selectionArgs, null);

Essa próxima seção usa o cursor para avançar pelo conjunto de resultados. Ele usa as constantes definidas no início do exemplo para retornar os valores de cada campo.

// 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...

   ...
}

Modificação de uma agenda

Para realizar uma atualização de uma agenda, é possível fornecer o _ID da agenda como um ID anexado ao URI (withAppendedId()) ou como o primeiro item da seleção. A seleção deve começar com "_id=?", e o primeiro selectionArg deve ser o _ID da agenda. Você ainda pode codificar o ID do URI para fazer atualizações. Esse exemplo altera o nome de exibição de uma agenda usando a abordagem (withAppendedId()) :

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);

Inserção de uma agenda

Agendas são projetadas para serem gerenciadas principalmente por um adaptador de sincronização, por isso, deve-se inserir novas agendas somente como um adaptador de sincronização. Para a maior parte, aplicativos só podem efetuar mudanças superficiais em agendas, como mudar o nome de exibição. Se um aplicativo precisa criar uma agenda local, pode fazê-lo realizando a inserção da agenda como um adaptador de sincronização usando um ACCOUNT_TYPE de ACCOUNT_TYPE_LOCAL. ACCOUNT_TYPE_LOCAL é um tipo de conta especial para agendas não associado a nenhuma conta do dispositivo. Agendas desse tipo não são sincronizadas com um servidor. Para ver discussões sobre adaptadores de sincronização, consulte Adaptadores de sincronização.

Tabela de eventos

A tabela CalendarContract.Events contém detalhes de eventos individuais. Para adicionar, atualizar ou excluir eventos, um aplicativo deve conter a permissão WRITE_CALENDAR no arquivo de manifesto.

As colunas de Eventos a seguir são graváveis tanto por um aplicativo quanto por um adaptador de sincronização. Para obter uma lista completa de campos compatíveis, consulte a referência de CalendarContract.Events.

Constante Descrição
CALENDAR_ID O _ID da agenda à qual pertence o evento.
ORGANIZER E-mail do organizador (proprietário) do evento.
TITLE Título do evento.
EVENT_LOCATION Local do evento.
DESCRIPTION Descrição do evento.
DTSTART Horário de início do evento em milissegundos em UTC desde a época.
DTEND Horário de término do evento em milissegundos em UTC desde a época.
EVENT_TIMEZONE Fuso horário do evento.
EVENT_END_TIMEZONE Fuso horário do horário de término do evento.
DURATION Duração do evento em formato RCF5545. Por exemplo: um valor de "PT1H" indica que o evento deve durar uma hora e um valor de "P2W" indica uma duração de 2 semanas.
ALL_DAY Um valor de 1 indica que esse evento dura o dia inteiro, como definido pelo fuso horário local. Um valor de 0 indica que é um evento comum que pode iniciar e terminar a qualquer momento durante um dia.
RRULE A regra de recorrência do formato do evento. Por exemplo, "FREQ=WEEKLY;COUNT=10;WKST=SU". Veja mais exemplos aqui.
RDATE As datas de recorrência do evento. Normalmente, usa-se RDATE em conjunto com RRULE para definir um conjunto agregado de ocorrências repetidas. Para ver mais discussões, consulte a Especificação RFC5545.
AVAILABILITY Se esse evento for considerado como tempo ocupado ou como tempo livre que pode ser reagendado.
GUESTS_CAN_MODIFY Se convidados podem modificar o evento.
GUESTS_CAN_INVITE_OTHERS Se convidados podem convidar outras pessoas.
GUESTS_CAN_SEE_GUESTS Se convidados podem ver a lista de participantes.

Adição de eventos

Quando o aplicativo insere um novo evento, recomenda-se usar um intent INSERT, como descrito em Uso de um intent para inserir um evento. Contudo, caso necessário, é possível inserir eventos diretamente. Esta seção descreve como fazê-lo.

Eis as regras para inserção de um novo evento:

Eis um exemplo de inserção de um evento: Para simplificar, isso está sendo realizado no encadeamento da IU. Na prática, inserções e atualizações devem ser feitas em um encadeamento assíncrono para mover a ação para um encadeamento de segundo plano. Para obter mais informações, consulte AsyncQueryHandler.

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
//
//

Observação: Veja como esse exemplo captura o ID do evento depois que o evento é criado. Esse é o modo mais fácil de obter um ID de evento. Muitas vezes, o ID do evento é necessário para realizar outras operações de agenda — por exemplo, adicionar participantes ou lembretes a um evento.

Atualização de eventos

Quando o aplicativo deseja permitir que o usuário edite um evento, é recomendável usar um intent EDIT, como descrito em Uso de um intent para editar um evento. Contudo, caso necessário, é possível editar eventos diretamente. Para atualizar um evento, é possível fornecer o _ID do evento como um ID anexado ao URI (withAppendedId()) ou como o primeiro item da seleção. A seleção deve iniciar com "_id=?", e o primeiro selectionArg deve ser o _ID do evento. Você também pode realizar atualizações usando uma seleção sem ID. Eis um exemplo de atualização de um evento. É possível mudar o título do evento usando a abordagem withAppendedId() :

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 = getContentResolver().update(updateUri, values, null, null);
Log.i(DEBUG_TAG, "Rows updated: " + rows);  

Exclusão de eventos

Pode-se excluir um evento tanto pelo _ID como um ID anexado ao URI quanto usando a seleção padrão. Ao usar um ID anexado, não é possível fazer seleções. Há duas versões de exclusão: como aplicativo e como adaptador de sincronização. A exclusão do aplicativo define a coluna deleted como 1. Esse sinalizador diz ao adaptador de sincronização que a linha foi excluída e que essa exclusão deve ser propagada para o servidor. A exclusão por um adaptador de sincronização remove o evento do banco de dados juntamente com todos os dados associados. Eis um exemplo de um aplicativo excluindo um evento pelo seu _ID:

private static final String DEBUG_TAG = "MyActivity";
...
long eventID = 201;
...
ContentResolver cr = getContentResolver();
ContentValues values = new ContentValues();
Uri deleteUri = null;
deleteUri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
int rows = getContentResolver().delete(deleteUri, null, null);
Log.i(DEBUG_TAG, "Rows deleted: " + rows);

Tabela de participantes

Cada linha da tabela CalendarContract.Attendees representa um único participante ou convidado de um evento. Chamar query() retorna uma lista de participantes para o evento com o EVENT_ID em questão. Esse EVENT_ID deve corresponder ao _ID de um determinado evento.

A tabela a seguir lista os campos graváveis. Ao inserir um novo participante, é necessário incluir todos eles exceto ATTENDEE_NAME.

Constante Descrição
EVENT_ID ID do evento.
ATTENDEE_NAME Nome do participante.
ATTENDEE_EMAIL Endereço de e-mail do participante.
ATTENDEE_RELATIONSHIP

A relação do participante com o evento. Pode ser:

ATTENDEE_TYPE

O tipo de participante. Pode ser:

ATTENDEE_STATUS

O status de participação do participante. Pode ser:

Adição de participantes

A seguir, há um exemplo que adiciona um único participante a um evento. Observe que EVENT_ID é obrigatório:

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);

Tabela de lembretes

Cada linha da tabela CalendarContract.Reminders representa um único lembrete de um evento. Chamar query() retorna uma lista de lembretes para o evento com o EVENT_ID em questão.

A tabela a seguir relaciona os campos graváveis de lembretes. Todos eles devem ser incluídos ao inserir um novo lembrete. Observe que adaptadores de sincronização especificam os tipos de lembretes compatíveis na tabela CalendarContract.Calendars. Consulte ALLOWED_REMINDERS para obter detalhes.

Constante Descrição
EVENT_ID ID do evento.
MINUTES Quantidade de minutos antes do evento o lembrete deve disparar.
METHOD

O método de alarme, como definido no servidor. Pode ser:

Adição de lembretes

Esse exemplo adiciona um lembrete para um evento. O lembrete dispara 15 minutos antes do evento.

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);

Tabela de instâncias

A tabela CalendarContract.Instances contém os horários de início e término das ocorrência de um evento. Cada linha nessa tabela representa uma única ocorrência do evento. A tabela de instâncias não é gravável e fornece somente um modo de consultar ocorrências de eventos.

A tabela a seguir relaciona alguns dos campos passíveis de consulta de uma instância. Observe que o fuso horário é definido por KEY_TIMEZONE_TYPE e KEY_TIMEZONE_INSTANCES.

Constante Descrição
BEGIN O horário de início da instância, em milissegundos UTC.
END O horário de término da instância, em milissegundos UTC.
END_DAY O dia final do calendário juliano da instância relativo ao fuso horário do Agenda.
END_MINUTE O minuto final da instância calculado a partir de meia-noite no fuso horário do Agenda.
EVENT_ID O _ID do evento para essa instância.
START_DAY O dia inicial do calendário juliano da instância relativo ao fuso horário do Agenda.
START_MINUTE O minuto inicial da instância calculado a partir de meia-noite, relativo ao fuso horário do Agenda.

Consulta na tabela de instâncias

Para consultar a tabela de instâncias, é necessário especificar um intervalo de tempo para a consulta na URI. Nesse exemplo, CalendarContract.Instances obtém acesso ao campo TITLE por meio da implementação da interface CalendarContract.EventsColumns. Em outras palavras, TITLE é retornado por uma vista do banco de dados, não por uma consulta à tabela de CalendarContract.Instances brutas.

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 do Agenda

O aplicativo não precisa de permissões para ler e gravar dados de agenda. Em vez disso, ele pode usar intents compatíveis com o aplicativo Agenda do Android para entregar operações de leitura e gravação. A tabela a seguir lista os intents compatíveis com o Provedor de Agenda.

Ação URI Descrição Extras

VIEW

content://com.android.calendar/time/<ms_since_epoch>

Você também pode consultar o URI com CalendarContract.CONTENT_URI. Para ver um exemplo de uso desse intent, consulte Uso de intents para exibir dados de calendário.
Abra o calendário no horário especificado por <ms_since_epoch>. Nenhum.

VIEW

content://com.android.calendar/events/<event_id>

Você também pode consultar o URI com Events.CONTENT_URI. Para ver um exemplo de uso desse intent, consulte Uso de intents para exibir dados de calendário.
Exibe o evento especificado por <event_id>. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

content://com.android.calendar/events/<event_id>

Você também pode consultar o URI com Events.CONTENT_URI. Para ver um exemplo de uso desse intent, consulte Uso de um intent para editar um evento.
Edita o evento especificado por <event_id>. CalendarContract.EXTRA_EVENT_BEGIN_TIME


CalendarContract.EXTRA_EVENT_END_TIME
EDIT

INSERT

content://com.android.calendar/events

Você também pode consultar o URI com Events.CONTENT_URI. Para ver um exemplo do uso desse intent, consulte Uso de um intent para inserir um evento.
Crie um evento. Qualquer um dos extras listados na tabela abaixo.

A tabela a seguir lista os extras de intent compatíveis com o Provedor de Agenda:

Extra de intent Descrição
Events.TITLE Nome do evento.
CalendarContract.EXTRA_EVENT_BEGIN_TIME Horário de início do evento em milissegundos desde a época.
CalendarContract.EXTRA_EVENT_END_TIME Horário de término do evento em milissegundos desde a época.
CalendarContract.EXTRA_EVENT_ALL_DAY Booleano que indica que um evento dura o dia inteiro. O valor pode ser true ou false.
Events.EVENT_LOCATION Local do evento.
Events.DESCRIPTION Descrição do evento.
Intent.EXTRA_EMAIL Lista com endereços de e-mail das pessoas a convidar, com termos separados por vírgula.
Events.RRULE A regra de recorrência do evento.
Events.ACCESS_LEVEL Se o evento é privado ou público.
Events.AVAILABILITY Se esse evento é considerado como tempo ocupado ou como tempo livre que pode ser reagendado.

As seções a seguir descrevem como usar estes intents.

Uso de um intent para inserir um evento

O intent INSERT permite que o aplicativo entregue a tarefa de inserção de eventos ao próprio Agenda. Com essa abordagem, o aplicativo não precisará ter a permissão WRITE_CALENDAR contida no arquivo de manifesto.

Quando usuários executam um aplicativo que usa essa abordagem, ele os direciona ao Agenda para finalizar a adição do evento. O intent INSERT usa campos extras para pré-preencher um formulário com os detalhes do evento no Agenda. Os usuários podem, então, cancelar o evento, editar o formulário conforme necessário ou salvar o evento na sua agenda.

A seguir, há um snippet de código que agenda um evento em 19 de janeiro de 2012, que acontece das 7h30 às 8h30. Observe o seguinte sobre esse snippet de código:

  • Ele especifica Events.CONTENT_URI como o URI.
  • Ele usa os campos extras {@linkandroid.provider.CalendarContract#EXTRA_EVENT_BEGIN_TIME CalendarContract.EXTRA_EVENT_BEGIN_TIME} e {@linkandroid.provider.CalendarContract#EXTRA_EVENT_END_TIME CalendarContract.EXTRA_EVENT_END_TIME} para pré-preencher o formulário com o horário do evento. Os valores desses horários devem estar em milissegundos UTC a partir da época.
  • Ele usa o campo extra Intent.EXTRA_EMAIL para fornecer uma lista de termos separados por vírgula de convidados, especificados por endereço de e-mail.
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);

Uso de um intent para editar um evento

É possível atualizar um evento diretamente, como descrito em Atualização de eventos. Porém, o uso do intent EDIT permite que um aplicativo sem permissão entregue a edição de eventos ao aplicativo Agenda. Quando os usuários finalizam a edição do evento no Agenda, são direcionados ao aplicativo original.

A seguir há um exemplo de um intent que define um novo título para o evento especificado e permite aos usuários editar o evento no Agenda.

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);

Uso de intents para exibir dados de agenda

O Provedor de Agenda oferece dois modos diferentes de usar o intent VIEW:

  • Para abrir o Agenda em uma data específica.
  • Para exibir um evento.

Eis há um exemplo que mostra como abrir o Agenda em uma data específica:

// 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);

Eis há um exemplo que mostra como abrir um evento para exibição:

long eventID = 208;
...
Uri uri = ContentUris.withAppendedId(Events.CONTENT_URI, eventID);
Intent intent = new Intent(Intent.ACTION_VIEW)
   .setData(uri);
startActivity(intent);

Adaptadores de sincronização

Há pequenas diferenças apenas nos modos de acesso ao Provedor de Agenda via aplicativo e via adaptador de sincronização:

  • Um adaptador de sincronização precisa especificar que é um adaptador de sincronização que define CALLER_IS_SYNCADAPTER como true.
  • Os adaptadores de sincronização precisam fornecer um ACCOUNT_NAME e um ACCOUNT_TYPE como parâmetros da consulta no URI.
  • Os adaptadores de sincronização têm acesso de gravação a mais colunas do que um aplicativo ou widget. Por exemplo, um aplicativo só pode modificar algumas características de uma agenda, como nome, nome de exibição, configurações de visibilidade e se a agenda está sincronizada. Por comparação, um adaptador de sincronização pode acessar não somente essas colunas, mas muitas outras, como cores da agenda, fuso horário, nível de acesso, local etc. No entanto, um adaptador de sincronização é restrito ao ACCOUNT_NAME e ao ACCOUNT_TYPE que especificou.

Eis um método auxiliar que pode ser usado para retornar uma URI para uso com um adaptador de sincronização:

 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();
 }

Para obter um exemplo de implementação de um adaptador de sincronização (não especificamente relacionado ao Agenda), consulte SampleSyncAdapter.